LoginRegisterCommercial SupportContact Us


POD documentation > Database Management > Form.pm

Form.pm

Generation of forms and inputs for database records and columns
posted on 2:36 PM, July 12, 2009


ExSite::Form - ExSite form management tools

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.


Form Processing

get_data() - fetch raw input

This method retrieves the form input and parses it (assuming it comes from input_record). It returns the total length of the input data.

get_action() - what are we supposed to do with this 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() - perform the requested action

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() - perform the do() tasks that directly touch the database

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.

do_update() - perform an automatic update from a form

In cases where do() decides to update the database, it does so by calling do_update().

do_insert() - perform an automatic insert from a form

In cases where do() decides to insert a record into the database, it does so by calling do_insert().

do_search() - perform an automatic search of a table

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(%data) - decode form data

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() - push new data onto the end of the form

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.


Form Validation

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() - validate form data

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($table,$datahash) - validate a datahash

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($table,$column,$datum) - validate a column value

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($type,$datum) - validate a data value

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.

validate_language($text,@forbidden) - validates that $text uses ``clean'' language

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.


Form Construction

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(%options) - build a completely self-contained form

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.

Typical Examples:

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)

make() options

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.

make_form_buttons()

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.

edit($table,$record,$hide,$show,$extra)

This is a wrapper for make() that generates a form to edit an existing record.

append($table,$record,$hide,$show,$extra)

This is a wrapper for make() that generates a form to insert a new record.

search_query($table,$hide,$show,$extra)

This is a wrapper for make() that generates a form to search a table.

input_record($opt) - make labels and input tags for a whole record

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.

input_column(%opt) - make the input tag(s) for a database column

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.

input_exsite(%opt) - make the input tag(s) for an ExSite datatype

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.

General Input Options:

datatype
the ExSite datatype of the input

name
the name of the input

value
the default value of the input

Datatype-specific Input Options:

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.

input_html(%opt) - generate a single HTML input tag

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:

use_wysiwyg() - check if the client supports WYSIWYG editing

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:

input_htmleditor(%opt) - place an HTML editor into a form

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}

Notes on using the HTML editor

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.

editor_javascript($section_id)

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.