#!/usr/bin/perl use constant DATABASE => 'database'; use constant USERNAME => 'user'; use constant PASSWORD => 'pass'; use constant HOST => 'localhost'; use DBI; use Data::FormValidator; use strict; # The following is the "configurable" portion of this # script where templates, behaviour and subroutines can # be modified. It also incorporates the definitions of # mode_param, run_modes and start_mode which correspond # to the respective definitions within the # CGI::Application module - These definitions have been # included here so that the CGI::Application-inherited # class should only need to be edited for the # introduction of new behaviours and subroutines. my $app = Self->new( # File path of template files location 'TMPL_PATH' => '../templates', 'PARAMS' => { # Database handle if required - This can be any # name as the teardown routine will iterate # through all parameters and call disconnect on # DBI handles. 'dbh' => DBI->connect( "DBI:mysql:database=@{[ DATABASE ]};host=@{[ HOST ]}", USERNAME, PASSWORD ), # HTML templates which correspond to each run_mode 'html' => { '1' => 'stage1.tmpl', '2' => 'stage2.tmpl', '3' => 'stage3.tmpl', }, # See comments above - Of special note is the # fact that dispatch subroutines are defined by # their name rather than code references. Eg. # \&form_entry, \&form_submission - This # functionality requires CGI::Application version # 1.3 or greater (current version is 2.1). With # older versions of CGI::Application, code # references can still be employed however, the # full class name of the reference must be # employed because this definition is taking # place outside of the Self class where the # methods reside. Eg. \&Self::form_entry, # \&Self::form_submission. See PM node 137024 'mode_param' => 'stage', 'run_modes' => { 'AUTOLOAD' => 'form_entry', '1' => 'form_entry', '2' => 'form_entry', '3' => 'form_submission' }, 'start_mode' => '1', # The following parameter is a # Data::FormValidator (or HTML::FormValidator) # object which if defined is called for the # validation and vetting of parameters from each # run-mode - Note that if this is employed the # first run-mode (start_mode) must have a null- # hash assigned to it so that no validation is # performed (as presumably no information has as # yet been entered - This is to be addressed as # pre- and post-validation definitions) 'validator' => Data::FormValidator->new({ '1' => {}, '2' => { 'optional' => [ qw/ organisation / ], 'required' => [ qw/ email firstname lastname / ], 'constraints' => { 'email' => 'email', 'firstname' => '/^[\w\s\-]+$/', 'lastname' => '/^[\w\s\-]+$/' }, 'filters' => [ qw/ trim / ] } }) } ); $app->run; exit 0; # The following is an example CGI::Application-inherited # class employed by this script - The form-entry method # provides the multiple form display and validation while # the setup and teardown methods handle most of the # definition and cleanup work. The final database # handling would be incorporated into the form_submission # routine. package Self; use base qw/ CGI::Application /; use strict; sub setup { my $self = shift; # Maintain CGI::Application default parameters if # none provided $self->run_modes( $self->param('run_modes'} || { 'start' => 'dump_html' } ); $self->mode_param( $self->param('mode_param') || 'rm' ); $self->start_mode( $self->param('start_mode') || 'start' ); } sub teardown { my $self = shift; # DBI handle clean up - See PM node 136736 foreach my $param ($self->params()) { $self->param($param)->disconnect if ref $self->param($param) eq 'DBI'; } } sub form_entry { my $self = shift; my $cgi = $self->query; # The following definition of the mode_param is # required in cases where this method may be called # via the AUTOLOAD dispatch run mode. $cgi->param( -name => $self->param('mode_param'), -value => $self->param('start_mode') ) unless defined $cgi->param($self->param('mode_param')); # Although the default template module with # CGI::Application is HTML::Template, there is # nothing to prevent the use of Template Toolkit - # The easiest way is to initiate the Template object # in place of the CGI::Application/HTML::Template # load_tmpl method and returning the result of # $template->output( $file, $params ) in place of # $html->output. See PM node 142580. my $html = load_tmpl( $self->param('html')->{ $cgi->param($self->param('mode_param')) }, { 'die_on_bad_params' => 0 }); my %param = map { $_ => $cgi->param($_) } grep { !/$self->param('mode_param')/ } $cgi->param(); my ($error_missing, $error_invalid) = ($self->param('validator')->validate(\%param, $cgi->param($self->param('mode_param'))))[1,2]; if (scalar ( @{$error_missing}, @{$error_invalid} )) { # Custom error dispatch for invalid or missing # parameters can be incorporated here - Normally # I have an error HTML template which push a # sorted list of friendly names for the erroreous # form fields into. } $html->param( $_ => $cgi->param($_) ) foreach $cgi->param(); return $html->output; } sub form_submission { my $self = shift; # Database handling and processing of completed # submission information would reside in this # subroutine } 1; __END__