Index
OVERALL
TASK: SEARCH FORM
TASK: SEARCH
TASK: CREATE
TASK: SHOW
TASK: EDIT
TASK: REMOVE
TASK: NOTIFY
TASK: WIZARD
TASK: WIZARD SEARCH
INTERNAL BEHAVIOR
BUGS
TO DO
SEE ALSO
COPYRIGHT
AUTHORS
NAME

OpenInteract::CommonHandler - Base class that with a few configuration items takes care of many common operations
SYNOPSIS

package MySite::Handler::MyTask;
use strict;
use OpenInteract::CommonHandler;
@MySite::Handler::MyTask::ISA = qw( OpenInteract::CommonHandler );
sub MY_PACKAGE { return 'mytask' }
sub MY_HANDLER_PATH { return '/MyTask' }
sub MY_OBJECT_TYPE { return 'myobject' }
sub MY_OBJECT_CLASS {
return OpenInteract::Request->instance->myobject
}
sub MY_SEARCH_FIELDS {
return qw( name type quantity purpose_in_life that_other.object_name )
}
sub MY_SEARCH_TABLE_LINKS { return ( that_other => 'myobject_id' ) }
sub MY_SEARCH_FORM_TITLE { return 'Search for Thingies' }
sub MY_SEARCH_FORM_TEMPLATE { return 'search_form' }
sub MY_SEARCH_RESULTS_TITLE { return 'Thingy Search Results' }
sub MY_SEARCH_RESULTS_TEMPLATE { return 'search_results' }
sub MY_OBJECT_FORM_TITLE { return 'Thingy Detail' }
sub MY_OBJECT_FORM_TEMPLATE { return 'form' }
sub MY_EDIT_RETURN_URL { return '/Thingy/search_form/' }
sub MY_EDIT_FIELDS {
return qw( myobject_id name type quantity purpose_in_life )
}
sub MY_EDIT_FIELDS_TOGGLED { return qw( is_indoctrinated ) }
sub MY_EDIT_FIELDS_DATE { return qw( birth_date ) }
sub MY_ALLOW_SEARCH_FORM { return 1 }
sub MY_ALLOW_SEARCH { return 1 }
sub MY_ALLOW_SHOW { return 1 }
sub MY_ALLOW_CREATE { return 1 }
sub MY_ALLOW_EDIT { return 1 }
sub MY_ALLOW_REMOVE { return undef }
sub MY_ALLOW_WIZARD { return undef }
sub MY_ALLOW_NOTIFY { return 1 }
# My date format is for users to type in 'yyyymmdd'
sub _read_field_date {
my ( $class, $apr, $field ) = @_;
my $date_value = $apr->param( $field );
$date_value =~ s/\D//g;
my ( $y, $m, $d ) = $date_value =~ /^(\d\d\d\d)(\d\d)(\d\d)$/;
return undef unless ( $y and $m and $d );
return join( '-', $y, $m, $d );
}
1;
DESCRIPTION

This class implements most of the common functionality required for
finding and displaying multiple objects, viewing a particular object,
making changes to it and removing it. And you just need to modify a
few configuration methods so that it knows what to save, where to save
it and what type of things you are doing.
This class is meant for the bread-and-butter of many web applications
-- enable a user to find, view and edit a particular object. Why keep
writing these parts again and again? And if you have more extensive
needs, it is very easy to still let this class do most of the work and
you can concentrate on the differences, making more maintainable code
and more sane programmers.
We break the process down into tasks, each task basically
corresponding to a particular URL class. (For instance,
'/MyApp/show/?myobject_id=4927' is a 'show' task that displays the
object with ID 4927.)
Every task allows you to customize an object, means for finding
objects or the parameters passed to the template. Each of these
methods take two arguments -- the first argument is always the class,
and the second is either the information (object, search criteria) to
be modified or a hashref of template parameters. (More detail below.)
In this documentation, we first list all the available tasks with a
brief description of what they do. Note that these are tasks
implemented for you, you are always free to create your own.
Next, we go into depth for each task and describe how you configure it
and how you can customize its behavior.
TASK METHODS

This class supplies the following methods for direct use as tasks. If
you override one, you need to supply content. You can, of course, add
your own methods (e.g., a 'summary()' method which displays the object
information in static detail along with related objects).
- search_form(): Display a search form.
- search(): Execute a search and display results.
- create(): Alias for
show() that displays an entry form for a
single record.
- show(): Display a single record.
- edit(): Modify a single record.
- remove(): Remove a single record.
- notify(): Email one or more objects in human-readable format.
- wizard(): Start the search wizard (generally display a search
criteria page).
- wizard_search(): Run the search wizard and display the results.
CUSTOMIZATION TYPES

- Template Customizations
These methods allow you to step in and modify any template parameters
that you like.
You can modify the template that any of these will use by setting the
parameter 'template_name'. If you set the template name yourself you
need to set it to a fully-qualified name, such as
'mypackage::mytemplate'.
- Data Customizations
These methods allow you to step in and modify the data being displayed
or processed. Read up on the specific customization method for the
exact parameters you can change and what is available to you.
OVERALL

These are configuration and customization items that are not specific
to a particular task.
Configuration
MY_PACKAGE() ($)
Name of this package.
MY_OBJECT_TYPE() ($)
Object type (e.g., 'user', 'news', etc.)
MY_HANDLER_PATH() ($) (optional)
Path of handler.
Default: '/' . MY_OBJECT_TYPE
MY_OBJECT_CLASS() ($) (optional)
Object class.
Default: Gets object class from $R using MY_OBJECT_TYPE:
Customizatiion
_fetch_object_customize( $object )
Called just before an object is returned via fetch_object(). You
have the option of looking at $object and making any necessary
modifications.
Note that fetch_object() is not called when returning objects from
a search, only when manipulating a single object with show(),
edit() or remove().

Configuration
MY_ALLOW_SEARCH_FORM() (bool) (optional)
Should the search form be viewed?
Default: true
MY_SEARCH_FORM_TITLE() ($) (optional)
Set the title for the search form.
Default: 'Search for Thingies'
MY_SEARCH_FORM_TEMPLATE() ($) (optional)
Name of the search form template.
Default: MY_PACKAGE . '::search_form'
Customization
_search_form_customize( \%template_params )
Template customization. Typically there are no parameters to
set/manipulate except possibly 'error_msg' or 'status_msg' if called
from other methods.
TASK: SEARCH

Configuration
MY_ALLOW_SEARCH() (bool) (optional)
Should searches be allowed?
Default: true
MY_SEARCH_FAIL_TASK() ($) (optional)
Task to run if your search fails. The parameter 'error_msg' will be
set to an appropriate message which you can display.
Default: search_form
MY_SEARCH_RESULTS_CAP() ($) (optional)
Constrains the max number of records returned. If this is set we run a
'count(*)' query using the search criteria before running the
search. If the result is greater than the number set here, we call
MY_SEARCH_RESULTS_CAP_FAIL_TASK with an error message set in the
'error_msg' parameter about the number of records that would have been
returned.
Note that this is a somewhat crude measure of the records returned
because it does not take into account security checks. That is, a
search that returns 500 records from the database could conceivably
return only 100 records after security checks. Keep this in mind when
setting the value.
Default: 0 (no cap)
MY_SEARCH_RESULTS_CAP_FAIL_TASK() ($) (optional)
Task to run in this class when a search exceeds the figure set in
MY_SEARCH_RESULTS_CAP. The task is run with a relevant message in
the 'error_msg' parameter.
Default: search_form
MY_SEARCH_RESULTS_PAGED() (bool) (optional)
Set to a true value to enable paged results, meaning that search
results will come back in groups of
MY_SEARCH_RESULTS_PAGE_SIZE. We
use the methods in 'results_manage' to accomplish this.
Note: If your objects are not retrievable through a single ID field,
you will not be able to page your results automatically. You should be
able to do this by hand in the future.
Default: false.
MY_SEARCH_RESULTS_PAGE_FIELD() ($) (optional)
If
MY_SEARCH_RESULTS_PAGED is true this is the parameter we will
check to see what page number of the results the user is requesting.
Default: 'pagenum'.
MY_SEARCH_RESULTS_PAGE_SIZE() ($) (optional)
If
MY_SEARCH_RESULTS_PAGED is set to a true value we output pages
of this size.
Default: 50
MY_SEARCH_RESULTS_KEY() ($) (optional)
If
MY_SEARCH_RESULTS_PAGED is true this routine will generate a key
under which you will save the ID to get your persisted search
results. We make the search ID accessible in the template parameters
under this name as well as 'search_id'.
Default:
MY_OBJECT_CLASS() . '_search_id'
MY_SEARCH_RESULTS_TITLE() ($) (optional)
Title of search results page.
Default: 'Search Results'
MY_SEARCH_RESULTS_TEMPLATE() ($) (optional)
Search results template name.
Default: 'search_results'
MY_SEARCH_FIELDS() (@) (optional)
List of fields used to build search. This can include fields from
other tables. Fields from other tables must be fully-qualified with
the table name.
For instance, for a list of fields used to find users, I might list:
sub MY_SEARCH_FIELDS { return qw( login_name last_name group.name ) }
Where 'group.name' is a field from another table. I would then have to
configure
MY_SEARCH_TABLE_LINKS (below) to tell CommonHandler how
to link my object with that table.
These are the actual parameters from the form used for searching. If
the names do not match up, such as if you fully-qualify your names in
the configuration but not the search form, then you will not get the
criteria you think you will. An obvious symptom of this is running a
search and getting many more records than you expected, maybe even all
of them.
No default.
MY_SEARCH_FIELDS_EXACT() (@) (optional)
Returns fields from
MY_SEARCH_FIELDS that must be an exact match.
This is used in
_search_build_where_clause(). If the field being
searched is an exact match, we use '=' as a search test.
Otherwise we use 'LIKE' and, if the field is not in
MY_SEARCH_FIELDS_LEFT_EXACT or
MY_SEARCH_FIELDS_RIGHT_EXACT (see
below), wrap the value in '%'.
If you need other custom behavior, do not include the field in
MY_SEARCH_FIELDS and use
_search_build_where_customize() to set.
No default.
MY_SEARCH_FIELDS_LEFT_EXACT() (@) (optional)
Returns fields from
MY_SEARCH_FIELDS that must match exactly on the
left-hand side. This sets up:
$fieldname LIKE "$fieldvalue%"
No default.
MY_SEARCH_FIELDS_RIGHT_EXACT() (@) (optional)
Returns fields from
MY_SEARCH_FIELDS that must match
exactly on the right-hand side. This sets up:
$fieldname LIKE "%$fieldvalue"
No default.
MY_SEARCH_TABLE_LINKS() (%) (optional)
Returns table name => ID field mapping used to build WHERE
clauses that JOIN multiple tables when executing a search.
A key is a table name, and the value enables us to build a join clause
to link table specified in the key to the table containing the object
being searched. The value is either a scalar or an arrayref.
If a scalar, the value is just the ID field in the destination table
that the ID value in the object maps to:
sub MY_SEARCH_TABLE_LINKS { return ( address => 'user_id' ) }
This means that the table 'address' contains the field 'user_id' which
the ID of our object matches.
If the value is an arrayref that means one of two things, depending on
the number of elements in the arrayref.
First, a two-element arrayref. This means we are have a non-key field
in our object which matches up with a key field in another object.
The elements are:
0: Fieldname in the object
1: Fieldname in the other table
(Frequently these are the same, but they do not have to be.)
For instance, say we have a table of people records and a table of
phone log records. Each phone log record has a 'person_id' field, but
we want to find all the phone log records generated by people who have
a last name with 'mith' in it.
sub MY_SEARCH_TABLE_LINKS {
return ( person => [ 'person_id', 'person_id' ] ) }
Which will generate a WHERE clause like:
WHERE person.last_name LIKE '%mith%'
AND phonelog.person_id = person.person_id
Second, a three-element arrayref. This means we are using a linking
table to do the join. The values of the arrayref are:
0: ID field matching the object ID field on the linking table
1: Name of the linking table
2: Name of the ID field on the destination table
So you could have the setup:
user (user_id) <--> user_group (user_id, group_id) <--> group (group_id)
and:
sub MY_SEARCH_TABLE_LINKS {
return ( group => [ 'user_id', 'user_group', 'group_id' ] ) }
And searching for a user by a group name with 'admin' would give:
WHERE group.name LIKE '%admin%'
AND group.group_id = user_group.group_id
AND user_group.user_id = user.user_id
No default.
MY_SEARCH_RESULTS_ORDER() ($) (optional)
An 'ORDER BY' clause used to order your results. The CommonHandler
makes sure to include the fields used to order the results in the
SELECT statement, since many databases will complain about their
absence.
No default.
MY_SEARCH_ADDITIONAL_PARAMS() (\%) (optional)
If you want to pass additional parameters directly to the SPOPS
fetch_iterator() call, return them here. For instance, if you want
to skip security for a particular search you would create:
sub MY_SEARCH_ADDITIONAL_PARAMS { return { skip_security => 1 } }
Default: An empty hashref (no parameters)
Customization
_search_customize( \%template_params )
Template customization. If you are not using paged results there is
only the parameter 'iterator' set. If you use paged results, then
there is 'iterator' as well as:
page_number_field
current_page
total_pages
total_hits
search_id
search_results_key
_search_criteria_customize( \%search_criteria )
Data customization. Modify the items in
\%search_criteria as
necessary. The format is simple: a key is a fully-qualified
(table.field) fieldname, and its value is either a scalar or arrayref
depending on whether multiple values were passed.
For instance, say we wanted to restrict searches to all objects with
an 'active' property of 'yes':
sub _search_criteria_customize {
my ( $class, $criteria ) = @_;
$criteria->{'mytable.active'} = 'yes';
}
Easy! Other possibilities include selecting objects based on qualities
of the user -- say certain objects should only be included in a search
if the user is a member of a particular group. Since
$R is
available to you, it is simple to check whether the user is a member
of a group and make necessary modifications.
Note that you must use the fully-qualified 'table.field' format for
the criteria key or the criterion will be discarded.
The method should always return the hashref of criteria. Failure to do
so will likely retrieve all objects in the database, which is
frequently a Bad Thing.
_search_build_where_customize( \@tables, \@where, \@values )
Data customization. Allows you to hand-modify the WHERE clause that
will be used for searching. If you override this method, you will be
passed three arguments:
- 1.
-
\@tables: An arrayref of tables that are used in the WHERE clause
-- they become the FROM clause of our search SELECT. If you add a JOIN
or other clause that depends on a separate table then be sure to add
it here -- otherwise the search will fail mightily.
- 2.
-
\@where: An arrayref of operations that will be joined together
with 'AND' before being passed to the search() method.
- 3.
-
\@values: An arrayref of values that will be plugged into the
operations.
This might seem a little confusing, but as usual it is easier to show
than tell. For example, we want to allow the user to select a date in
a search form and find all items one week after and one week before
that date:
sub _search_build_where_customize {
my ( $class, $table, $where, $value ) = @_;
my $R = OpenInteract::Request->instance;
my $search_date = $class->_read_field_date( 'pivot_date' );
push @{ $where },
"( TO_DAYS( ? ) BETWEEN ( TO_DAYS( pivot_date ) + 7 ) " .
"AND ( TO_DAYS( pivot_date ) - 7 ) )";
push @{ $value }, $search_date;
}
TASK: CREATE

This task is just an alias for show(), passing along a true value
for both the 'edit' and 'is_new_object' parameters, which show()
can inspect to do the right thing.
Configuration
MY_ALLOW_CREATE() (bool) (optional)
Should shortcut to display a form to create a new object be allowed?
Default: false
MY_OBJECT_CREATE_SECURITY() (security level) (optional)
Security required to create an object -- this should be a constant
from
SPOPS::Secure
Default: SEC_LEVEL_WRITE
Customization
None.
TASK: SHOW

Configuration
MY_ALLOW_SHOW() (bool) (optional)
Should object display be allowed?
Default: true
MY_SHOW_FAIL_TASK() ($) (optional)
If the display of the object fails -- cannot fetch it, object is not
active, etc. -- then what method should we run? Whatever method is run
should be able to display the error message (in 'error_msg') so the
user knows what happened.
Default: 'search_form'
MY_ACTIVE_CHECK() ($) (optional)
Should we check to see if the object is active before displaying it?
If true, the return value from this method should be the field to
check for a value of 'yes' or '1'.
If you do not want to check the 'active' status of an object, leave
this blank (the default).
Default: undef
MY_OBJECT_FORM_TITLE() ($) (optional)
Title of object editing page.
Default: 'Object Detail'
MY_OBJECT_FORM_TEMPLATE() ($) (optional)
Object form template name.
Default: 'object_form'
Customization
_show_customize( \%template_params )
Typically there are only the parameters 'object' and
MY_OBJECT_TYPE
set to the same value.
Note that this task does not differentiate between displaying an
object in an editable form and in a static (non-editable) display. If
you want to use this task to do both, you can use this customization
to set the template name based on the security status of the object.
For instance:
sub _show_customize {
my ( $class, $params ) = @_;
$params->{template_name} = ( $params->{object}{tmp_security_level} < SEC_LEVEL_WRITE )
? 'mypkg::static_display' : 'mypkg::form_display';
}
TASK: EDIT

Configuration
MY_ALLOW_EDIT() (bool) (optional)
Should edits be allowed?
Default: false
MY_EDIT_RETURN_URL() ($) (optional)
URL to use as return when displaying the 'edit' page. (If
you do not define this weird things can happen if users logout from
the editing page.)
Default: MY_HANDLER_PATH . '/'
MY_EDIT_FIELDS() (@) (optional)
Fields for CommonHandler to retrieve values from the form and set into
the object. You can set other values by hand using
_edit_customize().
You can also specify fields to be handled automatically by
CommonHandler in MY_EDIT_FIELDS_TOGGLED and MY_EDIT_FIELDS_DATE.
No default.
MY_EDIT_FIELDS_TOGGLED() (@) (optional)
List of fields that are either 'yes' or 'no'. If any true value (as
perl defines it) is read in then the value of the field is set to
'yes', otherwise it is set to 'no'.
No default
MY_EDIT_FIELDS_DATE() (@) (optional)
List of fields that are dates. If users are editing raw dates and the
field value does not need to be manipulated before entering the
database, then just keep such fields in MY_EDIT_FIELDS since they
do not need to be treated differently. The default is to read the date
from three separate fields, but you can override _read_field_date()
for your own needs.
No default
MY_EDIT_FAIL_TASK() ($) (optional)
Specify the task to run when the edit fails for any reason -- except
if you specify a different task to run when returning from
_edit_customize() with an error.
Default: 'search_form'
MY_EDIT_DISPLAY_TASK() ($) (optional)
Task we should execute after we have edited the record.
Default 'show' (re-displays the form you just edited with a status
message)
Customization
_edit_customize( $object, \%old_data )
Called just before an object is saved to the datastore. This is most
useful to perform any custom data retrieval, data manipulation or
validation. Data present in the object before any modifications is
passed as a hashref in the second argument.
Return value is a two-element list: the first is the status -- either
'OK' or 'ERROR' as exported by this module. The second is a hashref of
options whose contents depend on whether you return 'OK' or 'ERROR'.
If you return 'ERROR', thenthe options specify what to do next. If you
return 'OK', then the options get passed to the object
save() call,
which can be useful if for instance you need to tell SPOPS that a the
action is a creation even if it looks like an update.
Example. Data validation might look something like:
package My::Handler::MyHander;
use OpenInteract::CommonHandler qw( OK ERROR );
my %required_label = ( name => 'Name', quest => 'Quest',
favorite_color => 'Favorite Color' );
# ... Override the various configuration routines ...
sub _edit_customize {
my ( $class, $object, $old_data ) = @_;
my @msg = ();
foreach my $field ( keys %required_label ) {
if ( $object->{ $field } eq '' or ! defined $object->{ $field } ) {
push @msg, "$required_label{ $field } is a required field. " .
"Please enter data for it.";
}
}
return ( OK, undef ) unless ( scalar @msg );
return ( ERROR, { error_msg => join( "<br>\n", @msg ),
method => 'show' } );
}
So if any of the required fields are not filled in, the method returns
'ERROR' and a hashref with the method to execute on error, in this
case 'show' to redisplay the same object along with the error message
to display.
You can specify an action to execute in one of three ways:
- method: Calls
$method() in the current class.
- class, method: Calls
$class->$method().
- action: Calls the method and class specified by
$action.
TASK: REMOVE

Configuration
MY_ALLOW_REMOVE() (bool) (optional)
Should removals be allowed?
Default: false
MY_REMOVE_FAIL_TASK() ($) (optional)
Task to run if the remove fails for any reason.
Default: 'search_form'
MY_REMOVE_DISPLAY_TASK() ($) (optional)
Task to run after the remove completes
Default: 'search_form'
Customization
_remove_customize( $object )
Called just before an object is removed from the datastore.
TASK: NOTIFY

Configuration
MY_ALLOW_NOTIFY() (bool) (optional)
Should notify requests be fulfilled?
Default: false
MY_NOTIFY_FROM ($) (optional)
Address from which the message should come.
Default: 'admin_email' value from server configuration (see
OpenInteract::SPOPS for more info).
MY_NOTIFY_ID_FIELD() ($) (optional)
Specify the field used to grab ID values for objects to notify.
Default:
MY_OBJECT_CLASS()->id_field();
MY_NOTIFY_EMAIL_FIELD() ($) (optional)
Specify the field used for the address to which the notification
should be sent.
Default: 'email'
MY_NOTIFY_NOTES_FIELD() ($) (optional)
Specify the field used for notes that will be sent along with the
notification.
Default: 'notes'
MY_NOTIFY_SUBJECT() ($) (optional)
Subject of email to be sent out.
Default: "Object notification: $num_objects objects in mail"
Customization
_notify_customize( \%params )
Data customization. The
\%params hashref has the following keys you
can modify. All keys/values get sent on to the
notify() method of
OpenInteract::SPOPS:
- from_email: Address message is from (
MY_NOTIFY_FROM)
- email: Address message is to (value in
MY_NOTIFY_EMAIL_FIELD)
- subject: Subject of message (
MY_NOTIFY_SUBJECT)
- object: Object(s) fetched from specified IDs (values in
MY_NOTIFY_ID_FIELD)
- notes: Notes in message (value in
MY_NOTIFY_NOTES_FIELD)
- type: Type of object (
MY_OBJECT_TYPE)
TASK: WIZARD

This class contains some simple support for search wizards. With such
a wizard you can use OpenInteract in conjunction with JavaScript to
implement a 'Find...' widget so you can link one object to another
easily.
Configuration
MY_ALLOW_WIZARD() (bool) (optional)
Whether to enable the wizard.
Default: false
MY_WIZARD_FORM_TITLE() ($) (optional)
Title of wizard search form page.
Default: 'Wizard: Search'
MY_WIZARD_FORM_TEMPLATE() ($) (optional)
Name of wizard search form template.
Default: 'wizard_form'
Customization
_wizard_form_customize( \%params )
Template customization.
TASK: WIZARD SEARCH

Configuration
MY_ALLOW_WIZARD() (bool) (optional)
Whether to enable the wizard.
Default: false
MY_WIZARD_RESULTS_MAX() ($) (optional)
Max number of results to return.
Default: 50
MY_WIZARD_RESULTS_TITLE() ($) (optional)
Title of wizard search results page.
Default: 'Wizard: Results'
MY_WIZARD_RESULTS_TEMPLATE() ($) (optional)
Name of wizard search results template
Default: 'wizard_results'
Customization
_wizard_search_customize( \%params )
Template customization. Customize output of the search results.
INTERNAL BEHAVIOR

_search_build_criteria()
Scans the GET/POST for relevant (as specified by MY_SEARCH_FIELDS)
search criteria and puts them into a hashref. Multiple values are put
into an arrayref, single values into a scalar.
We call _search_criteria_customize() on the criteria just before
they are passed back to the caller.
Returns: Hashref of search fields and values entered.
_search_build_where_clause( \%search_criteria )
Builds a WHERE clause suitable for a SQL SELECT statement. It can
handle table links with configuration information available in
MY_SEARCH_TABLE_LINKS.
Returns: Three-value array: the first value is an arrayref of tables
used in the search, including the object table itself; the second
value is the actual WHERE clause, the third value is an arrayref of
the values used in the WHERE clause.
We call _search_build_where_customize() with the three arrayrefs
just before returning them.
_edit_assign_fields( $object )
If you override this method you will have to read all the information
from the GET/POST to the object. See below FIELD VALUE BEHAVIOR for
useful methods in doing this.
Object Retrieval
fetch_object( $id, [ $id_field, $id_field, ... ] )
This method is slightly different than the rest. It retrieves a
particular object for you, given either the ID value in $id or
given the ID value found in the first one of $id_field that is
defined in the GET/POST.
Returns: This method always returns an object. If it does not
return an object it will die(). If an object is not retrieved due
to an ID value not being found or a matching object not being found, a
new (empty) object is returned.
Depends on:
MY_OBJECT_CLASS
Field Values
_read_field( $apache_request, $field_name )
Just returns the value of $field_name as read from the GET/POST.
_read_field_toggled( $apache_request, $field_name )
If $field_name is set to a true value, returns 'yes', otherwise
returns 'no'.
_read_field_date( $apache_request, $field_name )
By default, reads in the value of $field_name which it assumes to
be in the format 'YYYYMMDD' and puts it into 'YYYY-MM-DD' format,
which it returns. This is probably the method you will most often
override, depending on how you present dates to your users.
BUGS

None known.
TO DO

GenericDispatcher items available thru methods
Modify the GenericDispatcher so that things like security information,
forbidden methods, etc. are available through class methods we can
override. We might hold off on this until we implement the
ActionDispatcher -- no reason to modify something we will
remove/modify soon anyway...
SEE ALSO

COPYRIGHT

Copyright (c) 2001-2002 intes.net, inc.. All rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
AUTHORS

Chris Winters <chris@cwinters.com>