]> Dogcows Code - chaz/p5-CGI-Ex/blob - lib/CGI/Ex/App.pod
e7c827d038e110c1cc0c719af8b968a0d473c1f2
[chaz/p5-CGI-Ex] / lib / CGI / Ex / App.pod
1 =head1 NAME
2
3 CGI::Ex::App - Anti-framework application framework.
4
5 =head1 DESCRIPTION
6
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.
12
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.
21
22
23 =head1 SYNOPSIS (A LONG "SYNOPSIS")
24
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.
33
34 ### File: /var/www/cgi-bin/my_app (depending upon Apache configuration)
35 ### --------------------------------------------
36 #!/usr/bin/perl -w
37
38 use strict;
39 use base qw(CGI::Ex::App);
40 use CGI::Ex::Dump qw(debug);
41
42 __PACKAGE__->navigate;
43 # OR
44 # my $obj = __PACKAGE__->new;
45 # $obj->navigate;
46
47 exit;
48
49 ###------------------------------------------###
50
51 sub post_navigate {
52 # show what happened
53 debug shift->dump_history;
54 }
55
56 sub main_hash_validation {
57 return {
58 'general no_alert' => 1,
59 'general no_confirm' => 1,
60 'group order' => [qw(username password password2)],
61 username => {
62 required => 1,
63 min_len => 3,
64 max_len => 30,
65 match => 'm/^\w+$/',
66 match_error => 'You may only use letters and numbers.',
67 },
68 password => {
69 required => 1,
70 min_len => 6,
71 },
72 password2 => {
73 equals => 'password',
74 },
75 };
76 }
77
78 sub main_file_print {
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>
84 <table>
85 <tr>
86 <td><b>Username:</b></td>
87 <td><input type=text name=username><span style='color:red' id=username_error>[% username_error %]</span></td>
88 </tr><tr>
89 <td><b>Password:</b></td>
90 <td><input type=text name=password><span style='color:red' id=password_error>[% password_error %]</span></td>
91 </tr><tr>
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>
94 </tr>
95 <tr><td colspan=2 align=right><input type=submit></td></tr>
96 </table>
97 </form>
98 [% js_validation %]
99 ";
100 }
101
102 sub main_finalize {
103 my $self = shift;
104
105 if ($self->form->{'username'} eq 'bar') {
106 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
107 return 0;
108 }
109
110 debug $self->form, "Do something useful with form here in the finalize hook.";
111
112 ### add success step
113 $self->add_to_swap({success_msg => "We did something"});
114 $self->append_path('success');
115 $self->set_ready_validate(0);
116 return 1;
117 }
118
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>
124 </div>
125 ";
126 }
127
128 __END__
129
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).
136
137 =head1 SYNOPSIS STEP BY STEP
138
139 This section goes step by step over the previous example.
140
141 Well - we start out with the customary CGI introduction.
142
143 #!/usr/bin/perl -w
144
145 use strict;
146 use base qw(CGI::Ex::App);
147 use CGI::Ex::Dump qw(debug);
148
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.
151
152 Now we need to invoke the process:
153
154 __PACKAGE__->navigate;
155 # OR
156 # my $obj = __PACKAGE__->new;
157 # $obj->navigate;
158 exit;
159
160 Note: the "exit" isn't necessary - but it is kind of nice to infer
161 that process flow doesn't go beyond the ->navigate call.
162
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.
173
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).
182
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.
188
189 sub post_navigate {
190 debug shift->dump_history;
191 } # show what happened
192
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
198 chunk of code.
199
200 sub main_hash_validation { ... }
201
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.
207
208 sub main_file_print { ... }
209
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).
218
219 A few things to note about the template:
220
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.
223
224 We provide locations to swap in inline errors.
225
226 <span style="color:red" id="username_error">[% username_error %]</span>
227
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
230 finds an error.
231
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.
235
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.
239
240 sub main_finalize {
241 my $self = shift;
242 my $form = $self->form;
243
244 At this point, all of the validated data is in the $form hashref.
245
246 if ($form->{'username'} eq 'bar') {
247 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
248 return 0;
249 }
250
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.
258
259 debug $form, "Do something useful with form here in the finalize hook.";
260
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.
263
264 ### add success step
265 $self->add_to_swap({success_msg => "We did something"});
266
267 Now that we have finished finalize, we add a message that will be passed to the template
268 engine.
269
270 $self->append_path('success');
271 $self->set_ready_validate(0);
272
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).
280
281 return 1;
282 }
283
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.
286
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.
289
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.
292
293 =head1 DEFAULT PROCESS FLOW
294
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.
302
303 =head2 navigate
304
305 The process starts off by calling ->navigate.
306
307 navigate {
308 eval {
309 ->pre_navigate
310 ->nav_loop
311 ->post_navigate
312 }
313 # dying errors will run the ->handle_error method
314
315 ->destroy
316 }
317
318 =head2 nav_loop
319
320 The nav_loop method will run as follows:
321
322 nav_loop {
323 ->path (get the array of path steps)
324 # look in $ENV{'PATH_INFO'}
325 # look in ->form for ->step_key
326 # make sure step is in ->valid_steps (if defined)
327
328 ->pre_loop($path)
329 # navigation stops if true
330
331 foreach step of path {
332
333 ->morph
334 # check ->allow_morph
335 # check ->allow_nested_morph
336 # ->morph_package (hook - get the package to bless into)
337 # ->fixup_after_morph if morph_package exists
338 # if no package is found, process continues in current file
339
340 ->run_step (hook)
341
342 ->refine_path (hook)
343 # only called if run_step returned false (page not printed)
344 ->next_step (hook) # find next step and add to path
345 ->set_ready_validate(0) (hook)
346
347 ->unmorph
348 # only called if morph worked
349 # ->fixup_before_unmorph if blessed to current package
350
351 # exit loop if ->run_step returned true (page printed)
352
353 } end of foreach step
354
355 ->post_loop
356 # navigation stops if true
357
358 ->default_step
359 ->insert_path (puts the default step into the path)
360 ->nav_loop (called again recursively)
361
362 } end of nav_loop
363
364 =head2 run_step (hook)
365
366 For each step of the path the following methods will be run
367 during the run_step hook.
368
369 run_step {
370 ->pre_step (hook)
371 # exits nav_loop if true
372
373 ->skip (hook)
374 # skips this step if true (stays in nav_loop)
375
376 ->prepare (hook - defaults to true)
377
378 ->info_complete (hook - ran if prepare was true)
379 ->ready_validate (hook)
380 return false if ! ready_validate
381 ->validate (hook - uses CGI::Ex::Validate to validate form info)
382 ->hash_validation (hook)
383 ->file_val (hook)
384 ->base_dir_abs
385 ->base_dir_rel
386 ->name_module
387 ->name_step
388 ->ext_val
389 returns true if validate is true or if nothing to validate
390
391 ->finalize (hook - defaults to true - ran if prepare and info_complete were true)
392
393 if ! ->prepare || ! ->info_complete || ! ->finalize {
394 ->prepared_print
395 ->hash_base (hook)
396 ->hash_common (hook)
397 ->hash_form (hook)
398 ->hash_fill (hook)
399 ->hash_swap (hook)
400 ->hash_errors (hook)
401 # merge form, base, common, and fill into merged fill
402 # merge form, base, common, swap, and errors into merged swap
403 ->print (hook - passed current step, merged swap hash, and merged fill)
404 ->file_print (hook - uses base_dir_rel, name_module, name_step, ext_print)
405 ->swap_template (hook - processes the file with CGI::Ex::Template)
406 ->template_args (hook - passed to CGI::Ex::Template->new)
407 ->fill_template (hook - fills the any forms with CGI::Ex::Fill)
408 ->fill_args (hook - passed to CGI::Ex::Fill::fill)
409 ->print_out (hook - print headers and the content to STDOUT)
410
411 ->post_print (hook - used for anything after the print process)
412
413 # return true to exit from nav_loop
414 }
415
416 ->post_step (hook)
417 # exits nav_loop if true
418
419 } end of run_step
420
421 It is important to learn the function and placement of each of the
422 hooks in the process flow in order to make the most of CGI::Ex::App.
423 It is enough to begin by learning a few common hooks - such as
424 hash_validation, hash_swap, and finalize, and then learn about other
425 hooks as needs arise. Sometimes, it is enough to simply override the
426 run_step hook and take care of processing the entire step yourself.
427
428 Because of the hook based system, and because CGI::Ex::App uses
429 sensible defaults, it is very easy to override a little or a lot which
430 ends up giving the developer a lot of flexibility.
431
432 Consequently, it should be possible to use CGI::Ex::App with the other
433 frameworks such as CGI::Application or CGI::Prototype. For these you
434 could simple let each "runmode" call the run_step hook of CGI::Ex::App
435 and you will instantly get all of the common process flow for free.
436
437 =head1 AVAILABLE METHODS / HOOKS
438
439 CGI::Ex::App's dispatch system works on the principles of hooks (which
440 are essentially glorified method lookups). When the run_hook method
441 is called, CGI::Ex::App will look for a corresponding method call for
442 that hook for the current step name. It is perhaps easier to show than
443 to explain.
444
445 If we are calling the "print" hook for the step "edit" we would call
446 run_hook like this:
447
448 $self->run_hook('print', 'edit', $template, \%swap, \%fill);
449
450 This would first look for a method named "edit_print". If it is unable to
451 find a method by that name, it will look for a method named "print". If it
452 is unable to find this method - it will die.
453
454 If allow_morph is set to true, the same methods are searched for but it becomes
455 possible to move some of those methods into an external package.
456
457 See the discussions under the methods named "find_hook" and "run_hook" for more details.
458
459 The following is the alphabetical list of methods and hooks.
460
461 =over 4
462
463 =item allow_morph (method)
464
465 Should return true if this step is allowed to "morph" the current App
466 object into another package. Default is false. It is passed a single
467 argument of the current step. For more granularity, if true value is
468 a hash, the step being morphed to must be in the hash.
469
470 To enable morphing for all steps, add the following:
471
472 sub allow_morph { 1 }
473
474 To enable morph on specific steps, do either of the following:
475
476 sub allow_morph {
477 return {
478 edit => 1,
479 delete => 1,
480 };
481 }
482
483 # OR
484
485 sub allow_morph {
486 my ($self, $step) = @_;
487 return $step =~ /^(edit|delete)$/;
488 }
489
490 See the morph "hook" for more information.
491
492 =item allow_nested_morph (method)
493
494 Similar to the allow_morph hook, but allows for one more level of morphing.
495 This is useful in cases where the base class was morphed early on, or
496 if a step needs to call a sub-step but morph first.
497
498 See the allow_morph and the morph method for more information.
499
500 Should return a boolean value or hash of allowed steps - just as the
501 allow_morph method does.
502
503 =item append_path (method)
504
505 Arguments are the steps to append. Can be called any time. Adds more
506 steps to the end of the current path.
507
508 =item auth_args (method)
509
510 Should return a hashref that will be passed to the new method of CGI::Ex::Auth.
511 It is augmented with arguments that integrate it into CGI::Ex::App.
512
513 See the get_valid_auth method and the CGI::Ex::Auth documentation.
514
515 sub auth_args {
516 return {
517 login_header => '<h1>My login header</h1>',
518 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
519 secure_hash_keys => [qw(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb ccccccccccccccccccccccc 2222222222222)],
520 # use_blowfish => 'my_blowfish_key',
521 };
522 }
523
524 =item auth_data (method)
525
526 Contains authentication data stored during the get_valid_auth method.
527 The data is normally blessed into the CGI::Ex::Auth::Data package which
528 evaluates to false if there was an error and true if the authentication
529 was successful - so this data can be defined but false.
530
531 See the get_valid_auth method.
532
533 =item cleanup_user (method)
534
535 Installed as a hook during get_valid_auth. Allows for cleaning
536 up the username. See the get_valid_auth method.
537
538 sub cleanup_user {
539 my ($self, $user) = @_;
540 return lc $user;
541 }
542
543 =item current_step (method)
544
545 Returns the current step that the nav_loop is functioning on.
546
547 =item default_step (method)
548
549 Step to show if the path runs out of steps. Default value is the
550 'default_step' property which defaults to 'main'.
551
552 If nav_loop runs of the end of the path (runs out of steps), this
553 method is called, the step is added to the path, and nav_loop calls
554 itself recursively.
555
556 =item destroy (method)
557
558 Called at the end of navigate after all other actions have run. Can
559 be used for undoing things done in the ->init method called during
560 the ->new method.
561
562 =item dump_history (method)
563
564 Show simplified trace information of which steps were called, the
565 order they were called in, the time they took to run, and a brief list
566 of the output (to see the full response returned by each hook, pass a
567 true value as the only argument to dump_history -
568 $self->dump_history(1)). Indentation is also applied to show which
569 hooks called other hooks.
570
571
572 The first line shows the amount of time elapsed for the entire
573 navigate execution. Subsequent lines contain:
574
575 Step - the name of the current step.
576 Hook - the name of the hook being called.
577 Found - the name of the method that was found.
578 Time - the total elapsed seconds that method took to run.
579 Output - the response of the hook - shown in shortened form.
580
581 Note - to get full output responses - pass a true value to
582 dump_history - or just call ->history. Times displayed are to 5
583 decimal places - this accuracy can only be provided if the Time::HiRes
584 module is installed on your system (it will only be used if installed).
585
586 It is usually best to print this history during the post_navigate
587 method as in the following:
588
589 use CGI::Ex::Dump qw(debug);
590 sub post_navigate { debug shift->dump_history }
591
592 The following is a sample output of dump_history called from the
593 sample recipe application at the end of this document. The step
594 called is "view".
595
596 debug: admin/Recipe.pm line 14
597 shift->dump_history = [
598 "Elapsed: 0.00562",
599 "view - run_step - run_step - 0.00488 - 1",
600 " view - pre_step - pre_step - 0.00003 - 0",
601 " view - skip - view_skip - 0.00004 - 0",
602 " view - prepare - prepare - 0.00003 - 1",
603 " view - info_complete - info_complete - 0.00010 - 0",
604 " view - ready_validate - ready_validate - 0.00004 - 0",
605 " view - prepared_print - prepared_print - 0.00441 - 1",
606 " view - hash_base - hash_base - 0.00009 - HASH(0x84ea6ac)",
607 " view - hash_common - view_hash_common - 0.00148 - HASH(0x8310a20)",
608 " view - hash_form - hash_form - 0.00004 - HASH(0x84eaa78)",
609 " view - hash_fill - hash_fill - 0.00003 - {}",
610 " view - hash_swap - hash_swap - 0.00003 - {}",
611 " view - hash_errors - hash_errors - 0.00003 - {}",
612 " view - print - print - 0.00236 - 1",
613 " view - file_print - file_print - 0.00024 - recipe/view.html",
614 " view - name_module - name_module - 0.00007 - recipe",
615 " view - name_step - name_step - 0.00004 - view",
616 " view - swap_template - swap_template - 0.00161 - <html> ...",
617 " view - template_args - template_args - 0.00008 - HASH(0x865abf8)",
618 " view - fill_template - fill_template - 0.00018 - 1",
619 " view - fill_args - fill_args - 0.00003 - {}",
620 " view - print_out - print_out - 0.00015 - 1",
621 " view - post_print - post_print - 0.00003 - 0"
622 ];
623
624 =item exit_nav_loop (method)
625
626 This method should not normally used but there is no problem with
627 using it on a regular basis. Essentially it is a "goto" that allows
628 for a long jump to the end of all nav_loops (even if they are
629 recursively nested). This effectively short circuits all remaining
630 hooks for the current and remaining steps. It is used to allow the
631 ->jump functionality. If the application has morphed, it will be
632 unmorphed before returning. Also - the post_navigate method will
633 still be called.
634
635 =item first_step (method)
636
637 Returns the first step of the path. Note that first_step may not be the same
638 thing as default_step if the path was overridden.
639
640 =item form (method)
641
642 Returns a hashref of the items passed to the CGI. Returns
643 $self->{form} which defaults to CGI::Ex::get_form.
644
645 =item handle_error (method)
646
647 If anything dies during execution, handle_error will be called with
648 the error that had happened. Default action is to die with that error.
649
650 =item history (method)
651
652 Returns an arrayref which contains trace history of which hooks of
653 which steps were ran. Useful for seeing what happened. In general -
654 each line of the history will show the current step, the hook
655 requested, and which hook was actually called.
656
657 The dump_history method shows a short condensed version of this
658 history which makes it easier to see what path was followed.
659
660 In general, the arrayref is free for anything to push onto which will
661 help in tracking other occurrences in the program as well.
662
663 =item init (method)
664
665 Called by the default new method. Allows for any object
666 initilizations that may need to take place. Default action does
667 nothing.
668
669 =item fill_args (hook)
670
671 Returns a hashref of args that will be passed to the CGI::Ex::Fill::fill.
672 It is augmented with the template to swap and the fill hash. This
673 could be useful if you needed to only swap a particular form on the template
674 page. Arguments are passed directly to the fill function.
675
676 sub fill_args { {target => 'my_form'} }
677
678 =item fill_template (hook)
679
680 Arguments are a template and a hashref. Takes the template that was
681 prepared using swap_template, and swaps html form fields using the
682 passed hashref. Overriding this method can control the fill behavior.
683
684 Calls the fill_args hook prior to calling CGI::Ex::Fill::fill
685
686 =item file_print (hook)
687
688 Returns a filename of the content to be used in the default print
689 hook. Adds method base_dir_rel to hook name_module, and name_step and
690 adds on the default file extension found in $self->ext_print which
691 defaults to the property $self->{ext_print} which will default to
692 ".html". Should return a filename relative to base_dir_abs that can be
693 swapped using CGI::Ex::Template, or should be a scalar reference to
694 the template content that can be swapped. This will be used by the
695 hook print.
696
697 sub base_dir_abs { '/var/www/templates' }
698 sub base_dir_rel { 'content' }
699 sub name_module { 'recipe' }
700 sub ext_print { 'html' } # default
701
702 # ->file_print('this_step')
703 # would return 'content/recipe/this_step.html'
704 # the template engine would look in '/var/www/templates'
705 # for a file by that name
706
707 It may also return a reference to a string containing the html template.
708 This is useful for prototyping applications and/or keeping all of
709 the data for the application in a single location.
710
711 =item file_val (hook)
712
713 Returns a filename containing the validation. Performs the same
714 as file_print, but uses ext_val to get the extension, and it adds
715 base_dir_abs onto the returned value (file_print is relative to
716 base_dir_abs, while file_val is fully qualified with base_dir_abs)
717
718 The file should be readable by CGI::Ex::Validate::get_validation.
719
720 This hook is only necessary if the hash_validation hook has not been
721 overridden.
722
723 This method an also return a hashref containing the validation - but
724 then you may have wanted to override the hash_validation hook.
725
726 =item finalize (hook)
727
728 Defaults to true. Used to do whatever needs to be done with the data once
729 prepare has returned true and info_complete has returned true. On failure
730 the print operations are ran. On success navigation moves on to the next
731 step.
732
733 This is normally were there core logic of a script will occur (such as
734 adding to a database, or updating a record). At this point, the data
735 should be validated. It is possible to do additional validation
736 and return errors using code such as the following.
737
738 if (! $user_is_unique) {
739 $self->add_errors(username => 'The username was already used');
740 return 0;
741 }
742
743 =item find_hook (method)
744
745 Called by run_hook. Arguments are a hook name, a step name. It
746 should return an arrayref containing the code_ref to run, and the
747 name of the method looked for. It uses ->can to find the appropriate
748 hook.
749
750 my $code = $self->hook('finalize', 'main');
751 ### will look first for $self->main_finalize;
752 ### will then look for $self->finalize;
753
754 This system is used to allow for multiple steps to be in the same
755 file and still allow for moving some steps out to external sub classed
756 packages (if desired).
757
758 If the application has successfully morphed via the morph method and
759 allow_morph then it is not necessary to add the step name to the
760 beginning of the method name as the morphed packages method will
761 override the base package (it is still OK to use the full method name
762 "${step}_hookname").
763
764 See the run_hook method and the morph method for more details.
765
766 =item forbidden_step (method)
767
768 Defaults to "__forbidden". The name of a step to run should the current
769 step name be invalid, or if a step found by the default path method
770 is invalid. See the path method.
771
772 =item form_name (hook)
773
774 Return the name of the form to attach the js validation to. Used by
775 js_validation.
776
777 =item get_pass_by_user (method)
778
779 This method is passed a username and the authentication object. It
780 should return the password for the given user. See the get_pass_by_user
781 method of CGI::Ex::Auth for more information. Installed as a hook
782 to the authentication object during the get_valid_auth method.
783
784 =item get_valid_auth (method)
785
786 If require_auth is true at either the application level or at the
787 step level, get_valid_auth will be called.
788
789 It will call auth_args to get some default args to pass to
790 CGI::Ex::Auth->new. It augments the args with sensible defaults that
791 App already provides (such as form, cookies, and template facilities).
792 It also installs hooks for the get_pass_by_user, cleanup_user, and verify_user
793 hooks of CGI::Ex::Auth.
794
795 It stores the $auth->last_auth_data in $self->auth_data for later use. For
796 example, to get the authenticated user:
797
798 sub require_auth { 1 }
799
800 sub cleanup_user {
801 my ($self, $user) = @_;
802 return lc $user;
803 }
804
805 sub get_pass_by_user {
806 my ($self, $user) = @_;
807 my $pass = $self->some_method_to_get_the_pass($user);
808 return $pass;
809 }
810
811 sub auth_args {
812 return {
813 login_header => '<h1>My login header</h1>',
814 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
815 };
816 }
817
818 sub main_hash_swap {
819 my $self = shift;
820 my $user = $self->auth_data->{'user'};
821 return {user => $user};
822 }
823
824 Successful authentication is cached for the duration of the
825 nav_loop so multiple steps will run the full authentication routine
826 only once.
827
828 Full customization of the login process and the login template can
829 be done via the auth_args hash. See the auth_args method and
830 CGI::Ex::Auth perldoc for more information.
831
832 =item hash_base (hook)
833
834 A hash of base items to be merged with hash_form - such as pulldown
835 menus, javascript validation, etc. It will now also be merged with
836 hash_fill, so it can contain default fillins as well. It can be
837 populated by passing a hash to ->add_to_base. By default a sub
838 similar to the following is what is used for hash_common. Note the
839 use of values that are code refs - so that the js_validation and
840 form_name hooks are only called if requested:
841
842 sub hash_base {
843 my ($self, $step) = @_;
844 return $self->{hash_base} ||= {
845 script_name => $ENV{SCRIPT_NAME},
846 js_validation => sub { $self->run_hook('js_validation', $step) },
847 form_name => sub { $self->run_hook('form_name', $step) },
848 };
849 }
850
851 =item hash_common (hook)
852
853 Almost identical in function and purpose to hash_base. It is
854 intended that hash_base be used for common items used in various
855 scripts inheriting from a common CGI::Ex::App type parent. Hash_common
856 is more intended for step level populating of both swap and fill.
857
858 =item hash_errors (hook)
859
860 Called in preparation for print after failed prepare, info_complete,
861 or finalize. Should contain a hash of any errors that occurred. Will
862 be merged into hash_form before the pass to print. Each error that
863 occurred will be passed to method format_error before being added to
864 the hash. If an error has occurred, the default validate will
865 automatically add {has_errors =>1}. To the error hash at the time of
866 validation. has_errors will also be added during the merge in case the
867 default validate was not used. Can be populated by passing a hash to
868 ->add_to_errors or ->add_errors.
869
870 =item hash_fill (hook)
871
872 Called in preparation for print after failed prepare, info_complete,
873 or finalize. Should contain a hash of any items needed to be filled
874 into the html form during print. Items from hash_form, hash_base, and
875 hash_common will be layered together. Can be populated by passing a
876 hash to ->add_to_fill.
877
878 By default - forms are sticky and data from previous requests will try
879 and populate the form. You can use the fill_template hook to disable
880 templating on a single page or on all pages.
881
882 This method can be used to pre-populate the form as well (such as on an
883 edit step). If a form fails validation, hash_fill will also be called
884 and will only want the submitted form fields to be sticky. You can
885 use the ready_validate hook to prevent pre-population in these cases as
886 follows:
887
888 sub edit_hash_fill {
889 my $self = shift;
890 my $step = shift;
891 return {} if $self->run_hook('ready_validate', $step);
892
893 my %hash;
894
895 ### get previous values from the database
896
897 return \%hash;
898 }
899
900 =item hash_form (hook)
901
902 Called in preparation for print after failed prepare, info_complete,
903 or finalize. Defaults to ->form. Can be populated by passing a hash
904 to ->add_to_form.
905
906 =item hash_swap (hook)
907
908 Called in preparation for print after failed prepare, info_complete,
909 or finalize. Should contain a hash of any items needed to be swapped
910 into the html during print. Will be merged with hash_base,
911 hash_common, hash_form, and hash_errors. Can be populated by passing
912 a hash to ->add_to_swap.
913
914 The hash will be passed as the second argument to swap_template.
915
916 =item hash_validation (hook)
917
918 Returns a hash of the validation information to check form against.
919 By default, will look for a filename using the hook file_val and will
920 pass it to CGI::Ex::Validate::get_validation. If no file_val is
921 returned or if the get_validation fails, an empty hash will be returned.
922 Validation is implemented by ->vob which loads a CGI::Ex::Validate object.
923
924 =item info_complete (hook)
925
926 Calls the ready_validate hook to see if data is ready to validate. If
927 so it calls the validate hook to validate the data. Should make
928 sure the data is ready and valid. Will not be run unless
929 prepare returns true (default).
930
931 =item insert_path (method)
932
933 Arguments are the steps to insert. Can be called any time. Inserts
934 the new steps at the current path location.
935
936 =item is_authed (method)
937
938 Returns true if the object has successful authentication data. It
939 returns false if the object has not been authenticated.
940
941 =item js_uri_path (method)
942
943 Return the URI path where the CGI/Ex/yaml_load.js and
944 CGI/Ex/validate.js files can be found. This will default to
945 "$ENV{SCRIPT_NAME}/js" if the path method has not been overridden,
946 otherwise it will default to "$ENV{SCRIPT_NAME}?step=js&js=" (the
947 latter is more friendly with overridden paths). A default handler for
948 the "js" step has been provided in "js_run_step" (this handler will
949 nicely print out the javascript found in the js files which are
950 included with this distribution. js_run_step will work properly with the
951 default "path" handler.
952
953 =item js_validation (hook)
954
955 Requires JSON or YAML. Will return Javascript that is capable of
956 validating the form. This is done using the capabilities of
957 CGI::Ex::Validate. This will call the hook hash_validation which will
958 then be encoded either json or into yaml and placed in a javascript
959 string. It will also call the hook form_name to determine which html
960 form to attach the validation to. The method js_uri_path is called to
961 determine the path to the appropriate validate.js files. If the
962 method ext_val is htm, then js_validation will return an empty string
963 as it assumes the htm file will take care of the validation itself.
964 In order to make use of js_validation, it must be added to the
965 variables returned by either the hash_base, hash_common, hash_swap or
966 hash_form hook (see examples of hash_base used in this doc).
967
968 By default it will try and use JSON first and then fail to YAML and
969 then will fail to returning an html comment that does nothing.
970
971 =item jump (method)
972
973 This method should not normally be used but is fine to use it on a
974 regular basis. It provides for moving to the next step at any point
975 during the nav_loop. It effectively short circuits the remaining
976 hooks for the current step. It does increment the recursion counter
977 (which has a limit of ->recurse_limit - default 15). It is normally
978 better to allow the other hooks in the loop to carry on their normal
979 functions and avoid jumping. (Essentially, this hook behaves like a
980 goto method to bypass everything else and continue at a different
981 location in the path - there are times when it is necessary or useful
982 to do this).
983
984 Jump takes a single argument which is the location in the path to jump
985 to. This argument may be either a step name, the special strings
986 "FIRST, LAST, CURRENT, PREVIOUS, OR NEXT" or the number of steps to
987 jump forward (or backward) in the path. The default value, 1,
988 indicates that CGI::Ex::App should jump to the next step (the default
989 action for jump). A value of 0 would repeat the current step (watch
990 out for recursion). A value of -1 would jump to the previous step.
991 The special value of "LAST" will jump to the last step. The special
992 value of "FIRST" will jump back to the first step. In each of these
993 cases, the path array returned by ->path is modified to allow for the
994 jumping (the path is modified so that the path history is not destroyed
995 - if we were on step 3 and jumped to one, that path would contain
996 1, 2, 3, *1, 2, 3, 4, etc and we would be at the *).
997
998 ### goto previous step
999 $self->jump($self->previous_step);
1000 $self->jump('PREVIOUS');
1001 $self->jump(-1);
1002
1003 ### goto next step
1004 $self->jump($self->next_step);
1005 $self->jump('NEXT');
1006 $self->jump(1);
1007 $self->jump;
1008
1009 ### goto current step (repeat)
1010 $self->jump($self->current_step);
1011 $self->jump('CURRENT');
1012 $self->jump(0);
1013
1014 ### goto last step
1015 $self->jump($self->last_step);
1016 $self->jump('LAST');
1017
1018 ### goto first step
1019 $self->jump($self->first_step);
1020 $self->jump('FIRST');
1021
1022 =item last_step (method)
1023
1024 Returns the last step of the path. Can be used to jump to the last step.
1025
1026 =item morph (method)
1027
1028 Allows for temporarily "becoming" another object type for the
1029 execution of the current step. This allows for separating some steps
1030 out into their own packages.
1031
1032 Morph will only run if the method allow_morph returns true.
1033 Additionally if the allow_morph returns a hash ref, morph will only
1034 run if the step being morphed to is in the hash. Morph also passes
1035 the step name to allow_morph.
1036
1037 The morph call occurs at the beginning of the step loop. A
1038 corresponding unmorph call occurs before the loop is exited. An
1039 object can morph several levels deep if allow_nested_morph returns
1040 true. For example, an object running as Foo::Bar that is looping on
1041 the step "my_step" that has allow_morph = 1, will do the following:
1042
1043 Call the morph_package hook (which would default to returning
1044 Foo::Bar::MyStep in this case)
1045
1046 Translate this to a package filename (Foo/Bar/MyStep.pm) and try
1047 and require it, if the file can be required, the object is blessed
1048 into that package.
1049
1050 Call the fixup_after_morph method.
1051
1052 Continue on with the run_step for the current step.
1053
1054 At any exit point of the loop, the unmorph call is made which
1055 re-blesses the object into the original package.
1056
1057 Samples of allowing morph:
1058
1059 sub allow_morph { 1 }
1060
1061 sub allow_morph { {edit => 1} }
1062
1063 sub allow_morph { my ($self, $step) = @_; return $step eq 'edit' }
1064
1065 It is possible to call morph earlier on in the program. An example of
1066 a useful early use of morph would be as in the following code:
1067
1068 sub allow_morph { 1 }
1069
1070 sub pre_navigate {
1071 my $self = shift;
1072 if ($ENV{'PATH_INFO'} && $ENV{'PATH_INFO'} =~ s|^/(\w+)||) {
1073 my $step = $1;
1074 $self->morph($step);
1075 $ENV{'PATH_INFO'} = "/$step";
1076 $self->stash->{'base_morphed'} = 1;
1077 }
1078 return 0;
1079 }
1080
1081 sub post_navigate {
1082 my $self = shift;
1083 $self->unmorph if $self->stash->{'base_morphed'};
1084 }
1085
1086 If this code was in a module Base.pm and the cgi running was cgi/base
1087 and called:
1088
1089 Base->navigate;
1090
1091 and you created a sub module that inherited Base.pm called
1092 Base/Ball.pm -- you could then access it using cgi/base/ball. You
1093 would be able to pass it steps using either cgi/base/ball/step_name or
1094 cgi/base/ball?step=step_name - Or Base/Ball.pm could implement its
1095 own path. It should be noted that if you do an early morph, it is
1096 suggested to provide a call to unmorph. And if you want to let your
1097 early morphed object morph again - you will need to provide
1098
1099 sub allow_nested_morph { 1 }
1100
1101 With allow_nested_morph enabled you could create the file
1102 Base/Ball/StepName.pm which inherits Base/Ball.pm. The Base.pm, with
1103 the custom init and default path method, would automatically morph us
1104 first into a Base::Ball object (during init) and then into a
1105 Base::Ball::StepName object (during the navigation loop).
1106
1107 Since it is complicated to explain - it may be a bit complicated to
1108 those who will try to follow your code later. CGI::Ex::App provides
1109 many ways to do things, but use the best one for your situation.
1110
1111 =item morph_package (hook)
1112
1113 Used by morph. Return the package name to morph into during a morph
1114 call. Defaults to using the current object type as a base. For
1115 example, if the current object running is a Foo::Bar object and the
1116 step running is my_step, then morph_package will return
1117 Foo::Bar::MyStep.
1118
1119 Because of the way that run_hook works, it is possible that several
1120 steps could be located in the same external file and overriding morph_package
1121 could allow for this to happen.
1122
1123 See the morph method.
1124
1125 =item name_module (hook)
1126
1127 Return the name (relative path) that should be pre-pended to name_step
1128 during the default file_print and file_val lookups. Defaults to
1129 the value in $self->{name_module} which in turn defaults to the name
1130 of the current script.
1131
1132 cgi-bin/my_app.pl => my_app
1133 cgi/my_app => my_app
1134
1135 This method is provided so that each cgi or mod_perl application can
1136 have its own directory for storing html for its steps.
1137
1138 See the file_print method for more information.
1139
1140 =item name_step (hook)
1141
1142 Return the step (appended to name_module) that should used when
1143 looking up the file in file_print and file_val lookups. Defaults to
1144 the current step.
1145
1146 =item nav_loop (method)
1147
1148 This is the main loop runner. It figures out the current path
1149 and runs all of the appropriate hooks for each step of the path. If
1150 nav_loop runs out of steps to run (which happens if no path is set, or if
1151 all other steps run successfully), it will insert the ->default_step into
1152 the path and run nav_loop again (recursively). This way a step is always
1153 assured to run. There is a method ->recurse_limit (default 15) that
1154 will catch logic errors (such as inadvertently running the same
1155 step over and over and over because there is either no hash_validation,
1156 or the data is valid but the set_ready_validate(0) method was not called).
1157
1158 =item navigate (method)
1159
1160 Takes a class name or a CGI::Ex::App object as arguments. If a class
1161 name is given it will call the "new" method to instantiate an object
1162 by that class (passing any extra arguments to the new method). All
1163 returns from navigate will return the object.
1164
1165 The method navigate is essentially a safe wrapper around the ->nav_loop
1166 method. It will catch any dies and pass them to ->handle_error.
1167
1168 This starts the process flow for the path and its steps.
1169
1170 =item navigate_authenticated (method)
1171
1172 Same as the method navigate but sets require_auth(1) before
1173 running. See the require_auth method.
1174
1175 =item new (class method)
1176
1177 Object creator. Takes a hashref of arguments that will become the
1178 initial properties of the object. Calls the init method once the
1179 object has been blessed to allow for any other initilizations.
1180
1181 my $app = MyApp->new({name_module => 'my_app'});
1182
1183 =item next_step (hook and method)
1184
1185 Returns the next step in the path. If there is no next step, it
1186 returns the default_step.
1187
1188 It can be used as a method to return the next step in the path
1189 to pass to a method such as ->jump.
1190
1191 It is also used as a hook by the refine_path hook. If there is no
1192 more steps, it will call the next_step hook to try and find a step to
1193 append to the path.
1194
1195 =item path (method)
1196
1197 Return an arrayref (modifiable) of the steps in the path. For each
1198 step the run_step hook and all of its remaining hooks will be run.
1199
1200 Hook methods are looked up and ran using the method "run_hook" which
1201 uses the method "find_hook" to lookup the hook. A history of ran
1202 hooks is stored in the array ref returned by $self->history.
1203
1204 If path has not been defined, the method will look first in the form
1205 for a key by the name found in ->step_key. It will then look in
1206 $ENV{'PATH_INFO'}. It will use this step to create a path with that
1207 one step as its contents. If a step is passed in via either of these
1208 ways, the method will call valid_steps to make sure that the step
1209 is valid (by default valid_steps returns undef - which means that
1210 any step is valid). Any step beginning with _ can not be passed in
1211 and are intended for use on private paths. If a non-valid step is
1212 found, then path will be set to contain a single step of ->forbidden_step.
1213
1214 For the best functionality, the arrayref returned should be the same
1215 reference returned for every call to path - this ensures that other
1216 methods can add to the path (and will most likely break if the
1217 arrayref is not the same).
1218
1219 If navigation runs out of steps to run, the default step found in
1220 default_step will be run. This is what allows for us to default
1221 to the "main" step for many applications.
1222
1223 =item post_loop (method)
1224
1225 Ran after all of the steps in the loop have been processed (if
1226 prepare, info_complete, and finalize were true for each of the steps).
1227 If it returns a true value the navigation loop will be aborted. If it
1228 does not return true, navigation continues by then inserting the step
1229 $self->default_step and running $self->nav_loop again (recurses) to
1230 fall back to the default step.
1231
1232 =item post_navigate (method)
1233
1234 Called from within navigate. Called after the nav_loop has finished
1235 running but within the eval block to catch errors. Will only run if
1236 there were no errors which died during the nav_loop process.
1237
1238 It can be disabled from running by setting the _no_post_navigate
1239 property.
1240
1241 If per-step authentication is enabled and authentication fails,
1242 the post_navigate method will still be called (the post_navigate
1243 method can check the ->is_authed method to change behavior). If
1244 application level authentication is enabled and authentication
1245 fails, none of the pre_navigate, nav_loop, or post_navigate methods
1246 will be called.
1247
1248 =item post_print (hook)
1249
1250 A hook which occurs after the printing has taken place. Is only run
1251 if the information was not complete. Useful for cases such as
1252 printing rows of a database query after displaying a query form.
1253
1254 =item post_step (hook)
1255
1256 Ran at the end of the step's loop if prepare, info_complete, and
1257 finalize all returned true. Allows for cleanup. If a true value is
1258 returned, execution of navigate is returned and no more steps are
1259 processed.
1260
1261 =item pre_loop (method)
1262
1263 Called right before the navigation loop is started (at the beginning
1264 of nav_loop). At this point the path is set (but could be modified).
1265 The only argument is a reference to the path array. If it returns a
1266 true value - the navigation routine is aborted.
1267
1268 =item pre_navigate (method)
1269
1270 Called at the very beginning of the navigate method, but within the
1271 eval block to catch errors. Called before the nav_loop method is
1272 started. If a true value is returned then navigation is skipped (the
1273 nav_loop is never started).
1274
1275 =item pre_step (hook)
1276
1277 Ran at the beginning of the loop before prepare, info_compelete, and
1278 finalize are called. If it returns true, execution of nav_loop is
1279 returned and no more steps are processed..
1280
1281 =item prepare (hook)
1282
1283 Defaults to true. A hook before checking if the info_complete is true.
1284 Intended to be used to cleanup the form data.
1285
1286 =item prepared_print (hook)
1287
1288 Called when any of prepare, info_complete, or finalize fail. Prepares
1289 a form hash and a fill hash to pass to print. The form hash is primarily
1290 intended for use by the templating system. The fill hash is intended
1291 to be used to fill in any html forms.
1292
1293 =item previous_step (method)
1294
1295 List the step previous to this one. Will return '' if there is no previous step.
1296
1297 =item print (hook)
1298
1299 Take the information generated by prepared_print, format it, and print it out.
1300 Default incarnation uses CGI::Ex::Template which is compatible with
1301 Template::Toolkit. Arguments are: step name (used to call the
1302 file_print hook), swap hashref (passed to call swap_template), and
1303 fill hashref (passed to fill_template).
1304
1305 During the print call, the file_print hook is called which should
1306 return a filename or a scalar reference to the template content is
1307
1308 =item ready_validate (hook)
1309
1310 Should return true if enough information is present to run validate.
1311 Default is to look if $ENV{'REQUEST_METHOD'} is 'POST'. A common
1312 usage is to pass a common flag in the form such as 'processing' => 1
1313 and check for its presence - such as the following:
1314
1315 sub ready_validate { shift->form->{'processing'} }
1316
1317 Changing the behavior of ready_validate can help in making wizard type
1318 applications.
1319
1320 =item refine_path (hook)
1321
1322 Called at the end of nav_loop. Passed a single value indicating
1323 if there are currently more steps in the path.
1324
1325 The default implementation returns if there are still more steps
1326 in the path. Otherwise, it calls the next_step hook and appends
1327 it to the path with the append_path method, and then calls
1328 the set_ready_validate hook and passes it 0.
1329
1330 This allows you to simply put
1331
1332 sub edit_next_step { '_edit_success' }
1333
1334 In your code and it will automatically do the right thing and
1335 go to the _edit_success step.
1336
1337 =item recurse_limit (method)
1338
1339 Default 15. Maximum number of times to allow nav_loop to call itself.
1340 The recurse level will increase every time that ->jump is called, or if
1341 the end of the nav_loop is reached and the process tries to add the
1342 default_step and run it again.
1343
1344 If ->jump is used often - the recurse_limit will be reached more
1345 quickly. It is safe to raise this as high as is necessary - so long
1346 as it is intentional.
1347
1348 Often the limit is reached if a step did not have a validation hash,
1349 or if the set_ready_validate(0) method was not called once the data
1350 had been successfully validated and acted upon.
1351
1352 =item replace_path (method)
1353
1354 Arguments are the steps used to replace. Can be called any time.
1355 Replaces the remaining steps (if any) of the current path.
1356
1357 =item require_auth (method)
1358
1359 Default undef. Can return either a true value or a hashref of step names.
1360
1361 If a hashref of stepnames is returned, authentication will be turned on
1362 at the step level. In this mode if any step is accessed, the get_valid_auth
1363 method will be called. If it fails, then the nav_loop will be stopped
1364 (the post_navigate method will be called - use the is_authed method to perform
1365 different functions). Any step of the path not in the hash will not require
1366 authentication. For example, to add authentication to add authentication
1367 to the add, edit and delete steps you could do:
1368
1369 sub require_auth { {add => 1, edit => 1, delete => 1} }
1370
1371 If a non-hash true value is returned from the require_auth method then
1372 authentication will take place before the pre_navigation or the nav_loop methods.
1373 If authentication fails the navigation process is exited (the post_navigate
1374 method will not be called).
1375
1376 sub require_auth { 1 }
1377
1378 Alternatively you can also could do either of the following:
1379
1380 __PACKAGE__->navigate_authenticated; # instead of __PACKAGE__->navigate;
1381
1382 # OR
1383
1384 sub init { shift->require_auth(1) }
1385
1386 # OR
1387
1388 __PACKAGE__->new({require_auth => 1}->navigate;
1389
1390 If get_valid_auth returns true, in either case, the is_authed method will
1391 return true and the auth_data will contain the authenticated user's data.
1392 If it returns false, auth_data may possibly contain a defined but false
1393 data object with details as to why authentication failed.
1394
1395 See the get_valid_auth method.
1396
1397 =item run_hook (method)
1398
1399 Arguments are a hook name and the step to find the hook for. Calls
1400 the find_hook method to get a code ref which it then calls and returns
1401 the result passing any extra arguments to run_hook as arguments to the
1402 code ref.
1403
1404 Each call to run_hook is logged in the arrayref returned by the
1405 history method. This information is summarized in the dump_history
1406 method and is useful for tracing the flow of the program.
1407
1408 The run_hook method is part of the core of CGI::Ex::App. It allows
1409 for an intermediate layer in normal method calls. Because of
1410 run_hook, it is possible to logically override methods on a step by
1411 step basis, or override a method for all of the steps, or even to
1412 break code out into separate modules.
1413
1414 =item run_step (hook)
1415
1416 Runs all of the hooks specific to each step, beginning with pre_step
1417 and ending with post_step (for a full listing of steps, see the
1418 section on process flow). Called after ->morph($step) has been run.
1419 If this hook returns true, the nav_loop is exited (meaning the
1420 run_step hook displayed a printed page). If it returns false, the
1421 nav_loop continues on to run the next step.
1422
1423 This hook performs the same base functionality as a method defined in
1424 CGI::Applications ->run_modes. The default run_step method provides
1425 much more granular control over the flow of the CGI.
1426
1427 =item set_path (method)
1428
1429 Arguments are the steps to set. Should be called before navigation
1430 begins. This will set the path arrayref to the passed steps.
1431
1432 This method is not normally used.
1433
1434 =item set_ready_validate (hook and method)
1435
1436 Sets that the validation is ready (or not) to validate. Should set the value
1437 checked by the hook ready_validate. The following would complement the
1438 processing flag above:
1439
1440 sub set_ready_validate {
1441 my $self = shift;
1442 my ($step, $is_ready) = (@_ == 2) ? @_ : (undef, shift);
1443 if ($is_ready) {
1444 $self->form->{'processing'} = 1;
1445 } else {
1446 delete $self->form->{'processing'};
1447 }
1448 return $is_ready;
1449 }
1450
1451 Note that for this example the form key "processing" was deleted. This
1452 is so that the call to fill in any html forms won't swap in a value of
1453 zero for form elements named "processing."
1454
1455 Also note that this method may be called as a hook as in
1456
1457 $self->run_hook('set_ready_validate', $step, 0)
1458 # OR
1459 $self->set_ready_validate($step, 0);
1460
1461 Or it can take a single argument and should set the ready status
1462 regardless of the step as in:
1463
1464 $self->set_ready_validate(0);
1465
1466 =item skip (hook)
1467
1468 Ran at the beginning of the loop before prepare, info_complete, and
1469 finalize are called. If it returns true, nav_loop moves on to the
1470 next step (the current step is skipped).
1471
1472 =item stash (method)
1473
1474 Returns a hashref that can store arbitrary user space data without
1475 worrying about overwriting the internals of the application.
1476
1477 =item step_key (method)
1478
1479 Should return the keyname that will be used by the default "path"
1480 method to look for in the form. Default value is 'step'.
1481
1482 =item swap_template (hook)
1483
1484 Takes the template and hash of variables prepared in print, and processes them
1485 through the current template engine (default engine is CGI::Ex::Template).
1486
1487 Arguments are the template and the swap hashref. The template can be either a
1488 scalar reference to the actual content, or the filename of the content. If the
1489 filename is specified - it should be relative to base_dir_abs.
1490
1491 =item template_args (hook)
1492
1493 Returns a hashref of args that will be passed to the "new" method of CGI::Ex::Template.
1494 By default this hashref contains INCLUDE_PATH which is set equal to base_dir_abs.
1495 It can be augmented with any arguments that CGI::Ex::Template would understand.
1496
1497 sub template_args {
1498 return {
1499 INCLUDE_PATH => '/my/own/include/path',
1500 WRAPPER => 'wrappers/main_wrapper.html',
1501 };
1502 }
1503
1504 =item unmorph (method)
1505
1506 Allows for returning an object back to its previous blessed state if
1507 the "morph" method was successful in morphing the App object. This
1508 only happens if the object was previously morphed into another object
1509 type. Before the object is re-blessed the method fixup_before_unmorph
1510 is called.
1511
1512 See allow_morph and morph.
1513
1514 =item valid_steps (method)
1515
1516 Called by the default path method. Should return a hashref of path
1517 steps that are allowed. If the current step is not found in the hash
1518 (or is not the default_step or js_step) the path method will return a
1519 single step of ->forbidden_step and run its hooks. If no hash or undef is
1520 returned, all paths are allowed (default). A key "forbidden_step"
1521 containing the step that was not valid will be placed in the stash.
1522 Often the valid_steps method does not need to be defined as arbitrary
1523 method calls are not possible with CGI::Ex::App.
1524
1525 Any steps that begin with _ are also "not" valid for passing in via the form
1526 or path info. See the path method.
1527
1528 Also, the pre_step, skip, prepare, and info_complete hooks allow for validating
1529 the data before running finalize.
1530
1531 =item validate (hook)
1532
1533 Passed the form from $self->form. Runs validation on the information
1534 contained in the passed form. Uses CGI::Ex::Validate for the default
1535 validation. Calls the hook hash_validation to load validation hashref
1536 (an empty hash means to pass validation). Should return true if the
1537 form passed validation and false otherwise. Errors are stored as a
1538 hash in $self->{hash_errors} via method add_errors and can be checked
1539 for at a later time with method has_errors (if the default validate
1540 was used).
1541
1542 There are many ways and types to validate the data. Please see the
1543 L<CGI::Ex::Validate> module.
1544
1545 Upon success, it will look through all of the items which were
1546 validated, if any of them contain the keys append_path, insert_path,
1547 or replace_path, that method will be called with the value as
1548 arguments. This allows for the validation to apply redirection to the
1549 path. A validation item of:
1550
1551 {field => 'foo', required => 1, append_path => ['bar', 'baz']}
1552
1553 would append 'bar' and 'baz' to the path should all validation succeed.
1554
1555 =item verify_user (method)
1556
1557 Installed as a hook to CGI::Ex::App during get_valid_auth. Should return
1558 true if the user is ok. Default is to always return true. This can be
1559 used to abort early before the get_pass_by_user hook is called.
1560
1561 sub verify_user {
1562 my ($self, $user) = @_;
1563 return 0 if $user eq 'paul'; # don't let paul in
1564 return 1; # let anybody else in
1565 }
1566
1567 =back
1568
1569 =head1 OTHER APPLICATION MODULES
1570
1571 The concepts used in CGI::Ex::App are not novel or unique. However, they
1572 are all commonly used and very useful. All application builders were
1573 built because somebody observed that there are common design patterns
1574 in CGI building. CGI::Ex::App differs in that it has found more common design
1575 patterns of CGI's than some and tries to get in the way less than others.
1576
1577 CGI::Ex::App is intended to be sub classed, and sub sub classed, and each step
1578 can choose to be sub classed or not. CGI::Ex::App tries to remain simple
1579 while still providing "more than one way to do it." It also tries to avoid
1580 making any sub classes have to call ->SUPER:: (although that is fine too).
1581
1582 There are certainly other modules for building CGI applications. The
1583 following is a short list of other modules and how CGI::Ex::App is
1584 different.
1585
1586 =over 4
1587
1588 =item C<CGI::Application>
1589
1590 Seemingly the most well know of application builders.
1591 CGI::Ex::App is different in that it:
1592
1593 * Uses Template::Toolkit compatible CGI::Ex::Template by default
1594 CGI::Ex::App can easily use another toolkit by simply
1595 overriding the ->swap_template method.
1596 CGI::Application uses HTML::Template.
1597 * Offers integrated data validation.
1598 CGI::Application has had custom plugins created that
1599 add some of this functionality. CGI::Ex::App has the benefit
1600 that validation is automatically available in javascript as well.
1601 * Allows the user to print at any time (so long as proper headers
1602 are sent. CGI::Application requires data to be pipelined.
1603 * Offers hooks into the various phases of each step ("mode" in
1604 CGI::Application lingo). CGI::Application provides only ->runmode
1605 which is only a dispatch.
1606 * Support for easily jumping around in navigation steps.
1607 * Support for storing some steps in another package.
1608
1609 CGI::Ex::App and CGI::Application are similar in that they take care
1610 of handling headers and they allow for calling other "runmodes" from
1611 within any given runmode. CGI::Ex::App's ->run_step is essentially
1612 equivalent to a method call defined in CGI::Application's ->run_modes.
1613 The ->run method of CGI::Application starts the application in the same
1614 manner as CGI::Ex::App's ->navigate call. Many of the hooks around
1615 CGI::Ex::App's ->run_step call are similar in nature to those provided by
1616 CGI::Application.
1617
1618 =item C<CGI::Prototype>
1619
1620 There are actually many similarities. One of the nicest things about
1621 CGI::Prototype is that it is extremely short (very very short). The
1622 ->activate starts the application in the same manner as CGI::Ex::App's
1623 ->navigate call. Both use Template::Toolkit as the default template
1624 system (CGI::Ex::App uses CGI::Ex::Template which is TT compatible).
1625 CGI::Ex::App is differrent in that it:
1626
1627 * Offers integrated data validation.
1628 CGI::Application has had custom addons created that
1629 add some of this functionality. CGI::Ex::App has the benefit
1630 that once validation is created,
1631 * Offers more hooks into the various phases of each step.
1632 * Support for easily jumping around in navigation steps.
1633 * Support for storing only some steps in another package.
1634
1635 =back
1636
1637
1638 =head1 SIMPLE EXTENDED EXAMPLE
1639
1640 The following example shows the creation of a basic recipe
1641 database. It requires the use of DBD::SQLite, but that is all.
1642 Once you have configured the db_file and base_dir_abs methods
1643 of the "recipe" file, you will have a working script that
1644 does CRUD for the recipe table. The observant reader may ask - why
1645 not use Catalyst or Ruby on Rails? The observant programmer will
1646 reply that making a framework do something simple is easy, but making
1647 it do something complex is complex and any framework that tries to
1648 do the those complex things for you is too complex. CGI::Ex::App
1649 lets you write the complex logic but gives you the ability to
1650 not worry about the boring details such as template engines,
1651 or sticky forms, or cgi parameters, or data validation. Once
1652 you are setup and are running, you are only left with providing
1653 the core logic of the application.
1654
1655 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
1656 ### --------------------------------------------
1657 #!/usr/bin/perl -w
1658
1659 use lib qw(/var/www/lib);
1660 use Recipe;
1661 Recipe->navigate;
1662
1663
1664 ### File: /var/www/lib/Recipe.pm
1665 ### --------------------------------------------
1666 package Recipe;
1667
1668 use strict;
1669 use base qw(CGI::Ex::App);
1670 use CGI::Ex::Dump qw(debug);
1671
1672 use DBI;
1673 use DBD::SQLite;
1674
1675 ###------------------------------------------###
1676
1677 sub post_navigate {
1678 # show what happened
1679 debug shift->dump_history;
1680 }
1681
1682 sub base_dir_abs { '/var/www/templates' }
1683
1684 sub base_dir_rel { 'content' }
1685
1686 sub db_file { '/var/www/recipe.sqlite' }
1687
1688 sub dbh {
1689 my $self = shift;
1690 if (! $self->{'dbh'}) {
1691 my $file = $self->db_file;
1692 my $exists = -e $file;
1693 $self->{'dbh'} = DBI->connect("dbi:SQLite:dbname=$file", '', '',
1694 {RaiseError => 1});
1695 $self->create_tables if ! $exists;
1696 }
1697 return $self->{'dbh'};
1698 }
1699
1700 sub create_tables {
1701 my $self = shift;
1702
1703 $self->dbh->do("CREATE TABLE recipe (
1704 id INTEGER PRIMARY KEY AUTOINCREMENT,
1705 title VARCHAR(50) NOT NULL,
1706 ingredients VARCHAR(255) NOT NULL,
1707 directions VARCHAR(255) NOT NULL,
1708 date_added VARCHAR(20) NOT NULL
1709 )");
1710 }
1711
1712 ###----------------------------------------------------------------###
1713
1714 sub main_info_complete { 0 }
1715
1716 sub main_hash_swap {
1717 my $self = shift;
1718
1719 my $s = "SELECT id, title, date_added
1720 FROM recipe
1721 ORDER BY date_added";
1722 my $data = $self->dbh->selectall_arrayref($s);
1723 my @data = map {my %h; @h{qw(id title date_added)} = @$_; \%h} @$data;
1724
1725 return {
1726 recipies => \@data,
1727 };
1728 }
1729
1730 ###----------------------------------------------------------------###
1731
1732 sub add_name_step { 'edit' }
1733
1734 sub add_hash_validation {
1735 return {
1736 'group order' => [qw(title ingredients directions)],
1737 title => {
1738 required => 1,
1739 max_len => 30,
1740 },
1741 ingredients => {
1742 required => 1,
1743 max_len => 255,
1744 },
1745 directions => {
1746 required => 1,
1747 max_len => 255,
1748 },
1749 };
1750 }
1751
1752 sub add_finalize {
1753 my $self = shift;
1754 my $form = $self->form;
1755
1756 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ?";
1757 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'});
1758 if ($count) {
1759 $self->add_errors(title => 'A recipe by this title already exists');
1760 return 0;
1761 }
1762
1763 $s = "INSERT INTO recipe (title, ingredients, directions, date_added)
1764 VALUES (?, ?, ?, ?)";
1765 $self->dbh->do($s, {}, $form->{'title'},
1766 $form->{'ingredients'},
1767 $form->{'directions'},
1768 scalar(localtime));
1769
1770 $self->add_to_form(success => "Recipe added to the database");
1771
1772 return 1;
1773 }
1774
1775 ###----------------------------------------------------------------###
1776
1777 sub edit_skip { shift->form->{'id'} ? 0 : 1 }
1778
1779 sub edit_hash_common {
1780 my $self = shift;
1781 return {} if $self->ready_validate;
1782
1783 my $sth = $self->dbh->prepare("SELECT * FROM recipe WHERE id = ?");
1784 $sth->execute($self->form->{'id'});
1785 my $hash = $sth->fetchrow_hashref;
1786
1787 return $hash;
1788 }
1789
1790 sub edit_hash_validation { shift->add_hash_validation(@_) }
1791
1792 sub edit_finalize {
1793 my $self = shift;
1794 my $form = $self->form;
1795
1796 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ? AND id != ?";
1797 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'}, $form->{'id'});
1798 if ($count) {
1799 $self->add_errors(title => 'A recipe by this title already exists');
1800 return 0;
1801 }
1802
1803 my $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?";
1804 $self->dbh->do($s, {}, $form->{'title'},
1805 $form->{'ingredients'},
1806 $form->{'directions'},
1807 $form->{'id'});
1808
1809 $self->add_to_form(success => "Recipe updated in the database");
1810
1811 return 1;
1812 }
1813
1814 ###----------------------------------------------------------------###
1815
1816 sub view_skip { shift->edit_skip(@_) }
1817
1818 sub view_hash_common { shift->edit_hash_common(@_) }
1819
1820 ###----------------------------------------------------------------###
1821
1822 sub delete_skip { shift->edit_skip(@_) }
1823
1824 sub delete_info_complete { 1 }
1825
1826 sub delete_finalize {
1827 my $self = shift;
1828 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
1829
1830 $self->add_to_form(success => "Recipe deleted from the database");
1831 return 1;
1832 }
1833
1834 1;
1835
1836 __END__
1837
1838
1839
1840 File: /var/www/templates/content/recipe/main.html
1841 ### --------------------------------------------
1842 <html>
1843 <head>
1844 <title>Recipe DB</title>
1845 </head>
1846 <h1>Recipe DB</h1>
1847
1848 [% IF success %]<span style="color:darkgreen"><h2>[% success %]</h2></span>[% END %]
1849
1850 <table style="border:1px solid blue">
1851 <tr><th>#</th><th>Title</th><th>Date Added</th></tr>
1852
1853 [% FOR row IN recipies %]
1854 <tr>
1855 <td>[% loop.count %].</td>
1856 <td><a href="[% script_name %]/view?id=[% row.id %]">[% row.title %]</a>
1857 (<a href="[% script_name %]/edit?id=[% row.id %]">Edit</a>)
1858 </td>
1859 <td>[% row.date_added %]</td>
1860 </tr>
1861 [% END %]
1862
1863 <tr><td colspan=2 align=right><a href="[% script_name %]/add">Add new recipe</a></td></tr>
1864 </table>
1865
1866 </html>
1867
1868
1869 File: /var/www/templates/content/recipe/edit.html
1870 ### --------------------------------------------
1871 <html>
1872 <head>
1873 <title>[% step == 'add' ? "Add" : "Edit" %] Recipe</title>
1874 </head>
1875 <h1>[% step == 'add' ? "Add" : "Edit" %] Recipe</h1>
1876
1877 <form method=post name=[% form_name %]>
1878 <input type=hidden name=step>
1879
1880 <table>
1881
1882 [% IF step != 'add' ~%]
1883 <tr>
1884 <td><b>Id:</b></td><td>[% id %]</td></tr>
1885 <input type=hidden name=id>
1886 </tr>
1887 <tr>
1888 <td><b>Date Added:</b></td><td>[% date_added %]</td></tr>
1889 </tr>
1890 [% END ~%]
1891
1892 <tr>
1893 <td valign=top><b>Title:</b></td>
1894 <td><input type=text name=title>
1895 <span style='color:red' id=title_error>[% title_error %]</span></td>
1896 </tr>
1897 <tr>
1898 <td valign=top><b>Ingredients:</b></td>
1899 <td><textarea name=ingredients rows=10 cols=40 wrap=physical></textarea>
1900 <span style='color:red' id=ingredients_error>[% ingredients_error %]</span></td>
1901 </tr>
1902 <tr>
1903 <td valign=top><b>Directions:</b></td>
1904 <td><textarea name=directions rows=10 cols=40 wrap=virtual></textarea>
1905 <span style='color:red' id=directions_error>[% directions_error %]</span></td>
1906 </tr>
1907 <tr>
1908 <td colspan=2 align=right>
1909 <input type=submit value="[% step == 'add' ? 'Add' : 'Update' %]"></td>
1910 </tr>
1911 </table>
1912 </form>
1913
1914 (<a href="[% script_name %]">Main Menu</a>)
1915 [% IF step != 'add' ~%]
1916 (<a href="[% script_name %]/delete?id=[% id %]">Delete this recipe</a>)
1917 [%~ END %]
1918
1919 [% js_validation %]
1920
1921 </html>
1922
1923
1924 File: /var/www/templates/content/recipe/view.html
1925 ### --------------------------------------------
1926 <html>
1927 <head>
1928 <title>[% title %] - Recipe DB</title>
1929 </head>
1930 <h1>[% title %]</h1>
1931 <h3>Date Added: [% date_added %]</h3>
1932
1933 <h2>Ingredients</h2>
1934 [% ingredients %]
1935
1936 <h2>Directions</h2>
1937 [% directions %]
1938
1939 <hr>
1940 (<a href="[% script_name %]">Main Menu</a>)
1941 (<a href="[% script_name %]/edit?id=[% id %]">Edit this recipe</a>)
1942
1943 </html>
1944
1945 ### --------------------------------------------
1946
1947 Notes:
1948
1949 The dbh method returns an SQLite dbh handle and auto creates the
1950 schema. You will normally want to use MySQL or Oracle, or Postgres
1951 and you will want your schema to NOT be auto-created.
1952
1953 This sample uses hand rolled SQL. Class::DBI or a similar module
1954 might make this example shorter. However, more complex cases that
1955 need to involve two or three or four tables would probably be better
1956 off using the hand crafted SQL.
1957
1958 This sample uses SQL. You could write the application to use whatever
1959 storage you want - or even to do nothing with the submitted data.
1960
1961 We had to write our own HTML (Catalyst and Ruby on Rails do this for
1962 you). For most development work - the HTML should be in a static
1963 location so that it can be worked on by designers. It is nice that
1964 the other frameworks give you stub html - but that is all it is. It
1965 is worth about as much as copying and pasting the above examples. All
1966 worthwhile HTML will go through a non-automated design/finalization
1967 process.
1968
1969 The add step used the same template as the edit step. We did
1970 this using the add_name_step hook which returned "edit". The template
1971 contains IF conditions to show different information if we were in
1972 add mode or edit mode.
1973
1974 We reused code, validation, and templates. Code and data reuse is a
1975 good thing.
1976
1977 The edit_hash_common returns an empty hashref if the form was ready to
1978 validate. When hash_common is called and the form is ready to
1979 validate, that means the form failed validation and is now printing
1980 out the page. To let us fall back and use the "sticky" form fields
1981 that were just submitted, we need to not provide values in the
1982 hash_common method.
1983
1984 We use hash_common. Values from hash_common are used for both
1985 template swapping and filling. We could have used hash_swap and
1986 hash_fill independently.
1987
1988 The hook main_info_complete is hard coded to 0. This basically says
1989 that we will never try and validate or finalize the main step - which
1990 is most often the case.
1991
1992 =head1 SEPARATING STEPS INTO SEPARATE FILES
1993
1994 It may be useful sometimes to separate some or all of the steps of an
1995 application into separate files. This is the way that CGI::Prototype
1996 works. This is useful in cases were some steps and their hooks are
1997 overly large - or are seldom used.
1998
1999 The following modifications can be made to the previous "recipe db"
2000 example that would move the "delete" step into its own file. Similar
2001 actions can be taken to break other steps into their own file as well.
2002
2003
2004 ### File: /var/www/lib/Recipe.pm
2005 ### Same as before but add the following line:
2006 ### --------------------------------------------
2007
2008 sub allow_morph { 1 }
2009
2010
2011 ### File: /var/www/lib/Recipe/Delete.pm
2012 ### Remove the delete_* subs from lib/Recipe.pm
2013 ### --------------------------------------------
2014 package Recipe::Delete;
2015
2016 use strict;
2017 use base qw(Recipe);
2018
2019 sub skip { shift->edit_skip(@_) }
2020
2021 sub info_complete { 1 }
2022
2023 sub finalize {
2024 my $self = shift;
2025 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
2026
2027 $self->add_to_form(success => "Recipe deleted from the database");
2028 return 1;
2029 }
2030
2031
2032 Notes:
2033
2034 The hooks that are called (skip, info_complete, and finalize) do not
2035 have to be prefixed with the step name because they are now in their
2036 own individual package space. However, they could still be named
2037 delete_skip, delete_info_complete, and delete_finalize and the
2038 run_hook method will find them (this would allow several steps with
2039 the same "morph_package" to still be stored in the same external
2040 module).
2041
2042 The method allow_morph is passed the step that we are attempting to
2043 morph to. If allow_morph returns true every time, then it will try
2044 and require the extra packages every time that step is ran. You could
2045 limit the morphing process to run only on certain steps by using code
2046 similar to the following:
2047
2048 sub allow_morph { return {delete => 1} }
2049
2050 # OR
2051
2052 sub allow_morph {
2053 my ($self, $step) = @_;
2054 return ($step eq 'delete') ? 1 : 0;
2055 }
2056
2057 The CGI::Ex::App temporarily blesses the object into the
2058 "morph_package" for the duration of the step and re-blesses it into the
2059 original package upon exit. See the morph method and allow_morph for more
2060 information.
2061
2062 =head1 RUNNING UNDER MOD_PERL
2063
2064 The previous samples are essentially suitable for running under flat CGI,
2065 Fast CGI, or mod_perl Registry or mod_perl PerlRun type environments. It
2066 is very easy to move the previous example to be a true mod_perl handler.
2067
2068 To convert the previous recipe example, simply add the following:
2069
2070 ### File: /var/www/lib/Recipe.pm
2071 ### Same as before but add the following lines:
2072 ### --------------------------------------------
2073
2074 sub handler {
2075 Recipe->navigate;
2076 return;
2077 }
2078
2079
2080 ### File: apache2.conf - or whatever your apache conf file is.
2081 ### --------------------------------------------
2082 <Location /recipe>
2083 SetHandler perl-script
2084 PerlHandler Recipe
2085 </Location>
2086
2087 Notes:
2088
2089 Both the /cgi-bin/recipe version and the /recipe version can co-exist.
2090 One of them will be a normal cgi and the other will correctly use
2091 mod_perl hooks for headers.
2092
2093 Setting the location to /recipe means that the $ENV{SCRIPT_NAME} will
2094 also be set to /recipe. This means that name_module method will
2095 resolve to "recipe". If a different URI location is desired such as
2096 "/my_cool_recipe" but the program is to use the same template content
2097 (in the /var/www/templates/content/recipe directory), then we would
2098 need to explicitly set the "name_module" parameter. It could be done
2099 in either of the following ways:
2100
2101 ### File: /var/www/lib/Recipe.pm
2102 ### Same as before but add the following line:
2103 ### --------------------------------------------
2104
2105 sub name_module { 'recipe' }
2106
2107 # OR
2108
2109 sub init {
2110 my $self = shift;
2111 $self->{'name_module'} = 'recipe';
2112 }
2113
2114 In most use cases it isn't necessary to set name_module, but it also
2115 doesn't hurt and in all cases it is more descriptive to anybody who is
2116 going to maintain the code later.
2117
2118 =head1 ADDING AUTHENTICATION TO THE ENTIRE APPLICATION
2119
2120 Having authentication is sometimes a good thing. To force
2121 the entire application to be authenticated (require a valid username
2122 and password before doing anything) you could do the following.
2123
2124 ### File: /var/www/lib/Recipe.pm
2125 ### Same as before but add
2126 ### --------------------------------------------
2127
2128 sub get_pass_by_user {
2129 my $self = shift;
2130 my $user = shift;
2131 my $pass = $self->lookup_and_cache_the_pass($user);
2132 return $pass;
2133 }
2134
2135
2136 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2137 ### Change the line with ->navigate; to
2138 ### --------------------------------------------
2139
2140 Recipe->navigate_authenticated;
2141
2142 # OR
2143
2144 ### File: /var/www/lib/Recipe.pm
2145 ### Same as before but add
2146 ### --------------------------------------------
2147
2148 sub require_auth { 1 }
2149
2150 # OR
2151
2152 ### File: /var/www/lib/Recipe.pm
2153 ### Same as before but add
2154 ### --------------------------------------------
2155
2156 sub init { shift->require_auth(1) }
2157
2158 See the require_auth, get_valid_auth, and auth_args methods for more information.
2159 Also see the L<CGI::Ex::Auth> perldoc.
2160
2161 =head1 ADDING AUTHENTICATION TO INDIVIDUAL STEPS
2162
2163 Sometimes you may only want to have certain steps require
2164 authentication. For example, in the previous recipe example we
2165 might want to let the main and view steps be accessible to anybody,
2166 but require authentication for the add, edit, and delete steps.
2167
2168 To do this, we would do the following to the original example (the
2169 navigation must start with ->navigate. Starting with ->navigate_authenticated
2170 will cause all steps to require validation):
2171
2172 ### File: /var/www/lib/Recipe.pm
2173 ### Same as before but add
2174 ### --------------------------------------------
2175
2176 sub get_pass_by_user {
2177 my $self = shift;
2178 my $user = shift;
2179 my $pass = $self->lookup_and_cache_the_pass($user);
2180 return $pass;
2181 }
2182
2183 sub require_auth { {add => 1, edit => 1, delete => 1} }
2184
2185 That's it. The add, edit, and delete steps will now require authentication.
2186 See the require_auth, get_valid_auth, and auth_args methods for more information.
2187 Also see the L<CGI::Ex::Auth> perldoc.
2188
2189 =head1 THANKS
2190
2191 Bizhosting.com - giving a problem that fit basic design patterns.
2192
2193 Earl Cahill - pushing the idea of more generic frameworks.
2194
2195 Adam Erickson - design feedback, bugfixing, feature suggestions.
2196
2197 James Lance - design feedback, bugfixing, feature suggestions.
2198
2199 =head1 AUTHOR
2200
2201 Paul Seamons <paul at seamons dot com>
2202
2203 =cut
This page took 0.116629 seconds and 3 git commands to generate.