- ExSite::Form - ExSite form management tools
- Form Processing
- Form Validation
- Form Construction
make(%options) - build a completely self-contained form
make_form_buttons()
edit($table,$record,$hide,$show,$extra)
append($table,$record,$hide,$show,$extra)
search_query($table,$hide,$show,$extra)
input_record($opt) - make labels and input tags for a whole record
input_column(%opt) - make the input tag(s) for a database column
input_exsite(%opt) - make the input tag(s) for an ExSite datatype
input_html(%opt) - generate a single HTML input tag
use_wysiwyg() - check if the client supports WYSIWYG editing
input_htmleditor(%opt) - place an HTML editor into a form
editor_javascript($section_id)
The Form class provides a variety of tools for composing HTML forms,
reading and parsing form input, and automatically performing standard
database operations (updates, inserts, searches) on forms that
correspond to database records.
There are two groups of methods in this class: (1) form processing
methods, and (2) form composition methods.
The form processing methods are mostly for processing forms that
represent database records; if these forms are built using the
input_record() method (below), then they can be automatically
processed (read, parsed, validated, and submitted to the database)
by Form methods. In other words, you do not need to write the
script that accepts the form data, in simple cases.
For instance, you can create a form as follows:
my $form = new ExSite::Form;
print $form->make({table=>"my_db_table",...});
This same form can be processed as follows:
$form->do;
Note that make() will automatically set the method, action, and
encoding type, so that no form processing code need be written.
Additionally, the Form class inherits from the Report, DB, and SQL
(or other database driver) classes, and includes all of their
functionality.
This method retrieves the form input and parses it (assuming it comes
from input_record). It returns the total length of the input data.
This method figures out what to do with the data, by either reading
the action field, or guessing based on the data. (Forms that specify
primary keys are presumed to be updates; otherwise they are presumed
to be inserts.)
Valid actions are ``insert'', ``update'', ``search''.
do() executes the action suggested by get_action().
First, however, it checks the submit_action, to make sure the user
didn't cancel the form. It also guesses a reasonable reply page, or
uses the reply argument provided by the form.
For updates and inserts, do performs a validation check on the form data,
by calling validate(). Any validation problems will prevent the
action from proceeding.
do_db() skips the control-flow logic of form processing (dealing with
cancels, determining the reply page, reporting results), and directly
invokes the db interaction methods. This is handy if a non-generic control
program is handling high-level form processing.
In cases where do() decides to update the database, it does so by
calling do_update().
In cases where do() decides to insert a record into the database,
it does so by calling do_insert().
In cases where do() decides to search a table in the database,
it does so by calling do_search(). Searches are done by looking
for records that contain all of the provided values (ie. there is an
impled logical AND of the fields); records are taken as matches if
they contain the provided values as substrings.
Parse does more than the usual URL-decoding of form data. It also:
The parsed data is returned in a hash with the following structure:
$formdata{TABLE}->{ROW}->{COLUMN} = VALUE
where ``ROW'' is the primary key value (record ID) of the row. For inserts
in which the primary key is not yet defined, the ROW is _ for single-record
inserts, or _n where n = 1,2,3,... for multi-record inserts.
If you rely on the Form class to automatically parse the form data, this
data structure will be stored in the Form object in $this-{form}>.
There are 2 methods for encoding the table/row information in the form:
Method 1 places hidden, encrypted table/record markers into the form data.
The markers are named "R[n]_mark" where [n] is some integer to identify
the record. All inputs beginning with "R[n]_[column]" are attached to that
record. This method is more secure because it is difficult to spoof invalid
table and record IDs. It also works better with Javascript.
Method 2 encodes the table and record directly into each input name:
table#record_id#column. The record_id can be null, or ``_'' for a
simple insert, or ``_[n]'' for multiple distinct inserts. This method
has some security concerns, since the table and record IDs could be
tampered with by an attacker. Exsite does attempt to trap such
tampering, but the security logic is simple, and may not be sufficient
for certain situations/applications. It is best avoid method 2 on
forms that are used by unauthenticated members of the general public.
The main advantage to Method 2 is that forms can easily be hand-coded.
formpush() is used to manually add new data items onto the form,
after the form data has already been parsed. This is typically used
by handlers and wizards to place extra data into the form after the
form has been submitted.
The new data is only added to the {form} attribute, not to the
raw form data, nor to the input object. It is always added to the
end of the form.
All of the validation routines return error messages (either single, or
an array) if invalid data is found, or undef/empty array if no invalid
data was detected.
Every datatype known to ExSite has its own validation regular expression.
Validation of inputs conists of comparing the input value to this regular
expression. ExSite determines the appropriate datatype to compare to
by looking up the table and column associated with the input field, in
the DBmap.
Additional validations that are performed incluide:
Note: The validation routines are automatically invoked by do().
Validate operates on the results of parse() that were stored in the
Form object. It determines the validity of all form data that was
entered, as well as detecting missing required data.
validate_record() validates the values in the passed $datahash,
returning an array of error messages for values that do not correspond
to the accepted values for the given column. It determines the
validity of all data present in the datahash, as well as detecting
missing required data. It can be called directly, without actually
processing a form.
The rules it follows are different depending on whether the record
is for an insert or an update; if the form action ($this-{action}>)
is not defined either way, an insert will be assumed, which is more
restrictive.
validate_column() validates a single value for a specific column in
the database. An error message is returned if the value does not
match expected values. undef is returned if the datum validates
correctly. It can be called directly, without actually processing a
form.
validate_datatype() checks that a data value conforms to the
allowed values for a datatype. It returns an error message if not, or
undef if valid. It can be called directly, without actually
processing a form.
If the wordfilter feature is enabled, this validation method will
be invoked automatically on any public text content (ie. all string,
text, and html columns that are readable at level 1 or lower).
If the wordfilter action is reject, then the validation routine
will throw validation errors if bad words are detected. For other
actions (censor and semi-censor), the text will be altered, and
warnings thown instead. Warnings will pass validation, but may still
generate messages on screen. If the user is of a sufficiently high
level (3 by default), their content is trusted, and always generates
warnings rather than errors.
validate_language() returns the (modified) text, plus a list of
error messages if validation has failed. For censoring actions, there
should be no errors (unless the wordfilter has not been configured
properly), while for non-censoring actions, the text should not be
modified. It is the caller's responsibility to replace the original
text with the modified text.
The list of forbidden words is taken from a config file, by default
conf/badwords.txt. If the wordfilter feature is turned off,
this method will do nothing using this dictionary of forbidden words.
However, you can still invoke this method directly for special cases,
and provide your own list of forbidden words after the text parameter.
The form construction methods are used to compose HTML forms that are
compatible with the form processing methods, above. Developers can
redirect these forms to their own processing methods, but by default
they will direct themselves to the automatic-processing methods.
make() builds forms for inserting or updating records into the
database, or for conducting searches on particular database tables.
By default, the form automatically sets its action so that it will
be automatically processed, executed, and the user will be returned
to an appropriate page when done.
Make a blank form to add a new record: $form->make(table=>$table_name)
Make a form to add a new record, prefilled with defaults : $form->make(table=>$table_name,data=>$datahash)
Make a form to update an existing record: $form->make(table=>$table_name,record=>$record_id)
Make a form to search a table: $form->make(table=>$table_name,search=>1)
- table
-
the table the form will be operating on. Optionally,
a reference to an array of table names may be given.
- record
-
the record ID of the record the form will be operating on.
If an array of table names was passed in
table, then a corresponding
array of record IDs should be passed here. This parameter can be left off
or set to undef for inserts.
- hide
-
ref to an array of column names that should be excluded
from the form.
- show
-
ref to an array of column names that should be shown on
the form. This defaults to all editable columns in the DBmap, but a
different list can be provided here to change the form presentation.
- extra
-
ref to a hash of additional keys/values that should
be included in the form (as hidden inputs). This is typically used to
include control directives such as a reply URL (key ``
reply'') to
go to after the form is processed.
- search
-
true/false flag indicating whether this form
should be processed as a table search operation. Searches return
generic reports of all matching records.
- action
-
the form action, ie. the URL to process the form input.
By default this is
doform.cgi, which simply executes the automatic
form processing methods detailed above. A custom form processing URL
can be specified here instead.
- method
-
the form method, ``POST'' by default.
- data
ref to a datahash containing presets/defaults for the form.
- debug
-
if true, directs the form to
debug.cgi, which simply
displays the form contents to the developer, without processing the data.
This generates standard submit, reset, and cancel buttons for a form.
It does not depend on make() and may be invoked by any form. Note
that ``Cancel'' submits the form, but sets the submit_method form
parameter to ``Cancel''. The form processing routine should check for
this value, before processing the form.
This is a wrapper for make() that generates a form to edit an
existing record.
This is a wrapper for make() that generates a form to insert a new record.
This is a wrapper for make() that generates a form to search a table.
Generates the input labels and tags corresponding to a database record.
$opt is a ref to an option hash:
table
-
the table the record belongs to
record
-
the record ID of the record (for updates)
data
-
preset default values (for inserts)
hide
-
ref to array of columns to NOT display
show
-
ref to array of columns to display
group
-
in some DBmaps, columns can have a group attribute,
allowing you to specify multiple columns with a single group identifier.
The
group parameters works like show, but for groups of columns.
input_record() includes security checks to determine whether the
user is permitted to read/write each field. The corresponding inputs
are not generated if the checks indicate otherwise.
Generates the HTML input tag(s) corresponding to a single database
column. %opt is an option hash (not a ref, as in input_record()).
The input label is not generated.
For some datatypes, a single column may result in multiple input
fields (eg. dates, which prompt for year, month, and day separately.)
In cases where multipart input fields are generated, ExSite appends
a part marker to the input field name, eg. input_name#part. It is
the responsibility of the decoding routines to patch these parts
back together into a single input value. The automatic form processing
tools above do this for you.
Options:
table
-
the table the value belongs to
column
-
the column the value belongs to
record
-
the record ID of the record the value belongs to (for updates)
value
-
the value of the column.
data
-
a datahash for the record, from which the
record and
value can be inferred, if not passed explicitly.
datatype
-
the datatype that should be used to determine the
input rules for this column. This defaults to the value indicated by
the DBmap, and is not normally required unless you want to override
the map.
size
-
the size of the allowed data, used to determine the
dimensions of the input field. This defaults to the value indicated by
the DBmap, and is not normally required unless you want to override
the map.
Note: no security checks are made on input_column(); if using this
routine to generate custom forms, you must decide for yourself
whether the user is allowed to alter the column in question.
Generates the HTML input tag(s) corresponding to an ExSite datatype.
This works similarly to input_column(), except that we have no
database data or DBmap metadata to tell us about the column, so we
have to provide values, datatypes, input sizes, and other values manually.
- datatype
-
the ExSite datatype of the input
- name
-
the name of the input
- value
-
the default value of the input
date/datetime
- null_date_type
-
``today'' or ``null'' (indicates how to preset date inputs,
if no preset is provided)
time/datetime
- minstep
-
minutes increment for minutes option menu (default is 15 minute increments)
set
- dummy
-
value to use for the dummy set indicator. This is a dummy
hidden input used to flag the presence of a set input. Set inputs are a
series of checkboxes, but if none are checked, the checkboxes do not appear
in the form data at all. This can make it difficult for the form processing
routines to determine whether a required set input was left blank, or if
it was not in the original form at all. The dummy set input is always
present, and tells the form processing code that checkboxes were present
even if none were checked.
foreign keys
- fmatch
-
match hash to select foreign keys to select from
- table
-
table this form is for
- column
-
the column in this table containing the foreign reference
- record
-
the id of the record containing the data being modified
- ftable
-
foreign table being referred to
encrypted fields
- table
-
table this form is for
- column
-
the column being encrypted
- record
-
the id of the record containing the encrypted value
Note: no security checks are made on input_exsite(); the form
processing routines are responsible for security validation of
the form data.
This method outputs the tags for a single HTML form input.
Options:
- name
-
the input field name
- type
-
the HTML input type (eg. text, radio, textarea, select, ...)
- value
-
the default preset input value
- size
-
the width of the input field
- readonly
-
prevent editing of the field, if true
- rows
-
height of a textarea input
- cols
-
width of a textarea input
- options
-
for selector inputs (radios, selects), an array of possible
input values, formatted as:
Returns a true/false result, depending on whether the client browser
identifies itself as one that supports the features of the ExSite HTML
editor. The following browsers are supported:
The editable content is specified as one of:
- table, record, column
-
a field in the database
- file
-
a path to a file on disk
- url
-
an external URL (this in no way implies that we can save over
the external URL)
Other Options:
- value
-
the HTML to edit
- name
-
the name of the input that will hold the HTML
- editor_height, editor_width
-
the dimensions (pixels) of the editor's IFRAME
- complete_html_content
-
if true, edits everything inside the
tags. Otherwise, edit everything inside the
tags.
- editor
-
ref to a hash of editor options to override those in
$config{htmleditor}
Only one instance of the editor may be used in a given form.
The editor downgrades to a simple textarea that edits raw HTML, if the
client does not support the necessary functionality.
The area you enter editor data into is really an IFRAME, not a form
input. Javascript tools are used to copy the contents of the IFRAME
into the first input field in the form, when the form is submitted.
The first input field of the form must therefore be a hidden input
field to receive the contents of the editor. This input field should
be flagged as containing HTML (ie. the name of the field should be
fieldname#html) if you want to benefit from more advanced CMS features
such as embedded images and dyanmic content. This is automatically set
up for you, if you use make(), but you may have to manually code it
on custom-built forms.
Returns the javascript that is needed to enable the HTML editor functions.
This is automatically invoked by input_htmleditor(), but may have to be
manually inserted into custom forms to enable the editor. The $section_id
argument is required by certain dialogs (link, image) if you want to
automatically fetch pages and images to work with.