+Fill in the blanks and get a ready made web application.
+
+This module is somewhat similar in spirit to CGI::Application,
+CGI::Path, and CGI::Builder and any other "CGI framework." As with
+the others, CGI::Ex::App tries to do as much of the mundane things, in
+a simple manner, without getting in the developer's way. However,
+there are various design patterns for CGI applications that
+CGI::Ex::App handles for you that the other frameworks require you to
+bring in extra support. The entire CGI::Ex suite has been taylored to
+work seamlessly together. Your mileage in building applications may
+vary.
+
+If you build applications that submit user information, validate it,
+re-display it, fill in forms, or separate logic into separate modules,
+then this module may be for you. If all you need is a dispatch
+engine, then this still may be for you. If all you want is to look at
+user passed information, then this may still be for you. If you like
+writing bare metal code, this could still be for you. If you don't want
+to write any code, this module will help - but you still need to
+provide your key actions and html.
+
+One of the great benefits of CGI::Ex::App vs. Catalyst or Rails style
+frameworks is that the model of CGI::Ex::App can be much more abstract.
+And models often are abstract.
+
+=head1 DEFAULT PROCESS FLOW
+
+The following pseudo-code describes the process flow
+of the CGI::Ex::App framework. Several portions of the flow
+are encapsulated in hooks which may be completely overridden to give
+different flow. All of the default actions are shown. It may look
+like a lot to follow, but if the process is broken down into the
+discrete operations of step iteration, data validation, and template
+printing the flow feels more natural.
+
+=head2 navigate
+
+The process starts off by calling ->navigate.
+
+ navigate {
+ eval {
+ ->pre_navigate
+ ->nav_loop
+ ->post_navigate
+ }
+ # dying errors will run the ->handle_error method
+
+ ->destroy
+ }
+
+=head2 nav_loop
+
+The nav_loop method will run as follows:
+
+ nav_loop {
+ ->path (get the array of path steps)
+ # ->path_info_map_base (method - map ENV PATH_INFO to form)
+ # look in ->form for ->step_key
+ # make sure step is in ->valid_steps (if defined)
+
+ ->pre_loop($path)
+ # navigation stops if true
+
+ foreach step of path {
+
+ ->morph
+ # check ->allow_morph
+ # check ->allow_nested_morph
+ # ->morph_package (hook - get the package to bless into)
+ # ->fixup_after_morph if morph_package exists
+ # if no package is found, process continues in current file
+
+ ->path_info_map (hook - map PATH_INFO to form)
+
+ ->run_step (hook)
+
+ ->refine_path (hook)
+ # only called if run_step returned false (page not printed)
+ ->next_step (hook) # find next step and add to path
+ ->set_ready_validate(0) (hook)
+
+ ->unmorph
+ # only called if morph worked
+ # ->fixup_before_unmorph if blessed to current package
+
+ # exit loop if ->run_step returned true (page printed)
+
+ } end of foreach step
+
+ ->post_loop
+ # navigation stops if true
+
+ ->default_step
+ ->insert_path (puts the default step into the path)
+ ->nav_loop (called again recursively)
+
+ } end of nav_loop
+
+=head2 run_step (hook)
+
+For each step of the path the following methods will be run
+during the run_step hook.
+
+ run_step {
+ ->pre_step (hook)
+ # exits nav_loop if true
+
+ ->skip (hook)
+ # skips this step if true (stays in nav_loop)
+
+ ->prepare (hook - defaults to true)
+
+ ->info_complete (hook - ran if prepare was true)
+ ->ready_validate (hook)
+ return false if ! ready_validate
+ ->validate (hook - uses CGI::Ex::Validate to validate form info)
+ ->hash_validation (hook)
+ ->file_val (hook)
+ ->base_dir_abs
+ ->base_dir_rel
+ ->name_module
+ ->name_step
+ ->ext_val
+ returns true if validate is true or if nothing to validate
+
+ ->finalize (hook - defaults to true - ran if prepare and info_complete were true)
+
+ if ! ->prepare || ! ->info_complete || ! ->finalize {
+ ->prepared_print
+ ->hash_base (hook)
+ ->hash_common (hook)
+ ->hash_form (hook)
+ ->hash_fill (hook)
+ ->hash_swap (hook)
+ ->hash_errors (hook)
+ # merge form, base, common, and fill into merged fill
+ # merge form, base, common, swap, and errors into merged swap
+ ->print (hook - passed current step, merged swap hash, and merged fill)
+ ->file_print (hook - uses base_dir_rel, name_module, name_step, ext_print)
+ ->swap_template (hook - processes the file with CGI::Ex::Template)
+ ->template_args (hook - passed to CGI::Ex::Template->new)
+ ->fill_template (hook - fills the any forms with CGI::Ex::Fill)
+ ->fill_args (hook - passed to CGI::Ex::Fill::fill)
+ ->print_out (hook - print headers and the content to STDOUT)
+
+ ->post_print (hook - used for anything after the print process)
+
+ # return true to exit from nav_loop
+ }
+
+ ->post_step (hook)
+ # exits nav_loop if true
+
+ } end of run_step
+
+It is important to learn the function and placement of each of the
+hooks in the process flow in order to make the most of CGI::Ex::App.
+It is enough to begin by learning a few common hooks - such as
+hash_validation, hash_swap, and finalize, and then learn about other
+hooks as needs arise. Sometimes, it is enough to simply override the
+run_step hook and take care of processing the entire step yourself.
+
+Because of the hook based system, and because CGI::Ex::App uses
+sensible defaults, it is very easy to override a little or a lot which
+ends up giving the developer a lot of flexibility.
+
+Additionally, it should be possible to use CGI::Ex::App with the other
+frameworks such as CGI::Application or CGI::Prototype. For these you
+could simple let each "runmode" call the run_step hook of CGI::Ex::App
+and you will instantly get all of the common process flow for free.
+
+=head1 MAPPING URI TO STEP
+
+The default out of the box configuration will map URIs to steps as follows:
+
+ # Assuming /cgi-bin/my_app is the program being run
+
+ URI: /cgi-bin/my_app
+ STEP: main
+ FORM: {}
+ WHY: No other information is passed. The path method is
+ called which eventually calls ->default_step which
+ defaults to "main"
+
+ URI: /cgi-bin/my_app?foo=bar
+ STEP: main
+ FORM: {foo => "bar"}
+ WHY: Same as previous example except that QUERY_STRING
+ information was passed and placed in form.
+
+ URI: /cgi-bin/my_app?step=my_step
+ STEP: my_step
+ FORM: {step => "my_step"}
+ WHY: The path method is called which looks in $self->form
+ for the key ->step_key (which defaults to "step").
+
+ URI: /cgi-bin/my_app?step=my_step&foo=bar
+ STEP: my_step
+ FORM: {foo => "bar", step => "my_step"}
+ WHY: Same as before but has other parameters were passed.
+
+ URI: /cgi-bin/my_app/my_step
+ STEP: my_step
+ FORM: {step => "my_step"}
+ WHY: The path method is called which called path_info_map_base
+ which matched $ENV{'PATH_INFO'} using the default regex
+ of qr{^/(\w+)$} and place the result in
+ $self->form->{$self->step_key}. Path then looks in
+ $self->form->{$self->step_key} for the initial step. See
+ the path_info_map_base method for more information.
+
+ URI: /cgi-bin/my_app/my_step?foo=bar
+ STEP: my_step
+ FORM: {foo => "bar", step => "my_step"}
+ WHY: Same as before but other parameters were passed.
+
+ URI: /cgi-bin/my_app/my_step?step=other_step
+ STEP: other_step
+ FORM: {step => "other_step"}
+ WHY: The same procedure took place, but when the PATH_INFO
+ string was matched, the form key "step" already existed
+ and was not replaced by the value from PATH_INFO.
+
+The remaining examples in this section are based on the assumption
+that the following method is installed in your script.
+
+ sub my_step_path_info_map {
+ return [
+ [qr{^/\w+/(\w+)/(\d+)$}, 'foo', 'id'],
+ [qr{^/\w+/(\w+)$}, 'foo'],
+ [qr{^/\w+/(.+)$}, 'anything_else'],
+ ];
+ }
+
+ URI: /cgi-bin/my_app/my_step/bar
+ STEP: my_step
+ FORM: {foo => "bar"}
+ WHY: The step was matched as in previous examples using
+ path_info_map_base. However, the form key "foo"
+ was set to "bar" because the second regex returned
+ by the path_info_map hook matched the PATH_INFO string
+ and the corresponding matched value was placed into
+ the form using the keys specified following the regex.
+
+ URI: /cgi-bin/my_app/my_step/bar/1234
+ STEP: my_step
+ FORM: {foo => "bar", id => "1234"}
+ WHY: Same as the previous example, except that the first
+ regex matched the string. The first regex had two
+ match groups and two form keys specified. Note that
+ it is important to order your match regexes in the
+ order that will match the most data. The third regex
+ would also match this PATH_INFO.
+
+ URI: /cgi-bin/my_app/my_step/some/other/type/of/data
+ STEP: my_step
+ FORM: {anything_else => 'some/other/type/of/data'}
+ WHY: Same as the previous example, except that the third
+ regex matched.
+
+ URI: /cgi-bin/my_app/my_step/bar?bling=blang
+ STEP: my_step
+ FORM: {foo => "bar", bling => "blang"}
+ WHY: Same as the first step, but additional QUERY_STRING
+ information was passed.
+
+ URI: /cgi-bin/my_app/my_step/one%20two?bar=three%20four
+ STEP: my_step
+ FORM: {anything_else => "one two", bar => "three four"}
+ WHY: The third path_info_map regex matched. Note that the
+ %20 in bar was unescaped by CGI::param, but the %20
+ in anything_else was unescaped by Apache. If you are
+ not using Apache, this behavior may vary. CGI::Ex::App
+ doesn't decode parameters mapped from PATH_INFO.
+
+See the path method for more information about finding the initial step
+of the path.
+
+The form method calls CGI::Ex::form which uses CGI::param to retrieve
+GET and POST parameters. See the form method for more information on
+how GET and POST parameters are parsed.
+
+See the path_info_map_base method, and path_info_map hook for more information
+on how the path_info maps function.
+
+Using the following code is very useful for determing what hooks have
+taken place:
+
+ use CGI::Ex::Dump qw(debug);
+
+ sub post_navigate {
+ my $self = shift;
+ debug $self->dump_history, $self->form;
+ }
+
+=head1 ADDING DATA VALIDATION TO A STEP
+
+CGI::Ex::App uses CGI::Ex::Validate for its data validation. See CGI::Ex::Validate
+for more information about the many ways you can validate your data.
+
+The default hash_validation hook returns an empty hashref. This means that passed
+in data is all valid and the script will automatically call the step's finalize method.
+
+The following shows how to some contrived validation to a step called "my_step".
+
+ sub my_step_hash_validation {
+ return {
+ username => {
+ required => 1,
+ match => 'm/^(\w+)$/',
+ match_error => 'The $field field may only contain word characters',
+ max_len => 20,
+ },
+ password => {
+ required => 1,
+ max_len => 15,
+ },
+ password_verify => {
+ validate_if => 'password',
+ equals => 'password',
+ },
+ usertype => {
+ required => 1,
+ enum => [qw(animal vegetable mineral)],
+ },
+ };
+ }
+
+The step will continue to display the html form until all of the fields pass
+validation.
+
+See the hash_validation hook and validate hook for more information about how
+this takes place.
+
+=head1 ADDING JAVASCRIPT DATA VALIDATION TO A STEP
+
+You must first provide a hash_validation hook as explained in the previous section.
+
+Once you have a hash_validation hook, you would place the following tags
+into your HTML template.
+
+ <form name="[% form_name %]" method="post">
+ ...
+ </form>
+ [% js_validation %]
+
+The "form_name" swap-in places a name on the form that the javascript returned by
+the js_validation swap-in will be able to find and check for validity.
+
+See the hash_validation, js_validation, and form_name hooks for more information.
+
+Also, CGI::Ex::validate.js allows for inline errors in addition to or in replacement
+of an alert message. To use inline errors, you must provide an element in your
+HTML document where this inline message can be placed. The common way to do it is as
+follows:
+
+ <input type="text" name="username"><br>
+ <span class="error" id="username_error">[% username_error %]</span>
+
+The span around the error allows for the error css class and it provides a location
+that the Javascript validation can populate with errors. The [% username_error %] provides
+a location for errors generated on the server side to be swapped in. If there was no error
+the [% username_error %] tag would default to "".
+
+=head1 ADDING ADDITIONAL TEMPLATE VARIABLES
+
+All variables returned by the hash_base, hash_common, hash_form, hash_swap, and
+hash_errors hooks are available for swapping in templates.
+
+The following shows how to add variables using the hash_swap hook on the step "main".
+
+ sub main_hash_swap {
+ return {
+ color => 'red',
+ choices => [qw(one two three)],
+ "warn" => sub { warn @_ },
+ };
+ }
+
+You could also return the fields from the hash_common hook and they would be available
+in both the template swapping as well as form filling.
+
+See the hash_base, hash_common, hash_form, hash_swap, hash_errors, swap_template, and
+template_args hooks for more information.
+
+The default template engine used is CGI::Ex::Template which is Template::Toolkit compatible.
+See the CGI::Ex::Template or Template::Toolkit documentation for the types of data
+that can be passed, and for the syntax that can be used.
+
+=head1 ADDING ADDITIONAL FORM FILL VARIABLES
+
+All variables returned by the hash_base, hash_common, hash_form, and hash_fill hooks
+are available for filling html fields in on templates.
+
+The following shows how to add variables using the hash_fill hook on the step "main".
+
+ sub main_hash_fill {
+ return {
+ color => 'red',
+ choices => [qw(one two three)],
+ };
+ }
+
+You could also return the fields from the hash_common hook and they would be available
+in both the form filling as well as in the template swapping.
+
+See the hash_base, hash_common, hash_form, hash_swap, hash_errors, fill_template, and
+fill_args hooks for more information.
+
+The default form filler is CGI::Ex::Fill which is similar to HTML::FillInForm but
+has several benefits. See the CGI::Ex::Fill module for the available options.
+
+=head1 FINDING TEMPLATES AND VALIDATION FILES
+
+CGI::Ex::App tries to help your applications use a good template directory layout, but allows
+for you to override everything.
+
+External template files are used for storing your html templates and
+for storing your validation files (if you use externally stored
+validation files).
+
+The default file_print hook will look for content on your file system,
+but it can also be completely overridden to return a reference to a
+scalar containing the contents of your file. Actually it can return
+anything that CGI::Ex::Template (Template::Toolkit compatible) will
+treat as input. This templated html is displayed to the user during
+any step that enters the "print" phase.
+
+Similarly the default file_val hook will look for a validation file on
+the file system, but it too can return a reference to a scalar
+containing the contents of a validation file. It may actually return
+anything that the CGI::Ex::Validate get_validation method is able to
+understand. This validation is used by the default "info_complete"
+method for verifying if the submitted information passes its specific
+checks. A more common way of inlining validation is to return a
+validation hash from a hash_validation hook override.
+
+If the default file_print and file_val hooks are used, the following methods
+are employed for finding templates and validation files on your filesystem (they
+are also documented more in the HOOKS AND METHODS section.
+
+=over 4
+
+=item base_dir_abs
+
+Absolute path or arrayref of paths to the base templates directory. Default "".
+
+=item base_dir_rel
+
+Relative path inside of the base_dir_abs directory where content can be found. Default "".
+
+=item name_module
+
+Directory inside of base_dir_rel where files for the current CGI (module) will be
+stored. Default value is $ENV{SCRIPT_NAME} with path and extension removed.
+
+=item name_step
+
+Used with ext_print and ext_val for creating the filename that will be looked for
+inside of the name_module directory. Default value is the current step.
+
+=item ext_print and ext_val
+
+Filename extensions added to name_step to create the filename looked for
+inside of the name_module directory. Default is "html" for ext_print and "val"
+for ext_val.
+
+=back
+
+It may be easier to understand the usage of each of these methods by showing
+a contrived example. The following is a hypothetical layout for your templates:
+
+ /home/user/templates/
+ /home/user/templates/chunks/
+ /home/user/templates/wrappers/
+ /home/user/templates/content/
+ /home/user/templates/content/my_app/
+ /home/user/templates/content/my_app/main.html
+ /home/user/templates/content/my_app/step1.html
+ /home/user/templates/content/my_app/step1.val
+ /home/user/templates/content/another_cgi/main.html
+
+In this example we would most likely set values as follows:
+
+ base_dir_abs /home/user/templates
+ base_dir_rel content
+ name_module my_app
+
+The name_module method defaults to the name of the running program, but
+with the path and extension removed. So if we were running
+/cgi-bin/my_app.pl, /cgi-bin/my_app, or /anypath/my_app, then
+name_module would default to "my_app" and we wouldn't have to
+hard code the value. Often it is wise to set the value anyway so
+that we can change the name of the cgi script without effecting
+where template content should be stored.
+
+Continuing with the example and assuming that name of the step that
+the user has requested is "step1" then the following values would be
+returned:
+
+ base_dir_abs /home/user/templates
+ base_dir_rel content
+ name_module my_app
+ name_step step1
+ ext_print html
+ ext_val val
+
+ file_print content/my_app/step1.html
+ file_val /home/user/templates/content/my_app/step1.val
+
+The call to the template engine would look something like
+the following:
+
+ my $t = $self->template_obj({
+ INCLUDE_PATH => $self->base_dir_abs,
+ });
+
+ $t->process($self->file_print($step), \%vars);