3 CGI::Ex::App - Anti-framework application framework.
7 Fill in the blanks and get a ready made web application. This module
8 is somewhat similar in spirit to CGI::Application, CGI::Path, and
9 CGI::Builder and any other "CGI framework." As with the others,
10 CGI::Ex::App tries to do as much of the mundane things, in a simple
11 manner, without getting in the developer's way. Your mileage may vary.
13 If you build applications that submit user information, validate it,
14 re-display it, fill in forms, or separate logic into separate modules,
15 then this module may be for you. If all you need is a dispatch
16 engine, then this still may be for you. If all want is to look at
17 user passed information, then this may still be for you. If you like
18 writing bare metal code, this could still be for you. If you don't want
19 to write any code, this module will help - but you still need to
20 provide you key actions.
23 =head1 SYNOPSIS (A LONG "SYNOPSIS")
25 More examples will come with time. Here are the basics for now.
26 This example script would most likely be in the form of a cgi, accessible via
27 the path http://yourhost.com/cgi-bin/my_app (or however you do CGIs on
28 your system. About the best way to get started is to paste the following
29 code into a cgi script (such as cgi-bin/my_app) and try it out. A detailed
30 walk-through follows in the next section. There is also a longer recipe
31 database example at the end of this document that covers other topics including
32 making your module a mod_perl handler.
34 ### File: /var/www/cgi-bin/my_app (depending upon Apache configuration)
35 ### --------------------------------------------
39 use base qw(CGI::Ex::App);
40 use CGI::Ex::Dump qw(debug);
42 __PACKAGE__->navigate;
44 # my $obj = __PACKAGE__->new;
49 ###------------------------------------------###
53 debug shift->dump_history;
56 sub main_hash_validation {
58 'general no_alert' => 1,
59 'general no_confirm' => 1,
60 'group order' => [qw(username password password2)],
66 match_error => 'You may only use letters and numbers.',
79 # reference to string means ref to content
80 # non-reference means filename
81 return \ "<h1>Main Step</h1>
82 <form method=post name=[% form_name %]>
83 <input type=hidden name=step>
86 <td><b>Username:</b></td>
87 <td><input type=text name=username><span style='color:red' id=username_error>[% username_error %]</span></td>
89 <td><b>Password:</b></td>
90 <td><input type=text name=password><span style='color:red' id=password_error>[% password_error %]</span></td>
92 <td><b>Verify Password:</b></td>
93 <td><input type=text name=password2><span style='color:red' id=password2_error>[% password2_error %]</span></td>
95 <tr><td colspan=2 align=right><input type=submit></td></tr>
105 if ($self->form->{'username'} eq 'bar') {
106 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
110 debug $self->form, "Do something useful with form here in the finalize hook.";
113 $self->add_to_swap({success_msg => "We did something"});
114 $self->append_path('success');
115 $self->set_ready_validate(0);
119 sub success_file_print {
120 \ "<div style=background:lightblue>
121 <h1>Success Step - [% success_msg %]</h1>
122 Username: <b>[% username %]</b><br>
123 Password: <b>[% password %]</b><br>
130 Note: This example would be considerably shorter if the html file
131 (file_print) and the validation file (file_val) had been placed in
132 separate files. Though CGI::Ex::App will work "out of the box" as
133 shown it is more probable that any platform using it will customize
134 the various hooks to their own tastes (for example, switching print to
135 use a templating system other than CGI::Ex::Template).
137 =head1 SYNOPSIS STEP BY STEP
139 This section goes step by step over the previous example.
141 Well - we start out with the customary CGI introduction.
146 use base qw(CGI::Ex::App);
147 use CGI::Ex::Dump qw(debug);
149 Note: the "use base" is not normally used in the "main" portion of a script.
150 It does allow us to just do __PACKAGE__->navigate.
152 Now we need to invoke the process:
154 __PACKAGE__->navigate;
156 # my $obj = __PACKAGE__->new;
160 Note: the "exit" isn't necessary - but it is kind of nice to infer
161 that program flow doesn't go beyond the ->navigate call.
163 The navigate routine is now going to try and "run" through a series of
164 steps. Navigate will call the ->path method which should return an
165 arrayref containing the valid steps. By default, if path method has
166 not been overridden, the path method will default first to the step
167 found in form key named ->step_name, then it will fall to the contents
168 of $ENV{'PATH_INFO'}. If navigation runs out of steps to run it will
169 run the step found in ->default_step which defaults to 'main'. So the
170 URI '/cgi-bin/my_app' would run the step 'main' first by default. The
171 URI '/cgi-bin/my_app?step=foo' would run the step 'foo' first. The
172 URI '/cgi-bin/my_app/bar' would run the step 'bar' first.
174 CGI::Ex::App allows for running steps in a preset path. The navigate
175 method will go through a step of the path at a time and see if it is
176 completed (various methods determine the definition of "completed").
177 This preset type of path can also be automated using the CGI::Path
178 module. Rather than using a preset path, CGI::Ex::App also has
179 methods that allow for dynamic changing of the path, so that each step
180 can determine which step to do next (see the jump, append_path,
181 insert_path, and replace_path methods).
183 During development it would be nice to see what happened during the
184 course of our navigation. This is stored in the arrayref contained in
185 ->history. There is a method that is called after all of the navigation
186 has taken place called "post_navigate". This chunk will display history after we
187 have printed the content.
190 debug shift->dump_history;
191 } # show what happened
193 Ok. Finally we are looking at the methods used by each step of the path. The
194 hook mechanism of CGI::Ex::App will look first for a method ${step}_${hook_name}
195 called before falling back to the method named $hook_name. Internally in the
196 code there is a call that looks like $self->run_hook('hash_validation', $step). In
197 this case the step is main. The dispatch mechanism finds our method at the following
200 sub main_hash_validation { ... }
202 The process flow will see if the data is ready to validate. Once it is ready
203 (usually when the user presses the submit button) the data will be validated. The
204 hash_validation hook is intended to describe the data and will be tested
205 using CGI::Ex::Validate. See the CGI::Ex::Validate perldoc for more
206 information about the many types of validation available.
208 sub main_file_print { ... }
210 The navigation process will see if user submitted information (the form)
211 is ready for validation. If not, or if validation fails, the step needs to
212 be printed. Eventually the file_print hook is called. This hook should
213 return either the filename of the template to be printed, or a reference
214 to the actual template content. In this example we return a reference
215 to the content to be printed (this is useful for prototyping applications
216 and is also fine in real world use - but generally production applications
217 use external html templates).
219 A few things to note about the template:
221 First, we add a hidden form field called step. This will be filled in
222 at a later point with the current step we are on.
224 We provide locations to swap in inline errors.
226 <span style="color:red" id="username_error">[% username_error %]</span>
228 As part of the error html we name each span with the name of the error. This
229 will allow for us to have Javascript update the error spots when the javascript
232 At the very end we add the TT variable [% js_validation %]. This swap in is
233 provided by the default hash_base hook and will provide for form data to be
234 validated using javascript.
236 Once the process flow has deemed that the data is validated, it then calls
237 the finalize hook. Finalize is where the bulk of operations should go.
238 We'll look at it more in depth.
242 my $form = $self->form;
244 At this point, all of the validated data is in the $form hashref.
246 if ($form->{'username'} eq 'bar') {
247 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
251 It is most likely that though the data is of the correct type and formatting,
252 it still isn't completely correct. This previous section shows a hard coded
253 test to see if the username was 'bar'. If it was then an appropriate error will
254 be set, the routine returns 0 and the run_step process knows that it needs to
255 redisplay the form page for this step. The username_error will be shown inline.
256 The program could do more complex things such as checking to see if the username
257 was already taken in a database.
259 debug $form, "Do something useful with form here in the finalize hook.";
261 This debug $form piece is simply a place holder. It is here that the program would
262 do something useful such as add the information to a database.
265 $self->add_to_swap({success_msg => "We did something"});
267 Now that we have finished finalize, we add a message that will be passed to the template
270 $self->append_path('success');
271 $self->set_ready_validate(0);
273 The program now needs to move on to the next step. In this case we want to
274 follow with a page that informs us we succeeded. So, we append a step named "success".
275 We also call set_ready_validate(0) to inform the navigation control that the
276 form is no longer ready to validate - which will cause the success page to
277 print without trying to validate the data. It is normally a good idea
278 to set this as leaving the engine in a "ready to validate" state can result
279 in an recursive loop (that will be caught).
284 We then return 1 which tells the engine that we completed this step successfully
285 and it needs to move on to the next step.
287 Finally we run the "success" step because we told it to. That step isn't
288 ready to validate so it prints out the template page.
290 For more of a real world example, it would be good to read the sample recipe db
291 application included at the end of this document.
293 =head1 DEFAULT PROGRAM FLOW
295 The following pseudo-code describes the process flow
296 of the CGI::Ex::App framework. Several portions of the flow
297 are encapsulated in hooks which may be completely overridden to give
298 different flow. All of the default actions are shown. It may look
299 like a lot to follow, but if the process is broken down into the
300 discrete operations of step iteration, data validation, and template
301 printing the flow feels more natural.
303 The process starts off by calling ->navigate.
311 # dying errors will run the ->handle_error method
314 The nav_loop method will run as follows:
317 ->path (get the array of path steps)
318 # look in $ENV{'PATH_INFO'}
319 # look in ->form for ->step_key
320 # make sure step is in ->valid_steps (if defined)
323 # navigation stops if true
325 foreach step of path {
328 # check ->allow_morph
329 # check ->allow_nested_morph
330 # ->morph_package (hook - get the package to bless into)
331 # ->fixup_after_morph if morph_package exists
332 # if no package is found, process continues in current file
337 # only called if morph worked
338 # ->fixup_before_unmorph if blessed to current package
340 # exit loop if ->run_step returned true (page printed)
342 } end of foreach step
345 # navigation stops if true
348 ->insert_path (puts the default step into the path)
349 ->nav_loop (called again recursively)
353 For each step of the path the following methods will be run
354 during the run_step hook.
358 # exits nav_loop if true
361 # skips this step if true (stays in nav_loop)
363 ->prepare (hook - defaults to true)
365 ->info_complete (hook - ran if prepare was true)
366 ->ready_validate (hook)
367 return false if ! ready_validate
368 ->validate (hook - uses CGI::Ex::Validate to validate form info)
369 ->hash_validation (hook)
376 returns true if validate is true or if nothing to validate
378 ->finalize (hook - defaults to true - ran if prepare and info_complete were true)
380 if ! ->prepare || ! ->info_complete || ! ->finalize {
388 # merge form, base, common, and fill into merged fill
389 # merge form, base, common, swap, and errors into merged swap
390 ->print (hook - passed current step, merged swap hash, and merged fill)
391 ->file_print (hook - uses base_dir_rel, name_module, name_step, ext_print)
392 ->swap_template (hook - processes the file with CGI::Ex::Template)
393 ->template_args (hook - passed to CGI::Ex::Template->new)
394 ->fill_template (hook - fills the any forms with CGI::Ex::Fill)
395 ->fill_args (hook - passed to CGI::Ex::Fill::fill)
396 ->print_out (hook - print headers and the content to STDOUT)
398 ->post_print (hook - used for anything after the print process)
400 # return true to exit from nav_loop
404 # exits nav_loop if true
408 It is important to learn the function and placement of each of the
409 hooks in the process flow in order to make the most of CGI::Ex::App.
410 It is enough to begin by learning a few common hooks - such as
411 hash_validation, hash_swap, and finalize, and then learn about other
412 hooks as needs arise. Sometimes, it is enough to simply override the
413 run_step hook and take care of processing the entire step yourself.
415 Because of the hook based system, and because CGI::Ex::App uses
416 sensible defaults, it is very easy to override a little or a lot which
417 ends up giving the developer a lot of flexibility.
419 Consequently, it should be possible to use CGI::Ex::App with the other
420 frameworks such as CGI::Application or CGI::Prototype. For these you
421 could simple let each "runmode" call the run_step hook of CGI::Ex::App
422 and you will instantly get all of the common process flow for free.
424 =head1 AVAILABLE METHODS / HOOKS
426 CGI::Ex::App's dispatch system works on the principles of hooks (which
427 are essentially glorified method lookups). When the run_hook method
428 is called, CGI::Ex::App will look for a corresponding method call for
429 that hook for the current step name. It is perhaps easier to show than
432 If we are calling the "print" hook for the step "edit" we would call
435 $self->run_hook('print', 'edit', $template, \%swap, \%fill);
437 This would first look for a method named "edit_print". If it is unable to
438 find a method by that name, it will look for a method named "print". If it
439 is unable to find this method - it will die.
441 If allow_morph is set to true, the same methods are searched for but it becomes
442 possible to move some of those methods into an external package.
444 See the discussions under the methods named "find_hook" and "run_hook" for more details.
446 The following is the alphabetical list of methods and hooks.
450 =item allow_morph (method)
452 Should return true if this step is allowed to "morph" the current App
453 object into another package. Default is false. It is passed a single
454 argument of the current step. For more granularity, if true value is
455 a hash, the step being morphed to must be in the hash.
457 To enable morphing for all steps, add the following:
459 sub allow_morph { 1 }
461 To enable morph on specific steps, do either of the following:
473 my ($self, $step) = @_;
474 return $step =~ /^(edit|delete)$/;
477 See the morph "hook" for more information.
479 =item allow_nested_morph (method)
481 Similar to the allow_morph hook, but allows for one more level of morphing.
482 This is useful in cases where the base class was morphed early on, or
483 if a step needs to call a sub-step but morph first.
485 See the allow_morph and the morph method for more information.
487 Should return a boolean value or hash of allowed steps - just as the
488 allow_morph method does.
490 =item append_path (method)
492 Arguments are the steps to append. Can be called any time. Adds more
493 steps to the end of the current path.
495 =item auth_args (method)
497 Should return a hashref that will be passed to the new method of CGI::Ex::Auth.
498 It is augmented with arguments that integrate it into CGI::Ex::App.
500 See the get_valid_auth method and the CGI::Ex::Auth documentation.
504 login_header => '<h1>My login header</h1>',
505 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
506 secure_hash_keys => [qw(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb ccccccccccccccccccccccc 2222222222222)],
507 # use_blowfish => 'my_blowfish_key',
511 =item auth_data (method)
513 Contains authentication data stored during the get_valid_auth method.
514 The data is normally blessed into the CGI::Ex::Auth::Data package which
515 evaluates to false if there was an error and true if the authentication
516 was successful - so this data can be defined but false.
518 See the get_valid_auth method.
520 =item cleanup_user (method)
522 Installed as a hook during get_valid_auth. Allows for cleaning
523 up the username. See the get_valid_auth method.
526 my ($self, $user) = @_;
530 =item current_step (method)
532 Returns the current step that the nav_loop is functioning on.
534 =item default_step (method)
536 Step to show if the path runs out of steps. Default value is the
537 'default_step' property which defaults to 'main'.
539 If nav_loop runs of the end of the path (runs out of steps), this
540 method is called, the step is added to the path, and nav_loop calls
543 =item dump_history (method)
545 Show simplified trace information of which steps were called, the
546 order they were called in, the time they took to run, and a brief list
547 of the output (to see the full response returned by each hook, pass a
548 true value as the only argument to dump_history -
549 $self->dump_history(1)). Indentation is also applied to show which
550 hooks called other hooks.
553 The first line shows the amount of time elapsed for the entire
554 navigate execution. Subsequent lines contain:
556 Step - the name of the current step.
557 Hook - the name of the hook being called.
558 Found - the name of the method that was found.
559 Time - the total elapsed seconds that method took to run.
560 Output - the response of the hook - shown in shortened form.
562 Note - to get full output responses - pass a true value to
563 dump_history - or just call ->history. Times displayed are to 5
564 decimal places - this accuracy can only be provided if the Time::HiRes
565 module is installed on your system (it will only be used if installed).
567 It is usually best to print this history during the post_navigate
568 method as in the following:
570 use CGI::Ex::Dump qw(debug);
571 sub post_navigate { debug shift->dump_history }
573 The following is a sample output of dump_history called from the
574 sample recipe application at the end of this document. The step
577 debug: admin/Recipe.pm line 14
578 shift->dump_history = [
580 "view - run_step - run_step - 0.00488 - 1",
581 " view - pre_step - pre_step - 0.00003 - 0",
582 " view - skip - view_skip - 0.00004 - 0",
583 " view - prepare - prepare - 0.00003 - 1",
584 " view - info_complete - info_complete - 0.00010 - 0",
585 " view - ready_validate - ready_validate - 0.00004 - 0",
586 " view - prepared_print - prepared_print - 0.00441 - 1",
587 " view - hash_base - hash_base - 0.00009 - HASH(0x84ea6ac)",
588 " view - hash_common - view_hash_common - 0.00148 - HASH(0x8310a20)",
589 " view - hash_form - hash_form - 0.00004 - HASH(0x84eaa78)",
590 " view - hash_fill - hash_fill - 0.00003 - {}",
591 " view - hash_swap - hash_swap - 0.00003 - {}",
592 " view - hash_errors - hash_errors - 0.00003 - {}",
593 " view - print - print - 0.00236 - 1",
594 " view - file_print - file_print - 0.00024 - recipe/view.html",
595 " view - name_module - name_module - 0.00007 - recipe",
596 " view - name_step - name_step - 0.00004 - view",
597 " view - swap_template - swap_template - 0.00161 - <html> ...",
598 " view - template_args - template_args - 0.00008 - HASH(0x865abf8)",
599 " view - fill_template - fill_template - 0.00018 - 1",
600 " view - fill_args - fill_args - 0.00003 - {}",
601 " view - print_out - print_out - 0.00015 - 1",
602 " view - post_print - post_print - 0.00003 - 0"
605 =item exit_nav_loop (method)
607 This method should not normally used but there is no problem with
608 using it on a regular basis. Essentially it is a "goto" that allows
609 for a long jump to the end of all nav_loops (even if they are
610 recursively nested). This effectively short circuits all remaining
611 hooks for the current and remaining steps. It is used to allow the
612 ->jump functionality. If the application has morphed, it will be
613 unmorphed before returning. Also - the post_navigate method will
616 =item first_step (method)
618 Returns the first step of the path. Note that first_step may not be the same
619 thing as default_step if the path was overridden.
623 Returns a hashref of the items passed to the CGI. Returns
624 $self->{form} which defaults to CGI::Ex::get_form.
626 =item handle_error (method)
628 If anything dies during execution, handle_error will be called with
629 the error that had happened. Default action is to die with that error.
631 =item history (method)
633 Returns an arrayref which contains trace history of which hooks of
634 which steps were ran. Useful for seeing what happened. In general -
635 each line of the history will show the current step, the hook
636 requested, and which hook was actually called.
638 The dump_history method shows a short condensed version of this
639 history which makes it easier to see what path was followed.
641 In general, the arrayref is free for anything to push onto which will
642 help in tracking other occurrences in the program as well.
646 Called by the default new method. Allows for any object
647 initilizations that may need to take place. Default action does
650 =item fill_args (hook)
652 Returns a hashref of args that will be passed to the CGI::Ex::Fill::fill.
653 It is augmented with the template to swap and the fill hash. This
654 could be useful if you needed to only swap a particular form on the template
655 page. Arguments are passed directly to the fill function.
657 sub fill_args { {target => 'my_form'} }
659 =item fill_template (hook)
661 Arguments are a template and a hashref. Takes the template that was
662 prepared using swap_template, and swaps html form fields using the
663 passed hashref. Overriding this method can control the fill behavior.
665 Calls the fill_args hook prior to calling CGI::Ex::Fill::fill
667 =item file_print (hook)
669 Returns a filename of the content to be used in the default print
670 hook. Adds method base_dir_rel to hook name_module, and name_step and
671 adds on the default file extension found in $self->ext_print which
672 defaults to the property $self->{ext_print} which will default to
673 ".html". Should return a filename relative to base_dir_abs that can be
674 swapped using CGI::Ex::Template, or should be a scalar reference to
675 the template content that can be swapped. This will be used by the
678 sub base_dir_abs { '/var/www/templates' }
679 sub base_dir_rel { 'content' }
680 sub name_module { 'recipe' }
681 sub ext_print { 'html' } # default
683 # ->file_print('this_step')
684 # would return 'content/recipe/this_step.html'
685 # the template engine would look in '/var/www/templates'
686 # for a file by that name
688 It may also return a reference to a string containing the html template.
689 This is useful for prototyping applications and/or keeping all of
690 the data for the application in a single location.
692 =item file_val (hook)
694 Returns a filename containing the validation. Performs the same
695 as file_print, but uses ext_val to get the extension, and it adds
696 base_dir_abs onto the returned value (file_print is relative to
697 base_dir_abs, while file_val is fully qualified with base_dir_abs)
699 The file should be readable by CGI::Ex::Validate::get_validation.
701 This hook is only necessary if the hash_validation hook has not been
704 This method an also return a hashref containing the validation - but
705 then you may have wanted to override the hash_validation hook.
707 =item finalize (hook)
709 Defaults to true. Used to do whatever needs to be done with the data once
710 prepare has returned true and info_complete has returned true. On failure
711 the print operations are ran. On success navigation moves on to the next
714 This is normally were there core logic of a script will occur (such as
715 adding to a database, or updating a record). At this point, the data
716 should be validated. It is possible to do additional validation
717 and return errors using code such as the following.
719 if (! $user_is_unique) {
720 $self->add_errors(username => 'The username was already used');
724 =item find_hook (method)
726 Called by run_hook. Arguments are a hook name, a step name. It
727 should return an arrayref containing the code_ref to run, and the
728 name of the method looked for. It uses ->can to find the appropriate
731 my $code = $self->hook('finalize', 'main');
732 ### will look first for $self->main_finalize;
733 ### will then look for $self->finalize;
735 This system is used to allow for multiple steps to be in the same
736 file and still allow for moving some steps out to external sub classed
737 packages (if desired).
739 If the application has successfully morphed via the morph method and
740 allow_morph then it is not necessary to add the step name to the
741 beginning of the method name as the morphed packages method will
742 override the base package (it is still OK to use the full method name
745 See the run_hook method and the morph method for more details.
747 =item forbidden_step (method)
749 Defaults to "__forbidden". The name of a step to run should the current
750 step name be invalid, or if a step found by the default path method
751 is invalid. See the path method.
753 =item form_name (hook)
755 Return the name of the form to attach the js validation to. Used by
758 =item get_pass_by_user (method)
760 This method is passed a username and the authentication object. It
761 should return the password for the given user. See the get_pass_by_user
762 method of CGI::Ex::Auth for more information. Installed as a hook
763 to the authentication object during the get_valid_auth method.
765 =item get_valid_auth (method)
767 If require_auth is true at either the application level or at the
768 step level, get_valid_auth will be called.
770 It will call auth_args to get some default args to pass to
771 CGI::Ex::Auth->new. It augments the args with sensible defaults that
772 App already provides (such as form, cookies, and template facilities).
773 It also installs hooks for the get_pass_by_user, cleanup_user, and verify_user
774 hooks of CGI::Ex::Auth.
776 It stores the $auth->last_auth_data in $self->auth_data for later use. For
777 example, to get the authenticated user:
779 sub require_auth { 1 }
782 my ($self, $user) = @_;
786 sub get_pass_by_user {
787 my ($self, $user) = @_;
788 my $pass = $self->some_method_to_get_the_pass($user);
794 login_header => '<h1>My login header</h1>',
795 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
801 my $user = $self->auth_data->{'user'};
802 return {user => $user};
805 Successful authentication is cached for the duration of the
806 nav_loop so multiple steps will run the full authentication routine
809 Full customization of the login process and the login template can
810 be done via the auth_args hash. See the auth_args method and
811 CGI::Ex::Auth perldoc for more information.
813 =item hash_base (hook)
815 A hash of base items to be merged with hash_form - such as pulldown
816 menus, javascript validation, etc. It will now also be merged with
817 hash_fill, so it can contain default fillins as well. It can be
818 populated by passing a hash to ->add_to_base. By default a sub
819 similar to the following is what is used for hash_common. Note the
820 use of values that are code refs - so that the js_validation and
821 form_name hooks are only called if requested:
824 my ($self, $step) = @_;
825 return $self->{hash_base} ||= {
826 script_name => $ENV{SCRIPT_NAME},
827 js_validation => sub { $self->run_hook('js_validation', $step) },
828 form_name => sub { $self->run_hook('form_name', $step) },
832 =item hash_common (hook)
834 Almost identical in function and purpose to hash_base. It is
835 intended that hash_base be used for common items used in various
836 scripts inheriting from a common CGI::Ex::App type parent. Hash_common
837 is more intended for step level populating of both swap and fill.
839 =item hash_errors (hook)
841 Called in preparation for print after failed prepare, info_complete,
842 or finalize. Should contain a hash of any errors that occurred. Will
843 be merged into hash_form before the pass to print. Each error that
844 occurred will be passed to method format_error before being added to
845 the hash. If an error has occurred, the default validate will
846 automatically add {has_errors =>1}. To the error hash at the time of
847 validation. has_errors will also be added during the merge in case the
848 default validate was not used. Can be populated by passing a hash to
849 ->add_to_errors or ->add_errors.
851 =item hash_fill (hook)
853 Called in preparation for print after failed prepare, info_complete,
854 or finalize. Should contain a hash of any items needed to be filled
855 into the html form during print. Items from hash_form, hash_base, and
856 hash_common will be layered together. Can be populated by passing a
857 hash to ->add_to_fill.
859 By default - forms are sticky and data from previous requests will try
860 and populate the form. You can use the fill_template hook to disable
861 templating on a single page or on all pages.
863 This method can be used to pre-populate the form as well (such as on an
864 edit step). If a form fails validation, hash_fill will also be called
865 and will only want the submitted form fields to be sticky. You can
866 use the ready_validate hook to prevent pre-population in these cases as
872 return {} if $self->run_hook('ready_validate', $step);
876 ### get previous values from the database
881 =item hash_form (hook)
883 Called in preparation for print after failed prepare, info_complete,
884 or finalize. Defaults to ->form. Can be populated by passing a hash
887 =item hash_swap (hook)
889 Called in preparation for print after failed prepare, info_complete,
890 or finalize. Should contain a hash of any items needed to be swapped
891 into the html during print. Will be merged with hash_base,
892 hash_common, hash_form, and hash_errors. Can be populated by passing
893 a hash to ->add_to_swap.
895 The hash will be passed as the second argument to swap_template.
897 =item hash_validation (hook)
899 Returns a hash of the validation information to check form against.
900 By default, will look for a filename using the hook file_val and will
901 pass it to CGI::Ex::Validate::get_validation. If no file_val is
902 returned or if the get_validation fails, an empty hash will be returned.
903 Validation is implemented by ->vob which loads a CGI::Ex::Validate object.
905 =item info_complete (hook)
907 Calls the ready_validate hook to see if data is ready to validate. If
908 so it calls the validate hook to validate the data. Should make
909 sure the data is ready and valid. Will not be run unless
910 prepare returns true (default).
912 =item insert_path (method)
914 Arguments are the steps to insert. Can be called any time. Inserts
915 the new steps at the current path location.
917 =item is_authed (method)
919 Returns true if the object has successful authentication data. It
920 returns false if the object has not been authenticated.
922 =item js_uri_path (method)
924 Return the URI path where the CGI/Ex/yaml_load.js and
925 CGI/Ex/validate.js files can be found. This will default to
926 "$ENV{SCRIPT_NAME}/js" if the path method has not been overridden,
927 otherwise it will default to "$ENV{SCRIPT_NAME}?step=js&js=" (the
928 latter is more friendly with overridden paths). A default handler for
929 the "js" step has been provided in "js_run_step" (this handler will
930 nicely print out the javascript found in the js files which are
931 included with this distribution. js_run_step will work properly with the
932 default "path" handler.
934 =item js_validation (hook)
936 Requires JSON or YAML. Will return Javascript that is capable of
937 validating the form. This is done using the capabilities of
938 CGI::Ex::Validate. This will call the hook hash_validation which will
939 then be encoded either json or into yaml and placed in a javascript
940 string. It will also call the hook form_name to determine which html
941 form to attach the validation to. The method js_uri_path is called to
942 determine the path to the appropriate validate.js files. If the
943 method ext_val is htm, then js_validation will return an empty string
944 as it assumes the htm file will take care of the validation itself.
945 In order to make use of js_validation, it must be added to the
946 variables returned by either the hash_base, hash_common, hash_swap or
947 hash_form hook (see examples of hash_base used in this doc).
949 By default it will try and use JSON first and then fail to YAML and
950 then will fail to returning an html comment that does nothing.
954 This method should not normally be used but is fine to use it on a
955 regular basis. It provides for moving to the next step at any point
956 during the nav_loop. It effectively short circuits the remaining
957 hooks for the current step. It does increment the recursion counter
958 (which has a limit of ->recurse_limit - default 15). It is normally
959 better to allow the other hooks in the loop to carry on their normal
960 functions and avoid jumping. (Essentially, this hook behaves like a
961 goto method to bypass everything else and continue at a different
962 location in the path - there are times when it is necessary or useful
965 Jump takes a single argument which is the location in the path to jump
966 to. This argument may be either a step name, the special strings
967 "FIRST, LAST, CURRENT, PREVIOUS, OR NEXT" or the number of steps to
968 jump forward (or backward) in the path. The default value, 1,
969 indicates that CGI::Ex::App should jump to the next step (the default
970 action for jump). A value of 0 would repeat the current step (watch
971 out for recursion). A value of -1 would jump to the previous step.
972 The special value of "LAST" will jump to the last step. The special
973 value of "FIRST" will jump back to the first step. In each of these
974 cases, the path array returned by ->path is modified to allow for the
975 jumping (the path is modified so that the path history is not destroyed
976 - if we were on step 3 and jumped to one, that path would contain
977 1, 2, 3, *1, 2, 3, 4, etc and we would be at the *).
979 ### goto previous step
980 $self->jump($self->previous_step);
981 $self->jump('PREVIOUS');
985 $self->jump($self->next_step);
990 ### goto current step (repeat)
991 $self->jump($self->current_step);
992 $self->jump('CURRENT');
996 $self->jump($self->last_step);
1000 $self->jump($self->first_step);
1001 $self->jump('FIRST');
1003 =item last_step (method)
1005 Returns the last step of the path. Can be used to jump to the last step.
1007 =item morph (method)
1009 Allows for temporarily "becoming" another object type for the
1010 execution of the current step. This allows for separating some steps
1011 out into their own packages.
1013 Morph will only run if the method allow_morph returns true.
1014 Additionally if the allow_morph returns a hash ref, morph will only
1015 run if the step being morphed to is in the hash. Morph also passes
1016 the step name to allow_morph.
1018 The morph call occurs at the beginning of the step loop. A
1019 corresponding unmorph call occurs before the loop is exited. An
1020 object can morph several levels deep if allow_nested_morph returns
1021 true. For example, an object running as Foo::Bar that is looping on
1022 the step "my_step" that has allow_morph = 1, will do the following:
1024 Call the morph_package hook (which would default to returning
1025 Foo::Bar::MyStep in this case)
1027 Translate this to a package filename (Foo/Bar/MyStep.pm) and try
1028 and require it, if the file can be required, the object is blessed
1031 Call the fixup_after_morph method.
1033 Continue on with the run_step for the current step.
1035 At any exit point of the loop, the unmorph call is made which
1036 re-blesses the object into the original package.
1038 Samples of allowing morph:
1040 sub allow_morph { 1 }
1042 sub allow_morph { {edit => 1} }
1044 sub allow_morph { my ($self, $step) = @_; return $step eq 'edit' }
1046 It is possible to call morph earlier on in the program. An example of
1047 a useful early use of morph would be as in the following code:
1049 sub allow_morph { 1 }
1053 if ($ENV{'PATH_INFO'} && $ENV{'PATH_INFO'} =~ s|^/(\w+)||) {
1055 $self->morph($step);
1056 $ENV{'PATH_INFO'} = "/$step";
1057 $self->stash->{'base_morphed'} = 1;
1064 $self->unmorph if $self->stash->{'base_morphed'};
1067 If this code was in a module Base.pm and the cgi running was cgi/base
1072 and you created a sub module that inherited Base.pm called
1073 Base/Ball.pm -- you could then access it using cgi/base/ball. You
1074 would be able to pass it steps using either cgi/base/ball/step_name or
1075 cgi/base/ball?step=step_name - Or Base/Ball.pm could implement its
1076 own path. It should be noted that if you do an early morph, it is
1077 suggested to provide a call to unmorph. And if you want to let your
1078 early morphed object morph again - you will need to provide
1080 sub allow_nested_morph { 1 }
1082 With allow_nested_morph enabled you could create the file
1083 Base/Ball/StepName.pm which inherits Base/Ball.pm. The Base.pm, with
1084 the custom init and default path method, would automatically morph us
1085 first into a Base::Ball object (during init) and then into a
1086 Base::Ball::StepName object (during the navigation loop).
1088 Since it is complicated to explain - it may be a bit complicated to
1089 those who will try to follow your code later. CGI::Ex::App provides
1090 many ways to do things, but use the best one for your situation.
1092 =item morph_package (hook)
1094 Used by morph. Return the package name to morph into during a morph
1095 call. Defaults to using the current object type as a base. For
1096 example, if the current object running is a Foo::Bar object and the
1097 step running is my_step, then morph_package will return
1100 Because of the way that run_hook works, it is possible that several
1101 steps could be located in the same external file and overriding morph_package
1102 could allow for this to happen.
1104 See the morph method.
1106 =item name_module (hook)
1108 Return the name (relative path) that should be pre-pended to name_step
1109 during the default file_print and file_val lookups. Defaults to
1110 the value in $self->{name_module} which in turn defaults to the name
1111 of the current script.
1113 cgi-bin/my_app.pl => my_app
1114 cgi/my_app => my_app
1116 This method is provided so that each cgi or mod_perl application can
1117 have its own directory for storing html for its steps.
1119 See the file_print method for more information.
1121 =item name_step (hook)
1123 Return the step (appended to name_module) that should used when
1124 looking up the file in file_print and file_val lookups. Defaults to
1127 =item nav_loop (method)
1129 This is the main loop runner. It figures out the current path
1130 and runs all of the appropriate hooks for each step of the path. If
1131 nav_loop runs out of steps to run (which happens if no path is set, or if
1132 all other steps run successfully), it will insert the ->default_step into
1133 the path and run nav_loop again (recursively). This way a step is always
1134 assured to run. There is a method ->recurse_limit (default 15) that
1135 will catch logic errors (such as inadvertently running the same
1136 step over and over and over because there is either no hash_validation,
1137 or the data is valid but the set_ready_validate(0) method was not called).
1139 =item navigate (method)
1141 Takes a class name or a CGI::Ex::App object as arguments. If a class
1142 name is given it will call the "new" method to instantiate an object
1143 by that class (passing any extra arguments to the new method). All
1144 returns from navigate will return the object.
1146 The method navigate is essentially a safe wrapper around the ->nav_loop
1147 method. It will catch any dies and pass them to ->handle_error.
1149 This starts the process flow for the path and its steps.
1151 =item navigate_authenticated (method)
1153 Same as the method navigate but sets require_auth(1) before
1154 running. See the require_auth method.
1156 =item new (class method)
1158 Object creator. Takes a hashref of arguments that will become the
1159 initial properties of the object. Calls the init method once the
1160 object has been blessed to allow for any other initilizations.
1162 my $app = MyApp->new({name_module => 'my_app'});
1164 =item next_step (method)
1166 Returns the next step in the path. If there is no next step, it
1167 returns the default_step.
1171 Return an arrayref (modifiable) of the steps in the path. For each
1172 step the run_step hook and all of its remaining hooks will be run.
1174 Hook methods are looked up and ran using the method "run_hook" which
1175 uses the method "find_hook" to lookup the hook. A history of ran
1176 hooks is stored in the array ref returned by $self->history.
1178 If path has not been defined, the method will look first in the form
1179 for a key by the name found in ->step_key. It will then look in
1180 $ENV{'PATH_INFO'}. It will use this step to create a path with that
1181 one step as its contents. If a step is passed in via either of these
1182 ways, the method will call valid_steps to make sure that the step
1183 is valid (by default valid_steps returns undef - which means that
1184 any step is valid). Any step beginning with _ can not be passed in
1185 and are intended for use on private paths. If a non-valid step is
1186 found, then path will be set to contain a single step of ->forbidden_step.
1188 For the best functionality, the arrayref returned should be the same
1189 reference returned for every call to path - this ensures that other
1190 methods can add to the path (and will most likely break if the
1191 arrayref is not the same).
1193 If navigation runs out of steps to run, the default step found in
1194 default_step will be run. This is what allows for us to default
1195 to the "main" step for many applications.
1197 =item post_loop (method)
1199 Ran after all of the steps in the loop have been processed (if
1200 prepare, info_complete, and finalize were true for each of the steps).
1201 If it returns a true value the navigation loop will be aborted. If it
1202 does not return true, navigation continues by then inserting the step
1203 $self->default_step and running $self->nav_loop again (recurses) to
1204 fall back to the default step.
1206 =item post_navigate (method)
1208 Called from within navigate. Called after the nav_loop has finished
1209 running but within the eval block to catch errors. Will only run if
1210 there were no errors which died during the nav_loop process.
1212 It can be disabled from running by setting the _no_post_navigate
1215 If per-step authentication is enabled and authentication fails,
1216 the post_navigate method will still be called (the post_navigate
1217 method can check the ->is_authed method to change behavior). If
1218 application level authentication is enabled and authentication
1219 fails, none of the pre_navigate, nav_loop, or post_navigate methods
1222 =item post_print (hook)
1224 A hook which occurs after the printing has taken place. Is only run
1225 if the information was not complete. Useful for cases such as
1226 printing rows of a database query after displaying a query form.
1228 =item post_step (hook)
1230 Ran at the end of the step's loop if prepare, info_complete, and
1231 finalize all returned true. Allows for cleanup. If a true value is
1232 returned, execution of navigate is returned and no more steps are
1235 =item pre_loop (method)
1237 Called right before the navigation loop is started (at the beginning
1238 of nav_loop). At this point the path is set (but could be modified).
1239 The only argument is a reference to the path array. If it returns a
1240 true value - the navigation routine is aborted.
1242 =item pre_navigate (method)
1244 Called at the very beginning of the navigate method, but within the
1245 eval block to catch errors. Called before the nav_loop method is
1246 started. If a true value is returned then navigation is skipped (the
1247 nav_loop is never started).
1249 =item pre_step (hook)
1251 Ran at the beginning of the loop before prepare, info_compelete, and
1252 finalize are called. If it returns true, execution of nav_loop is
1253 returned and no more steps are processed..
1255 =item prepare (hook)
1257 Defaults to true. A hook before checking if the info_complete is true.
1258 Intended to be used to cleanup the form data.
1260 =item prepared_print (hook)
1262 Called when any of prepare, info_complete, or finalize fail. Prepares
1263 a form hash and a fill hash to pass to print. The form hash is primarily
1264 intended for use by the templating system. The fill hash is intended
1265 to be used to fill in any html forms.
1267 =item previous_step (method)
1269 List the step previous to this one. Will return '' if there is no previous step.
1273 Take the information generated by prepared_print, format it, and print it out.
1274 Default incarnation uses CGI::Ex::Template which is compatible with
1275 Template::Toolkit. Arguments are: step name (used to call the
1276 file_print hook), swap hashref (passed to call swap_template), and
1277 fill hashref (passed to fill_template).
1279 During the print call, the file_print hook is called which should
1280 return a filename or a scalar reference to the template content is
1282 =item ready_validate (hook)
1284 Should return true if enough information is present to run validate.
1285 Default is to look if $ENV{'REQUEST_METHOD'} is 'POST'. A common
1286 usage is to pass a common flag in the form such as 'processing' => 1
1287 and check for its presence - such as the following:
1289 sub ready_validate { shift->form->{'processing'} }
1291 Changing the behavior of ready_validate can help in making wizard type
1294 =item recurse_limit (method)
1296 Default 15. Maximum number of times to allow nav_loop to call itself.
1297 The recurse level will increase every time that ->jump is called, or if
1298 the end of the nav_loop is reached and the process tries to add the
1299 default_step and run it again.
1301 If ->jump is used often - the recurse_limit will be reached more
1302 quickly. It is safe to raise this as high as is necessary - so long
1303 as it is intentional.
1305 Often the limit is reached if a step did not have a validation hash,
1306 or if the set_ready_validate(0) method was not called once the data
1307 had been successfully validated and acted upon.
1309 =item replace_path (method)
1311 Arguments are the steps used to replace. Can be called any time.
1312 Replaces the remaining steps (if any) of the current path.
1314 =item require_auth (method)
1316 Default undef. Can return either a true value or a hashref of step names.
1318 If a hashref of stepnames is returned, authentication will be turned on
1319 at the step level. In this mode if any step is accessed, the get_valid_auth
1320 method will be called. If it fails, then the nav_loop will be stopped
1321 (the post_navigate method will be called - use the is_authed method to perform
1322 different functions). Any step of the path not in the hash will not require
1323 authentication. For example, to add authentication to add authentication
1324 to the add, edit and delete steps you could do:
1326 sub require_auth { {add => 1, edit => 1, delete => 1} }
1328 If a non-hash true value is returned from the require_auth method then
1329 authentication will take place before the pre_navigation or the nav_loop methods.
1330 If authentication fails the navigation process is exited (the post_navigate
1331 method will not be called).
1333 sub require_auth { 1 }
1335 Alternatively you can also could do either of the following:
1337 __PACKAGE__->navigate_authenticated; # instead of __PACKAGE__->navigate;
1341 sub init { shift->require_auth(1) }
1345 __PACKAGE__->new({require_auth => 1}->navigate;
1347 If get_valid_auth returns true, in either case, the is_authed method will
1348 return true and the auth_data will contain the authenticated user's data.
1349 If it returns false, auth_data may possibly contain a defined but false
1350 data object with details as to why authentication failed.
1352 See the get_valid_auth method.
1354 =item run_hook (method)
1356 Arguments are a hook name and the step to find the hook for. Calls
1357 the find_hook method to get a code ref which it then calls and returns
1358 the result passing any extra arguments to run_hook as arguments to the
1361 Each call to run_hook is logged in the arrayref returned by the
1362 history method. This information is summarized in the dump_history
1363 method and is useful for tracing the flow of the program.
1365 The run_hook method is part of the core of CGI::Ex::App. It allows
1366 for an intermediate layer in normal method calls. Because of
1367 run_hook, it is possible to logically override methods on a step by
1368 step basis, or override a method for all of the steps, or even to
1369 break code out into separate modules.
1371 =item run_step (hook)
1373 Runs all of the hooks specific to each step, beginning with pre_step
1374 and ending with post_step (for a full listing of steps, see the
1375 section on process flow). Called after ->morph($step) has been run.
1376 If this hook returns true, the nav_loop is exited (meaning the
1377 run_step hook displayed a printed page). If it returns false, the
1378 nav_loop continues on to run the next step.
1380 This hook performs the same base functionality as a method defined in
1381 CGI::Applications ->run_modes. The default run_step method provides
1382 much more granular control over the flow of the CGI.
1384 =item set_path (method)
1386 Arguments are the steps to set. Should be called before navigation
1387 begins. This will set the path arrayref to the passed steps.
1389 This method is not normally used.
1391 =item set_ready_validate (method)
1393 Sets that the validation is ready to validate. Should set the value
1394 checked by the hook ready_validate. The following would complement the
1395 processing flag above:
1397 sub set_ready_validate {
1400 $self->form->{'processing'} = 1;
1402 delete $self->form->{'processing'};
1406 Note that for this example the form key "processing" was deleted. This
1407 is so that the call to fill in any html forms won't swap in a value of
1408 zero for form elements named "processing."
1412 Ran at the beginning of the loop before prepare, info_complete, and
1413 finalize are called. If it returns true, nav_loop moves on to the
1414 next step (the current step is skipped).
1416 =item stash (method)
1418 Returns a hashref that can store arbitrary user space data without
1419 worrying about overwriting the internals of the application.
1421 =item step_key (method)
1423 Should return the keyname that will be used by the default "path"
1424 method to look for in the form. Default value is 'step'.
1426 =item swap_template (hook)
1428 Takes the template and hash of variables prepared in print, and processes them
1429 through the current template engine (default engine is CGI::Ex::Template).
1431 Arguments are the template and the swap hashref. The template can be either a
1432 scalar reference to the actual content, or the filename of the content. If the
1433 filename is specified - it should be relative to base_dir_abs.
1435 =item template_args (hook)
1437 Returns a hashref of args that will be passed to the "new" method of CGI::Ex::Template.
1438 By default this hashref contains INCLUDE_PATH which is set equal to base_dir_abs.
1439 It can be augmented with any arguments that CGI::Ex::Template would understand.
1443 INCLUDE_PATH => '/my/own/include/path',
1444 WRAPPER => 'wrappers/main_wrapper.html',
1448 =item unmorph (method)
1450 Allows for returning an object back to its previous blessed state if
1451 the "morph" method was successful in morphing the App object. This
1452 only happens if the object was previously morphed into another object
1453 type. Before the object is re-blessed the method fixup_before_unmorph
1456 See allow_morph and morph.
1458 =item valid_steps (method)
1460 Called by the default path method. Should return a hashref of path
1461 steps that are allowed. If the current step is not found in the hash
1462 (or is not the default_step or js_step) the path method will return a
1463 single step of ->forbidden_step and run its hooks. If no hash or undef is
1464 returned, all paths are allowed (default). A key "forbidden_step"
1465 containing the step that was not valid will be placed in the stash.
1466 Often the valid_steps method does not need to be defined as arbitrary
1467 method calls are not possible with CGI::Ex::App.
1469 Any steps that begin with _ are also "not" valid for passing in via the form
1470 or path info. See the path method.
1472 Also, the pre_step, skip, prepare, and info_complete hooks allow for validating
1473 the data before running finalize.
1475 =item validate (hook)
1477 Runs validation on the information posted in $self->form. Uses
1478 CGI::Ex::Validate for the default validation. Calls the hook
1479 hash_validation to load validation information. Should return true if
1480 the form passed validation and false otherwise. Errors are stored as
1481 a hash in $self->{hash_errors} via method add_errors and can be
1482 checked for at a later time with method has_errors (if the default
1485 There are many ways and types to validate the data. Please see the L<CGI::Ex::Validate>
1488 Upon success, it will look through all of the items which were
1489 validated, if any of them contain the keys append_path, insert_path,
1490 or replace_path, that method will be called with the value as
1491 arguments. This allows for the validation to apply redirection to the
1492 path. A validation item of:
1494 {field => 'foo', required => 1, append_path => ['bar', 'baz']}
1496 would append 'bar' and 'baz' to the path should all validation succeed.
1498 =item verify_user (method)
1500 Installed as a hook to CGI::Ex::App during get_valid_auth. Should return
1501 true if the user is ok. Default is to always return true. This can be
1502 used to abort early before the get_pass_by_user hook is called.
1505 my ($self, $user) = @_;
1506 return 0 if $user eq 'paul'; # don't let paul in
1507 return 1; # let anybody else in
1512 =head1 OTHER APPLICATION MODULES
1514 The concepts used in CGI::Ex::App are not novel or unique. However, they
1515 are all commonly used and very useful. All application builders were
1516 built because somebody observed that there are common design patterns
1517 in CGI building. CGI::Ex::App differs in that it has found more common design
1518 patterns of CGI's than some and tries to get in the way less than others.
1520 CGI::Ex::App is intended to be sub classed, and sub sub classed, and each step
1521 can choose to be sub classed or not. CGI::Ex::App tries to remain simple
1522 while still providing "more than one way to do it." It also tries to avoid
1523 making any sub classes have to call ->SUPER:: (although that is fine too).
1525 There are certainly other modules for building CGI applications. The
1526 following is a short list of other modules and how CGI::Ex::App is
1531 =item C<CGI::Application>
1533 Seemingly the most well know of application builders.
1534 CGI::Ex::App is different in that it:
1536 * Uses Template::Toolkit compatible CGI::Ex::Template by default
1537 CGI::Ex::App can easily use another toolkit by simply
1538 overriding the ->swap_template method.
1539 CGI::Application uses HTML::Template.
1540 * Offers integrated data validation.
1541 CGI::Application has had custom plugins created that
1542 add some of this functionality. CGI::Ex::App has the benefit
1543 that validation is automatically available in javascript as well.
1544 * Allows the user to print at any time (so long as proper headers
1545 are sent. CGI::Application requires data to be pipelined.
1546 * Offers hooks into the various phases of each step ("mode" in
1547 CGI::Application lingo). CGI::Application provides only ->runmode
1548 which is only a dispatch.
1549 * Support for easily jumping around in navigation steps.
1550 * Support for storing some steps in another package.
1552 CGI::Ex::App and CGI::Application are similar in that they take care
1553 of handling headers and they allow for calling other "runmodes" from
1554 within any given runmode. CGI::Ex::App's ->run_step is essentially
1555 equivalent to a method call defined in CGI::Application's ->run_modes.
1556 The ->run method of CGI::Application starts the application in the same
1557 manner as CGI::Ex::App's ->navigate call. Many of the hooks around
1558 CGI::Ex::App's ->run_step call are similar in nature to those provided by
1561 =item C<CGI::Prototype>
1563 There are actually many similarities. One of the nicest things about
1564 CGI::Prototype is that it is extremely short (very very short). The
1565 ->activate starts the application in the same manner as CGI::Ex::App's
1566 ->navigate call. Both use Template::Toolkit as the default template
1567 system (CGI::Ex::App uses CGI::Ex::Template which is TT compatible).
1568 CGI::Ex::App is differrent in that it:
1570 * Offers integrated data validation.
1571 CGI::Application has had custom addons created that
1572 add some of this functionality. CGI::Ex::App has the benefit
1573 that once validation is created,
1574 * Offers more hooks into the various phases of each step.
1575 * Support for easily jumping around in navigation steps.
1576 * Support for storing only some steps in another package.
1581 =head1 SIMPLE EXTENDED EXAMPLE
1583 The following example shows the creation of a basic recipe
1584 database. It requires the use of DBD::SQLite, but that is all.
1585 Once you have configured the db_file and base_dir_abs methods
1586 of the "recipe" file, you will have a working script that
1587 does CRUD for the recipe table. The observant reader may ask - why
1588 not use Catalyst or Ruby on Rails? The observant programmer will
1589 reply that making a framework do something simple is easy, but making
1590 it do something complex is complex and any framework that tries to
1591 do the those complex things for you is too complex. CGI::Ex::App
1592 lets you write the complex logic but gives you the ability to
1593 not worry about the boring details such as template engines,
1594 or sticky forms, or cgi parameters, or data validation. Once
1595 you are setup and are running, you are only left with providing
1596 the core logic of the application.
1598 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
1599 ### --------------------------------------------
1602 use lib qw(/var/www/lib);
1607 ### File: /var/www/lib/Recipe.pm
1608 ### --------------------------------------------
1612 use base qw(CGI::Ex::App);
1613 use CGI::Ex::Dump qw(debug);
1618 ###------------------------------------------###
1621 # show what happened
1622 debug shift->dump_history;
1625 sub base_dir_abs { '/var/www/templates' }
1627 sub base_dir_rel { 'content' }
1629 sub db_file { '/var/www/recipe.sqlite' }
1633 if (! $self->{'dbh'}) {
1634 my $file = $self->db_file;
1635 my $exists = -e $file;
1636 $self->{'dbh'} = DBI->connect("dbi:SQLite:dbname=$file", '', '',
1638 $self->create_tables if ! $exists;
1640 return $self->{'dbh'};
1646 $self->dbh->do("CREATE TABLE recipe (
1647 id INTEGER PRIMARY KEY AUTOINCREMENT,
1648 title VARCHAR(50) NOT NULL,
1649 ingredients VARCHAR(255) NOT NULL,
1650 directions VARCHAR(255) NOT NULL,
1651 date_added VARCHAR(20) NOT NULL
1655 ###----------------------------------------------------------------###
1657 sub main_info_complete { 0 }
1659 sub main_hash_swap {
1662 my $s = "SELECT id, title, date_added
1664 ORDER BY date_added";
1665 my $data = $self->dbh->selectall_arrayref($s);
1666 my @data = map {my %h; @h{qw(id title date_added)} = @$_; \%h} @$data;
1673 ###----------------------------------------------------------------###
1675 sub add_name_step { 'edit' }
1677 sub add_hash_validation {
1679 'group order' => [qw(title ingredients directions)],
1697 my $form = $self->form;
1699 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ?";
1700 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'});
1702 $self->add_errors(title => 'A recipe by this title already exists');
1706 $s = "INSERT INTO recipe (title, ingredients, directions, date_added)
1707 VALUES (?, ?, ?, ?)";
1708 $self->dbh->do($s, {}, $form->{'title'},
1709 $form->{'ingredients'},
1710 $form->{'directions'},
1713 $self->add_to_form(success => "Recipe added to the database");
1718 ###----------------------------------------------------------------###
1720 sub edit_skip { shift->form->{'id'} ? 0 : 1 }
1722 sub edit_hash_common {
1724 return {} if $self->ready_validate;
1726 my $sth = $self->dbh->prepare("SELECT * FROM recipe WHERE id = ?");
1727 $sth->execute($self->form->{'id'});
1728 my $hash = $sth->fetchrow_hashref;
1733 sub edit_hash_validation { shift->add_hash_validation(@_) }
1737 my $form = $self->form;
1739 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ? AND id != ?";
1740 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'}, $form->{'id'});
1742 $self->add_errors(title => 'A recipe by this title already exists');
1746 my $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?";
1747 $self->dbh->do($s, {}, $form->{'title'},
1748 $form->{'ingredients'},
1749 $form->{'directions'},
1752 $self->add_to_form(success => "Recipe updated in the database");
1757 ###----------------------------------------------------------------###
1759 sub view_skip { shift->edit_skip(@_) }
1761 sub view_hash_common { shift->edit_hash_common(@_) }
1763 ###----------------------------------------------------------------###
1765 sub delete_skip { shift->edit_skip(@_) }
1767 sub delete_info_complete { 1 }
1769 sub delete_finalize {
1771 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
1773 $self->add_to_form(success => "Recipe deleted from the database");
1783 File: /var/www/templates/content/recipe/main.html
1784 ### --------------------------------------------
1787 <title>Recipe DB</title>
1791 [% IF success %]<span style="color:darkgreen"><h2>[% success %]</h2></span>[% END %]
1793 <table style="border:1px solid blue">
1794 <tr><th>#</th><th>Title</th><th>Date Added</th></tr>
1796 [% FOR row IN recipies %]
1798 <td>[% loop.count %].</td>
1799 <td><a href="[% script_name %]/view?id=[% row.id %]">[% row.title %]</a>
1800 (<a href="[% script_name %]/edit?id=[% row.id %]">Edit</a>)
1802 <td>[% row.date_added %]</td>
1806 <tr><td colspan=2 align=right><a href="[% script_name %]/add">Add new recipe</a></td></tr>
1812 File: /var/www/templates/content/recipe/edit.html
1813 ### --------------------------------------------
1816 <title>[% step == 'add' ? "Add" : "Edit" %] Recipe</title>
1818 <h1>[% step == 'add' ? "Add" : "Edit" %] Recipe</h1>
1820 <form method=post name=[% form_name %]>
1821 <input type=hidden name=step>
1825 [% IF step != 'add' ~%]
1827 <td><b>Id:</b></td><td>[% id %]</td></tr>
1828 <input type=hidden name=id>
1831 <td><b>Date Added:</b></td><td>[% date_added %]</td></tr>
1836 <td valign=top><b>Title:</b></td>
1837 <td><input type=text name=title>
1838 <span style='color:red' id=title_error>[% title_error %]</span></td>
1841 <td valign=top><b>Ingredients:</b></td>
1842 <td><textarea name=ingredients rows=10 cols=40 wrap=physical></textarea>
1843 <span style='color:red' id=ingredients_error>[% ingredients_error %]</span></td>
1846 <td valign=top><b>Directions:</b></td>
1847 <td><textarea name=directions rows=10 cols=40 wrap=virtual></textarea>
1848 <span style='color:red' id=directions_error>[% directions_error %]</span></td>
1851 <td colspan=2 align=right>
1852 <input type=submit value="[% step == 'add' ? 'Add' : 'Update' %]"></td>
1857 (<a href="[% script_name %]">Main Menu</a>)
1858 [% IF step != 'add' ~%]
1859 (<a href="[% script_name %]/delete?id=[% id %]">Delete this recipe</a>)
1867 File: /var/www/templates/content/recipe/view.html
1868 ### --------------------------------------------
1871 <title>[% title %] - Recipe DB</title>
1873 <h1>[% title %]</h1>
1874 <h3>Date Added: [% date_added %]</h3>
1876 <h2>Ingredients</h2>
1883 (<a href="[% script_name %]">Main Menu</a>)
1884 (<a href="[% script_name %]/edit?id=[% id %]">Edit this recipe</a>)
1888 ### --------------------------------------------
1892 The dbh method returns an SQLite dbh handle and auto creates the
1893 schema. You will normally want to use MySQL or Oracle, or Postgres
1894 and you will want your schema to NOT be auto-created.
1896 This sample uses hand rolled SQL. Class::DBI or a similar module
1897 might make this example shorter. However, more complex cases that
1898 need to involve two or three or four tables would probably be better
1899 off using the hand crafted SQL.
1901 This sample uses SQL. You could write the application to use whatever
1902 storage you want - or even to do nothing with the submitted data.
1904 We had to write our own HTML (Catalyst and Ruby on Rails do this for
1905 you). For most development work - the HTML should be in a static
1906 location so that it can be worked on by designers. It is nice that
1907 the other frameworks give you stub html - but that is all it is. It
1908 is worth about as much as copying and pasting the above examples. All
1909 worthwhile HTML will go through a non-automated design/finalization
1912 The add step used the same template as the edit step. We did
1913 this using the add_name_step hook which returned "edit". The template
1914 contains IF conditions to show different information if we were in
1915 add mode or edit mode.
1917 We reused code, validation, and templates. Code and data reuse is a
1920 The edit_hash_common returns an empty hashref if the form was ready to
1921 validate. When hash_common is called and the form is ready to
1922 validate, that means the form failed validation and is now printing
1923 out the page. To let us fall back and use the "sticky" form fields
1924 that were just submitted, we need to not provide values in the
1927 We use hash_common. Values from hash_common are used for both
1928 template swapping and filling. We could have used hash_swap and
1929 hash_fill independently.
1931 The hook main_info_complete is hard coded to 0. This basically says
1932 that we will never try and validate or finalize the main step - which
1933 is most often the case.
1935 =head1 SEPARATING STEPS INTO SEPARATE FILES
1937 It may be useful sometimes to separate some or all of the steps of an
1938 application into separate files. This is the way that CGI::Prototype
1939 works. This is useful in cases were some steps and their hooks are
1940 overly large - or are seldom used.
1942 The following modifications can be made to the previous "recipe db"
1943 example that would move the "delete" step into its own file. Similar
1944 actions can be taken to break other steps into their own file as well.
1947 ### File: /var/www/lib/Recipe.pm
1948 ### Same as before but add the following line:
1949 ### --------------------------------------------
1951 sub allow_morph { 1 }
1954 ### File: /var/www/lib/Recipe/Delete.pm
1955 ### Remove the delete_* subs from lib/Recipe.pm
1956 ### --------------------------------------------
1957 package Recipe::Delete;
1960 use base qw(Recipe);
1962 sub skip { shift->edit_skip(@_) }
1964 sub info_complete { 1 }
1968 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
1970 $self->add_to_form(success => "Recipe deleted from the database");
1977 The hooks that are called (skip, info_complete, and finalize) do not
1978 have to be prefixed with the step name because they are now in their
1979 own individual package space. However, they could still be named
1980 delete_skip, delete_info_complete, and delete_finalize and the
1981 run_hook method will find them (this would allow several steps with
1982 the same "morph_package" to still be stored in the same external
1985 The method allow_morph is passed the step that we are attempting to
1986 morph to. If allow_morph returns true every time, then it will try
1987 and require the extra packages every time that step is ran. You could
1988 limit the morphing process to run only on certain steps by using code
1989 similar to the following:
1991 sub allow_morph { return {delete => 1} }
1996 my ($self, $step) = @_;
1997 return ($step eq 'delete') ? 1 : 0;
2000 The CGI::Ex::App temporarily blesses the object into the
2001 "morph_package" for the duration of the step and re-blesses it into the
2002 original package upon exit. See the morph method and allow_morph for more
2005 =head1 RUNNING UNDER MOD_PERL
2007 The previous samples are essentially suitable for running under flat CGI,
2008 Fast CGI, or mod_perl Registry or mod_perl PerlRun type environments. It
2009 is very easy to move the previous example to be a true mod_perl handler.
2011 To convert the previous recipe example, simply add the following:
2013 ### File: /var/www/lib/Recipe.pm
2014 ### Same as before but add the following lines:
2015 ### --------------------------------------------
2023 ### File: apache2.conf - or whatever your apache conf file is.
2024 ### --------------------------------------------
2026 SetHandler perl-script
2032 Both the /cgi-bin/recipe version and the /recipe version can co-exist.
2033 One of them will be a normal cgi and the other will correctly use
2034 mod_perl hooks for headers.
2036 Setting the location to /recipe means that the $ENV{SCRIPT_NAME} will
2037 also be set to /recipe. This means that name_module method will
2038 resolve to "recipe". If a different URI location is desired such as
2039 "/my_cool_recipe" but the program is to use the same template content
2040 (in the /var/www/templates/content/recipe directory), then we would
2041 need to explicitly set the "name_module" parameter. It could be done
2042 in either of the following ways:
2044 ### File: /var/www/lib/Recipe.pm
2045 ### Same as before but add the following line:
2046 ### --------------------------------------------
2048 sub name_module { 'recipe' }
2054 $self->{'name_module'} = 'recipe';
2057 In most use cases it isn't necessary to set name_module, but it also
2058 doesn't hurt and in all cases it is more descriptive to anybody who is
2059 going to maintain the code later.
2061 =head1 ADDING AUTHENTICATION TO THE ENTIRE APPLICATION
2063 Having authentication is sometimes a good thing. To force
2064 the entire application to be authenticated (require a valid username
2065 and password before doing anything) you could do the following.
2067 ### File: /var/www/lib/Recipe.pm
2068 ### Same as before but add
2069 ### --------------------------------------------
2071 sub get_pass_by_user {
2074 my $pass = $self->lookup_and_cache_the_pass($user);
2079 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2080 ### Change the line with ->navigate; to
2081 ### --------------------------------------------
2083 Recipe->navigate_authenticated;
2087 ### File: /var/www/lib/Recipe.pm
2088 ### Same as before but add
2089 ### --------------------------------------------
2091 sub require_auth { 1 }
2095 ### File: /var/www/lib/Recipe.pm
2096 ### Same as before but add
2097 ### --------------------------------------------
2099 sub init { shift->require_auth(1) }
2101 See the require_auth, get_valid_auth, and auth_args methods for more information.
2102 Also see the L<CGI::Ex::Auth> perldoc.
2104 =head1 ADDING AUTHENTICATION TO INDIVIDUAL STEPS
2106 Sometimes you may only want to have certain steps require
2107 authentication. For example, in the previous recipe example we
2108 might want to let the main and view steps be accessible to anybody,
2109 but require authentication for the add, edit, and delete steps.
2111 To do this, we would do the following to the original example (the
2112 navigation must start with ->navigate. Starting with ->navigate_authenticated
2113 will cause all steps to require validation):
2115 ### File: /var/www/lib/Recipe.pm
2116 ### Same as before but add
2117 ### --------------------------------------------
2119 sub get_pass_by_user {
2122 my $pass = $self->lookup_and_cache_the_pass($user);
2126 sub require_auth { {add => 1, edit => 1, delete => 1} }
2128 That's it. The add, edit, and delete steps will now require authentication.
2129 See the require_auth, get_valid_auth, and auth_args methods for more information.
2130 Also see the L<CGI::Ex::Auth> perldoc.
2134 Bizhosting.com - giving a problem that fit basic design patterns.
2136 Earl Cahill - pushing the idea of more generic frameworks.
2138 Adam Erickson - design feedback, bugfixing, feature suggestions.
2140 James Lance - design feedback, bugfixing, feature suggestions.
2144 Paul Seamons <paul at seamons dot com>