]> Dogcows Code - chaz/p5-CGI-Ex/blob - lib/CGI/Ex/App.pod
CGI::Ex 2.09
[chaz/p5-CGI-Ex] / lib / CGI / Ex / App.pod
1 =head1 NAME
2
3 CGI::Ex::App - Anti-framework application framework.
4
5 =head1 SYNOPSIS
6
7 #!/usr/bin/perl -w
8
9 use strict;
10 use base qw(CGI::Ex::App);
11
12 __PACKAGE__->navigate;
13 exit;
14
15 sub main_file_print {
16 return \ "Hello World";
17 }
18
19 There is a longer "SYNOPSIS" after the process flow discussion.
20
21 =head1 DESCRIPTION
22
23 Fill in the blanks and get a ready made web application.
24
25 This module is somewhat similar in spirit to CGI::Application,
26 CGI::Path, and CGI::Builder and any other "CGI framework." As with
27 the others, CGI::Ex::App tries to do as much of the mundane things, in
28 a simple manner, without getting in the developer's way. However,
29 there are various design patterns for CGI applications that
30 CGI::Ex::App handles for you that the other frameworks require you to
31 bring in extra support. The entire CGI::Ex suite has been taylored to
32 work seamlessly together. Your mileage in building applications may
33 vary.
34
35 If you build applications that submit user information, validate it,
36 re-display it, fill in forms, or separate logic into separate modules,
37 then this module may be for you. If all you need is a dispatch
38 engine, then this still may be for you. If all you want is to look at
39 user passed information, then this may still be for you. If you like
40 writing bare metal code, this could still be for you. If you don't want
41 to write any code, this module will help - but you still need to
42 provide your key actions and html.
43
44 One of the great benefits of CGI::Ex::App vs. Catalyst or Rails style
45 frameworks is that the model of CGI::Ex::App can be much more abstract.
46 And models often are abstract.
47
48 =head1 DEFAULT PROCESS FLOW
49
50 The following pseudo-code describes the process flow
51 of the CGI::Ex::App framework. Several portions of the flow
52 are encapsulated in hooks which may be completely overridden to give
53 different flow. All of the default actions are shown. It may look
54 like a lot to follow, but if the process is broken down into the
55 discrete operations of step iteration, data validation, and template
56 printing the flow feels more natural.
57
58 =head2 navigate
59
60 The process starts off by calling ->navigate.
61
62 navigate {
63 eval {
64 ->pre_navigate
65 ->nav_loop
66 ->post_navigate
67 }
68 # dying errors will run the ->handle_error method
69
70 ->destroy
71 }
72
73 =head2 nav_loop
74
75 The nav_loop method will run as follows:
76
77 nav_loop {
78 ->path (get the array of path steps)
79 # ->path_info_map_base (method - map ENV PATH_INFO to form)
80 # look in ->form for ->step_key
81 # make sure step is in ->valid_steps (if defined)
82
83 ->pre_loop($path)
84 # navigation stops if true
85
86 foreach step of path {
87
88 ->morph
89 # check ->allow_morph
90 # check ->allow_nested_morph
91 # ->morph_package (hook - get the package to bless into)
92 # ->fixup_after_morph if morph_package exists
93 # if no package is found, process continues in current file
94
95 ->path_info_map (hook - map PATH_INFO to form)
96
97 ->run_step (hook)
98
99 ->refine_path (hook)
100 # only called if run_step returned false (page not printed)
101 ->next_step (hook) # find next step and add to path
102 ->set_ready_validate(0) (hook)
103
104 ->unmorph
105 # only called if morph worked
106 # ->fixup_before_unmorph if blessed to current package
107
108 # exit loop if ->run_step returned true (page printed)
109
110 } end of foreach step
111
112 ->post_loop
113 # navigation stops if true
114
115 ->default_step
116 ->insert_path (puts the default step into the path)
117 ->nav_loop (called again recursively)
118
119 } end of nav_loop
120
121 =head2 run_step (hook)
122
123 For each step of the path the following methods will be run
124 during the run_step hook.
125
126 run_step {
127 ->pre_step (hook)
128 # exits nav_loop if true
129
130 ->skip (hook)
131 # skips this step if true (stays in nav_loop)
132
133 ->prepare (hook - defaults to true)
134
135 ->info_complete (hook - ran if prepare was true)
136 ->ready_validate (hook)
137 return false if ! ready_validate
138 ->validate (hook - uses CGI::Ex::Validate to validate form info)
139 ->hash_validation (hook)
140 ->file_val (hook)
141 ->base_dir_abs
142 ->base_dir_rel
143 ->name_module
144 ->name_step
145 ->ext_val
146 returns true if validate is true or if nothing to validate
147
148 ->finalize (hook - defaults to true - ran if prepare and info_complete were true)
149
150 if ! ->prepare || ! ->info_complete || ! ->finalize {
151 ->prepared_print
152 ->hash_base (hook)
153 ->hash_common (hook)
154 ->hash_form (hook)
155 ->hash_fill (hook)
156 ->hash_swap (hook)
157 ->hash_errors (hook)
158 # merge form, base, common, and fill into merged fill
159 # merge form, base, common, swap, and errors into merged swap
160 ->print (hook - passed current step, merged swap hash, and merged fill)
161 ->file_print (hook - uses base_dir_rel, name_module, name_step, ext_print)
162 ->swap_template (hook - processes the file with CGI::Ex::Template)
163 ->template_args (hook - passed to CGI::Ex::Template->new)
164 ->fill_template (hook - fills the any forms with CGI::Ex::Fill)
165 ->fill_args (hook - passed to CGI::Ex::Fill::fill)
166 ->print_out (hook - print headers and the content to STDOUT)
167
168 ->post_print (hook - used for anything after the print process)
169
170 # return true to exit from nav_loop
171 }
172
173 ->post_step (hook)
174 # exits nav_loop if true
175
176 } end of run_step
177
178 It is important to learn the function and placement of each of the
179 hooks in the process flow in order to make the most of CGI::Ex::App.
180 It is enough to begin by learning a few common hooks - such as
181 hash_validation, hash_swap, and finalize, and then learn about other
182 hooks as needs arise. Sometimes, it is enough to simply override the
183 run_step hook and take care of processing the entire step yourself.
184
185 Because of the hook based system, and because CGI::Ex::App uses
186 sensible defaults, it is very easy to override a little or a lot which
187 ends up giving the developer a lot of flexibility.
188
189 Additionally, it should be possible to use CGI::Ex::App with the other
190 frameworks such as CGI::Application or CGI::Prototype. For these you
191 could simple let each "runmode" call the run_step hook of CGI::Ex::App
192 and you will instantly get all of the common process flow for free.
193
194 =head1 MAPPING URI TO STEP
195
196 The default out of the box configuration will map URIs to steps as follows:
197
198 # Assuming /cgi-bin/my_app is the program being run
199
200 URI: /cgi-bin/my_app
201 STEP: main
202 FORM: {}
203 WHY: No other information is passed. The path method is
204 called which eventually calls ->default_step which
205 defaults to "main"
206
207 URI: /cgi-bin/my_app?foo=bar
208 STEP: main
209 FORM: {foo => "bar"}
210 WHY: Same as previous example except that QUERY_STRING
211 information was passed and placed in form.
212
213 URI: /cgi-bin/my_app?step=my_step
214 STEP: my_step
215 FORM: {step => "my_step"}
216 WHY: The path method is called which looks in $self->form
217 for the key ->step_key (which defaults to "step").
218
219 URI: /cgi-bin/my_app?step=my_step&foo=bar
220 STEP: my_step
221 FORM: {foo => "bar", step => "my_step"}
222 WHY: Same as before but has other parameters were passed.
223
224 URI: /cgi-bin/my_app/my_step
225 STEP: my_step
226 FORM: {step => "my_step"}
227 WHY: The path method is called which called path_info_map_base
228 which matched $ENV{'PATH_INFO'} using the default regex
229 of qr{^/(\w+)$} and place the result in
230 $self->form->{$self->step_key}. Path then looks in
231 $self->form->{$self->step_key} for the initial step. See
232 the path_info_map_base method for more information.
233
234 URI: /cgi-bin/my_app/my_step?foo=bar
235 STEP: my_step
236 FORM: {foo => "bar", step => "my_step"}
237 WHY: Same as before but other parameters were passed.
238
239 URI: /cgi-bin/my_app/my_step?step=other_step
240 STEP: other_step
241 FORM: {step => "other_step"}
242 WHY: The same procedure took place, but when the PATH_INFO
243 string was matched, the form key "step" already existed
244 and was not replaced by the value from PATH_INFO.
245
246 The remaining examples in this section are based on the assumption
247 that the following method is installed in your script.
248
249 sub my_step_path_info_map {
250 return [
251 [qr{^/\w+/(\w+)/(\d+)$}, 'foo', 'id'],
252 [qr{^/\w+/(\w+)$}, 'foo'],
253 [qr{^/\w+/(.+)$}, 'anything_else'],
254 ];
255 }
256
257 URI: /cgi-bin/my_app/my_step/bar
258 STEP: my_step
259 FORM: {foo => "bar"}
260 WHY: The step was matched as in previous examples using
261 path_info_map_base. However, the form key "foo"
262 was set to "bar" because the second regex returned
263 by the path_info_map hook matched the PATH_INFO string
264 and the corresponding matched value was placed into
265 the form using the keys specified following the regex.
266
267 URI: /cgi-bin/my_app/my_step/bar/1234
268 STEP: my_step
269 FORM: {foo => "bar", id => "1234"}
270 WHY: Same as the previous example, except that the first
271 regex matched the string. The first regex had two
272 match groups and two form keys specified. Note that
273 it is important to order your match regexes in the
274 order that will match the most data. The third regex
275 would also match this PATH_INFO.
276
277 URI: /cgi-bin/my_app/my_step/some/other/type/of/data
278 STEP: my_step
279 FORM: {anything_else => 'some/other/type/of/data'}
280 WHY: Same as the previous example, except that the third
281 regex matched.
282
283 URI: /cgi-bin/my_app/my_step/bar?bling=blang
284 STEP: my_step
285 FORM: {foo => "bar", bling => "blang"}
286 WHY: Same as the first step, but additional QUERY_STRING
287 information was passed.
288
289 URI: /cgi-bin/my_app/my_step/one%20two?bar=three%20four
290 STEP: my_step
291 FORM: {anything_else => "one two", bar => "three four"}
292 WHY: The third path_info_map regex matched. Note that the
293 %20 in bar was unescaped by CGI::param, but the %20
294 in anything_else was unescaped by Apache. If you are
295 not using Apache, this behavior may vary. CGI::Ex::App
296 doesn't decode parameters mapped from PATH_INFO.
297
298 See the path method for more information about finding the initial step
299 of the path.
300
301 The form method calls CGI::Ex::form which uses CGI::param to retrieve
302 GET and POST parameters. See the form method for more information on
303 how GET and POST parameters are parsed.
304
305 See the path_info_map_base method, and path_info_map hook for more information
306 on how the path_info maps function.
307
308 Using the following code is very useful for determing what hooks have
309 taken place:
310
311 use CGI::Ex::Dump qw(debug);
312
313 sub post_navigate {
314 my $self = shift;
315 debug $self->dump_history, $self->form;
316 }
317
318 =head1 ADDING DATA VALIDATION TO A STEP
319
320 CGI::Ex::App uses CGI::Ex::Validate for its data validation. See CGI::Ex::Validate
321 for more information about the many ways you can validate your data.
322
323 The default hash_validation hook returns an empty hashref. This means that passed
324 in data is all valid and the script will automatically call the step's finalize method.
325
326 The following shows how to some contrived validation to a step called "my_step".
327
328 sub my_step_hash_validation {
329 return {
330 username => {
331 required => 1,
332 match => 'm/^(\w+)$/',
333 match_error => 'The $field field may only contain word characters',
334 max_len => 20,
335 },
336 password => {
337 required => 1,
338 max_len => 15,
339 },
340 password_verify => {
341 validate_if => 'password',
342 equals => 'password',
343 },
344 usertype => {
345 required => 1,
346 enum => [qw(animal vegetable mineral)],
347 },
348 };
349 }
350
351 The step will continue to display the html form until all of the fields pass
352 validation.
353
354 See the hash_validation hook and validate hook for more information about how
355 this takes place.
356
357 =head1 ADDING JAVASCRIPT DATA VALIDATION TO A STEP
358
359 You must first provide a hash_validation hook as explained in the previous section.
360
361 Once you have a hash_validation hook, you would place the following tags
362 into your HTML template.
363
364 <form name="[% form_name %]" method="post">
365 ...
366 </form>
367 [% js_validation %]
368
369 The "form_name" swap-in places a name on the form that the javascript returned by
370 the js_validation swap-in will be able to find and check for validity.
371
372 See the hash_validation, js_validation, and form_name hooks for more information.
373
374 Also, CGI::Ex::validate.js allows for inline errors in addition to or in replacement
375 of an alert message. To use inline errors, you must provide an element in your
376 HTML document where this inline message can be placed. The common way to do it is as
377 follows:
378
379 <input type="text" name="username"><br>
380 <span class="error" id="username_error">[% username_error %]</span>
381
382 The span around the error allows for the error css class and it provides a location
383 that the Javascript validation can populate with errors. The [% username_error %] provides
384 a location for errors generated on the server side to be swapped in. If there was no error
385 the [% username_error %] tag would default to "".
386
387 =head1 ADDING ADDITIONAL TEMPLATE VARIABLES
388
389 All variables returned by the hash_base, hash_common, hash_form, hash_swap, and
390 hash_errors hooks are available for swapping in templates.
391
392 The following shows how to add variables using the hash_swap hook on the step "main".
393
394 sub main_hash_swap {
395 return {
396 color => 'red',
397 choices => [qw(one two three)],
398 "warn" => sub { warn @_ },
399 };
400 }
401
402 You could also return the fields from the hash_common hook and they would be available
403 in both the template swapping as well as form filling.
404
405 See the hash_base, hash_common, hash_form, hash_swap, hash_errors, swap_template, and
406 template_args hooks for more information.
407
408 The default template engine used is CGI::Ex::Template which is Template::Toolkit compatible.
409 See the CGI::Ex::Template or Template::Toolkit documentation for the types of data
410 that can be passed, and for the syntax that can be used.
411
412 =head1 ADDING ADDITIONAL FORM FILL VARIABLES
413
414 All variables returned by the hash_base, hash_common, hash_form, and hash_fill hooks
415 are available for filling html fields in on templates.
416
417 The following shows how to add variables using the hash_fill hook on the step "main".
418
419 sub main_hash_fill {
420 return {
421 color => 'red',
422 choices => [qw(one two three)],
423 };
424 }
425
426 You could also return the fields from the hash_common hook and they would be available
427 in both the form filling as well as in the template swapping.
428
429 See the hash_base, hash_common, hash_form, hash_swap, hash_errors, fill_template, and
430 fill_args hooks for more information.
431
432 The default form filler is CGI::Ex::Fill which is similar to HTML::FillInForm but
433 has several benefits. See the CGI::Ex::Fill module for the available options.
434
435 =head1 FINDING TEMPLATES AND VALIDATION FILES
436
437 CGI::Ex::App tries to help your applications use a good template directory layout, but allows
438 for you to override everything.
439
440 External template files are used for storing your html templates and
441 for storing your validation files (if you use externally stored
442 validation files).
443
444 The default file_print hook will look for content on your file system,
445 but it can also be completely overridden to return a reference to a
446 scalar containing the contents of your file. Actually it can return
447 anything that CGI::Ex::Template (Template::Toolkit compatible) will
448 treat as input. This templated html is displayed to the user during
449 any step that enters the "print" phase.
450
451 Similarly the default file_val hook will look for a validation file on
452 the file system, but it too can return a reference to a scalar
453 containing the contents of a validation file. It may actually return
454 anything that the CGI::Ex::Validate get_validation method is able to
455 understand. This validation is used by the default "info_complete"
456 method for verifying if the submitted information passes its specific
457 checks. A more common way of inlining validation is to return a
458 validation hash from a hash_validation hook override.
459
460 If the default file_print and file_val hooks are used, the following methods
461 are employed for finding templates and validation files on your filesystem (they
462 are also documented more in the HOOKS AND METHODS section.
463
464 =over 4
465
466 =item base_dir_abs
467
468 Absolute path or arrayref of paths to the base templates directory. Default "".
469
470 =item base_dir_rel
471
472 Relative path inside of the base_dir_abs directory where content can be found. Default "".
473
474 =item name_module
475
476 Directory inside of base_dir_rel where files for the current CGI (module) will be
477 stored. Default value is $ENV{SCRIPT_NAME} with path and extension removed.
478
479 =item name_step
480
481 Used with ext_print and ext_val for creating the filename that will be looked for
482 inside of the name_module directory. Default value is the current step.
483
484 =item ext_print and ext_val
485
486 Filename extensions added to name_step to create the filename looked for
487 inside of the name_module directory. Default is "html" for ext_print and "val"
488 for ext_val.
489
490 =back
491
492 It may be easier to understand the usage of each of these methods by showing
493 a contrived example. The following is a hypothetical layout for your templates:
494
495 /home/user/templates/
496 /home/user/templates/chunks/
497 /home/user/templates/wrappers/
498 /home/user/templates/content/
499 /home/user/templates/content/my_app/
500 /home/user/templates/content/my_app/main.html
501 /home/user/templates/content/my_app/step1.html
502 /home/user/templates/content/my_app/step1.val
503 /home/user/templates/content/another_cgi/main.html
504
505 In this example we would most likely set values as follows:
506
507 base_dir_abs /home/user/templates
508 base_dir_rel content
509 name_module my_app
510
511 The name_module method defaults to the name of the running program, but
512 with the path and extension removed. So if we were running
513 /cgi-bin/my_app.pl, /cgi-bin/my_app, or /anypath/my_app, then
514 name_module would default to "my_app" and we wouldn't have to
515 hard code the value. Often it is wise to set the value anyway so
516 that we can change the name of the cgi script without effecting
517 where template content should be stored.
518
519 Continuing with the example and assuming that name of the step that
520 the user has requested is "step1" then the following values would be
521 returned:
522
523 base_dir_abs /home/user/templates
524 base_dir_rel content
525 name_module my_app
526 name_step step1
527 ext_print html
528 ext_val val
529
530 file_print content/my_app/step1.html
531 file_val /home/user/templates/content/my_app/step1.val
532
533 The call to the template engine would look something like
534 the following:
535
536 my $t = $self->template_obj({
537 INCLUDE_PATH => $self->base_dir_abs,
538 });
539
540 $t->process($self->file_print($step), \%vars);
541
542 The template engine would then look for the relative file
543 inside of the absolute paths (from base_dir_abs).
544
545 The call to the validation engine would pass the absolute
546 filename that is returned by file_val.
547
548 The name_module and name_step methods can return filenames with
549 additional directories included. The previous example could
550 also have been setup using the following values:
551
552 base_dir_abs /home/user/templates
553 base_dir_rel
554 name_module content/my_app
555
556 In this case the same values would be returned for the file_print and file_val hooks
557 as were returned in the previous setup.
558
559 =head1 SYNOPSIS (A LONG "SYNOPSIS")
560
561 This example script would most likely be in the form of a cgi, accessible via
562 the path http://yourhost.com/cgi-bin/my_app (or however you do CGIs on
563 your system. About the best way to get started is to paste the following
564 code into a cgi script (such as cgi-bin/my_app) and try it out. A detailed
565 walk-through follows in the next section. There is also a longer recipe
566 database example at the end of this document that covers other topics including
567 making your module a mod_perl handler.
568
569 ### File: /var/www/cgi-bin/my_app (depending upon Apache configuration)
570 ### --------------------------------------------
571 #!/usr/bin/perl -w
572
573 use strict;
574 use base qw(CGI::Ex::App);
575 use CGI::Ex::Dump qw(debug);
576
577 __PACKAGE__->navigate;
578 # OR
579 # my $obj = __PACKAGE__->new;
580 # $obj->navigate;
581
582 exit;
583
584 ###------------------------------------------###
585
586 sub post_navigate {
587 # show what happened
588 debug shift->dump_history;
589 }
590
591 sub main_hash_validation {
592 return {
593 'general no_alert' => 1,
594 'general no_confirm' => 1,
595 'group order' => [qw(username password password2)],
596 username => {
597 required => 1,
598 min_len => 3,
599 max_len => 30,
600 match => 'm/^\w+$/',
601 match_error => 'You may only use letters and numbers.',
602 },
603 password => {
604 required => 1,
605 min_len => 6,
606 },
607 password2 => {
608 equals => 'password',
609 },
610 };
611 }
612
613 sub main_file_print {
614 # reference to string means ref to content
615 # non-reference means filename
616 return \ "<h1>Main Step</h1>
617 <form method=post name=[% form_name %]>
618 <input type=hidden name=step>
619 <table>
620 <tr>
621 <td><b>Username:</b></td>
622 <td><input type=text name=username><span style='color:red' id=username_error>[% username_error %]</span></td>
623 </tr><tr>
624 <td><b>Password:</b></td>
625 <td><input type=text name=password><span style='color:red' id=password_error>[% password_error %]</span></td>
626 </tr><tr>
627 <td><b>Verify Password:</b></td>
628 <td><input type=text name=password2><span style='color:red' id=password2_error>[% password2_error %]</span></td>
629 </tr>
630 <tr><td colspan=2 align=right><input type=submit></td></tr>
631 </table>
632 </form>
633 [% js_validation %]
634 ";
635 }
636
637 sub main_finalize {
638 my $self = shift;
639
640 if ($self->form->{'username'} eq 'bar') {
641 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
642 return 0;
643 }
644
645 debug $self->form, "Do something useful with form here in the finalize hook.";
646
647 ### add success step
648 $self->add_to_swap({success_msg => "We did something"});
649 $self->append_path('success');
650 $self->set_ready_validate(0);
651 return 1;
652 }
653
654 sub success_file_print {
655 \ "<div style=background:lightblue>
656 <h1>Success Step - [% success_msg %]</h1>
657 Username: <b>[% username %]</b><br>
658 Password: <b>[% password %]</b><br>
659 </div>
660 ";
661 }
662
663 __END__
664
665 Note: This example would be considerably shorter if the html file
666 (file_print) and the validation file (file_val) had been placed in
667 separate files. Though CGI::Ex::App will work "out of the box" as
668 shown it is more probable that any platform using it will customize
669 the various hooks to their own tastes (for example, switching print to
670 use a templating system other than CGI::Ex::Template).
671
672 =head1 SYNOPSIS STEP BY STEP
673
674 This section goes step by step over the previous example.
675
676 Well - we start out with the customary CGI introduction.
677
678 #!/usr/bin/perl -w
679
680 use strict;
681 use base qw(CGI::Ex::App);
682 use CGI::Ex::Dump qw(debug);
683
684 Note: the "use base" is not normally used in the "main" portion of a script.
685 It does allow us to just do __PACKAGE__->navigate.
686
687 Now we need to invoke the process:
688
689 __PACKAGE__->navigate;
690 # OR
691 # my $obj = __PACKAGE__->new;
692 # $obj->navigate;
693 exit;
694
695 Note: the "exit" isn't necessary - but it is kind of nice to infer
696 that process flow doesn't go beyond the ->navigate call.
697
698 The navigate routine is now going to try and "run" through a series of
699 steps. Navigate will call the ->path method which should return an
700 arrayref containing the valid steps. By default, if path method has
701 not been overridden, the path method will default first to the step
702 found in form key named ->step_name, then it will fall to the contents
703 of $ENV{'PATH_INFO'}. If navigation runs out of steps to run it will
704 run the step found in ->default_step which defaults to 'main'. So the
705 URI '/cgi-bin/my_app' would run the step 'main' first by default. The
706 URI '/cgi-bin/my_app?step=foo' would run the step 'foo' first. The
707 URI '/cgi-bin/my_app/bar' would run the step 'bar' first.
708
709 CGI::Ex::App allows for running steps in a preset path or each step may
710 choose the next step that should follow. The navigate
711 method will go through one step of the path at a time and see if it is
712 completed (various methods determine the definition of "completed").
713 This preset type of path can also be automated using the CGI::Path
714 module. Rather than using a preset path, CGI::Ex::App also has
715 methods that allow for dynamic changing of the path, so that each step
716 can determine which step to do next (see the jump, append_path,
717 insert_path, and replace_path methods).
718
719 During development it would be nice to see what happened during the
720 course of our navigation. This is stored in the arrayref contained in
721 ->history. There is a method that is called after all of the navigation
722 has taken place called "post_navigate". This chunk will display history after we
723 have printed the content.
724
725 sub post_navigate {
726 debug shift->dump_history;
727 } # show what happened
728
729 Ok. Finally we are looking at the methods used by each step of the path. The
730 hook mechanism of CGI::Ex::App will look first for a method ${step}_${hook_name}
731 called before falling back to the method named $hook_name. Internally in the
732 code there is a call that looks like $self->run_hook('hash_validation', $step). In
733 this case the step is main. The dispatch mechanism finds our method at the following
734 chunk of code.
735
736 sub main_hash_validation { ... }
737
738 The process flow will see if the data is ready to validate. Once it is ready
739 (usually when the user presses the submit button) the data will be validated. The
740 hash_validation hook is intended to describe the data and will be tested
741 using CGI::Ex::Validate. See the CGI::Ex::Validate perldoc for more
742 information about the many types of validation available.
743
744 sub main_file_print { ... }
745
746 The navigation process will see if user submitted information (the form)
747 is ready for validation. If not, or if validation fails, the step needs to
748 be printed. Eventually the file_print hook is called. This hook should
749 return either the filename of the template to be printed, or a reference
750 to the actual template content. In this example we return a reference
751 to the content to be printed (this is useful for prototyping applications
752 and is also fine in real world use - but generally production applications
753 use external html templates).
754
755 A few things to note about the template:
756
757 First, we add a hidden form field called step. This will be filled in
758 automatically at a later point with the current step we are on.
759
760 We provide locations to swap in inline errors.
761
762 <span style="color:red" id="username_error">[% username_error %]</span>
763
764 As part of the error html we name each span with the name of the error. This
765 will allow for us to have Javascript update the error spots when the javascript
766 finds an error.
767
768 At the very end we add the TT variable [% js_validation %]. This swap in is
769 provided by the default hash_base hook and will provide for form data to be
770 validated using javascript.
771
772 Once the process flow has deemed that the data is validated, it then calls
773 the finalize hook. Finalize is where the bulk of operations should go.
774 We'll look at it more in depth.
775
776 sub main_finalize {
777 my $self = shift;
778 my $form = $self->form;
779
780 At this point, all of the validated data is in the $form hashref.
781
782 if ($form->{'username'} eq 'bar') {
783 $self->add_errors(username => 'A trivial check to say the username cannot be "bar"');
784 return 0;
785 }
786
787 It is most likely that though the data is of the correct type and formatting,
788 it still isn't completely correct. This previous section shows a hard coded
789 test to see if the username was 'bar'. If it was then an appropriate error will
790 be set, the routine returns 0 and the run_step process knows that it needs to
791 redisplay the form page for this step. The username_error will be shown inline.
792 The program could do more complex things such as checking to see if the username
793 was already taken in a database.
794
795 debug $form, "Do something useful with form here in the finalize hook.";
796
797 This debug $form piece is simply a place holder. It is here that the program would
798 do something useful such as add the information to a database.
799
800 ### add success step
801 $self->add_to_swap({success_msg => "We did something"});
802
803 Now that we have finished finalize, we add a message that will be passed to the template
804 engine.
805
806 $self->append_path('success');
807 $self->set_ready_validate(0);
808
809 The program now needs to move on to the next step. In this case we want to
810 follow with a page that informs us we succeeded. So, we append a step named "success".
811 We also call set_ready_validate(0) to inform the navigation control that the
812 form is no longer ready to validate - which will cause the success page to
813 print without trying to validate the data. It is normally a good idea
814 to set this as leaving the engine in a "ready to validate" state can result
815 in an recursive loop (that will be caught).
816
817 return 1;
818 }
819
820 We then return 1 which tells the engine that we completed this step successfully
821 and it needs to move on to the next step.
822
823 Finally we run the "success" step because we told it to. That step isn't
824 ready to validate so it prints out the template page.
825
826 For more of a real world example, it would be good to read the sample recipe db
827 application included at the end of this document.
828
829 =head1 AVAILABLE METHODS / HOOKS
830
831 CGI::Ex::App's dispatch system works on the principles of hooks (which
832 are essentially glorified method lookups). When the run_hook method
833 is called, CGI::Ex::App will look for a corresponding method call for
834 that hook for the current step name. It is perhaps easier to show than
835 to explain.
836
837 If we are calling the "print" hook for the step "edit" we would call
838 run_hook like this:
839
840 $self->run_hook('print', 'edit', $template, \%swap, \%fill);
841
842 This would first look for a method named "edit_print". If it is unable to
843 find a method by that name, it will look for a method named "print". If it
844 is unable to find this method - it will die.
845
846 If allow_morph is set to true, the same methods are searched for but it becomes
847 possible to move some of those methods into an external package.
848
849 See the discussions under the methods named "find_hook" and "run_hook" for more details.
850
851 The following is the alphabetical list of methods and hooks.
852
853 =over 4
854
855 =item allow_morph (method)
856
857 Should return true if this step is allowed to "morph" the current App
858 object into another package. Default is false. It is passed a single
859 argument of the current step. For more granularity, if true value is
860 a hash, the step being morphed to must be in the hash.
861
862 To enable morphing for all steps, add the following:
863
864 sub allow_morph { 1 }
865
866 To enable morph on specific steps, do either of the following:
867
868 sub allow_morph {
869 return {
870 edit => 1,
871 delete => 1,
872 };
873 }
874
875 # OR
876
877 sub allow_morph {
878 my ($self, $step) = @_;
879 return $step =~ /^(edit|delete)$/;
880 }
881
882 See the morph "hook" for more information.
883
884 =item allow_nested_morph (method)
885
886 Similar to the allow_morph hook, but allows for one more level of morphing.
887 This is useful in cases where the base class was morphed early on, or
888 if a step needs to call a sub-step but morph first.
889
890 See the allow_morph and the morph method for more information.
891
892 Should return a boolean value or hash of allowed steps - just as the
893 allow_morph method does.
894
895 =item append_path (method)
896
897 Arguments are the steps to append. Can be called any time. Adds more
898 steps to the end of the current path.
899
900 =item auth_args (method)
901
902 Should return a hashref that will be passed to the new method of CGI::Ex::Auth.
903 It is augmented with arguments that integrate it into CGI::Ex::App.
904
905 See the get_valid_auth method and the CGI::Ex::Auth documentation.
906
907 sub auth_args {
908 return {
909 login_header => '<h1>My login header</h1>',
910 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
911 secure_hash_keys => [qw(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbb ccccccccccccccccccccccc 2222222222222)],
912 # use_blowfish => 'my_blowfish_key',
913 };
914 }
915
916 =item auth_data (method)
917
918 Contains authentication data stored during the get_valid_auth method.
919 The data is normally blessed into the CGI::Ex::Auth::Data package which
920 evaluates to false if there was an error and true if the authentication
921 was successful - so this data can be defined but false.
922
923 See the get_valid_auth method.
924
925 =item base_dir_abs (method)
926
927 Used as the absolute base directory to find template files and validation files.
928 It may return a single value or an arrayref of values, or a coderef that
929 returns an arrayref or coderef of values. You may pass base_dir_abs
930 as a parameter in the arguments passed to the "new" method.
931
932 Default value is "".
933
934 For example, to pass multiple paths, you would use something
935 similar to the following:
936
937 sub base_dir_abs {
938 return ['/my/path/one', '/some/other/path'];
939 }
940
941 The base_dir_abs value is used along with the base_dir_rel, name_module,
942 name_step, ext_print and ext_values for determining the values
943 returned by the default file_print and file_val hooks. See those methods
944 for further discussion.
945
946 See the section on FINDING TEMPLATES for further discussion.
947
948 =item base_dir_rel (method)
949
950 Added as a relative base directory to content under the base_dir_abs directory.
951
952 Default value is "".
953
954 The base_dir_abs method is used as top level where template includes may
955 pull from, while the base_dir_rel is directory relative to the base_dir_abs
956 where the content files will be stored.
957
958 A value for base_dir_rel may passed as a parameter in the arguments passed
959 to the new method.
960
961 See the base_dir_abs method for more discussion.
962
963 See the section on FINDING TEMPLATES for further discussion.
964
965 =item cleanup_user (method)
966
967 Used as a hook during get_valid_auth. Allows for cleaning
968 up the username. See the get_valid_auth method.
969
970 sub cleanup_user {
971 my ($self, $user) = @_;
972 return lc $user;
973 }
974
975 =item clear_app (method)
976
977 If the same CGI::Ex::App based object is used to run multiple
978 navigate sessions, the clear_app method should be called which
979 will attempt to clear as much session information as it can.
980 The following items will be cleared:
981
982 cgix
983 vob
984 form
985 cookies
986 stash
987 path
988 path_i
989 history
990 __morph_lineage_start_index
991 __morph_lineage
992 hash_errors
993 hash_fill
994 hash_swap
995 hash_common
996
997 =item current_step (method)
998
999 Returns the current step that the nav_loop is functioning on.
1000
1001 =item default_step (method)
1002
1003 Step to show if the path runs out of steps. Default value is the
1004 'default_step' property which defaults to 'main'.
1005
1006 If nav_loop runs of the end of the path (runs out of steps), this
1007 method is called, the step is added to the path, and nav_loop calls
1008 itself recursively.
1009
1010 =item destroy (method)
1011
1012 Called at the end of navigate after all other actions have run. Can
1013 be used for undoing things done in the ->init method called during
1014 the ->new method.
1015
1016 =item dump_history (method)
1017
1018 Show simplified trace information of which steps were called, the
1019 order they were called in, the time they took to run, and a brief list
1020 of the output (to see the full response returned by each hook, pass a
1021 true value as the only argument to dump_history -
1022 $self->dump_history(1)). Indentation is also applied to show which
1023 hooks called other hooks.
1024
1025
1026 The first line shows the amount of time elapsed for the entire
1027 navigate execution. Subsequent lines contain:
1028
1029 Step - the name of the current step.
1030 Hook - the name of the hook being called.
1031 Found - the name of the method that was found.
1032 Time - the total elapsed seconds that method took to run.
1033 Output - the response of the hook - shown in shortened form.
1034
1035 Note - to get full output responses - pass a true value to
1036 dump_history - or just call ->history. Times displayed are to 5
1037 decimal places - this accuracy can only be provided if the Time::HiRes
1038 module is installed on your system (it will only be used if installed).
1039
1040 It is usually best to print this history during the post_navigate
1041 method as in the following:
1042
1043 use CGI::Ex::Dump qw(debug);
1044 sub post_navigate { debug shift->dump_history }
1045
1046 The following is a sample output of dump_history called from the
1047 sample recipe application at the end of this document. The step
1048 called is "view".
1049
1050 debug: admin/Recipe.pm line 14
1051 shift->dump_history = [
1052 "Elapsed: 0.00562",
1053 "view - run_step - run_step - 0.00488 - 1",
1054 " view - pre_step - pre_step - 0.00003 - 0",
1055 " view - skip - view_skip - 0.00004 - 0",
1056 " view - prepare - prepare - 0.00003 - 1",
1057 " view - info_complete - info_complete - 0.00010 - 0",
1058 " view - ready_validate - ready_validate - 0.00004 - 0",
1059 " view - prepared_print - prepared_print - 0.00441 - 1",
1060 " view - hash_base - hash_base - 0.00009 - HASH(0x84ea6ac)",
1061 " view - hash_common - view_hash_common - 0.00148 - HASH(0x8310a20)",
1062 " view - hash_form - hash_form - 0.00004 - HASH(0x84eaa78)",
1063 " view - hash_fill - hash_fill - 0.00003 - {}",
1064 " view - hash_swap - hash_swap - 0.00003 - {}",
1065 " view - hash_errors - hash_errors - 0.00003 - {}",
1066 " view - print - print - 0.00236 - 1",
1067 " view - file_print - file_print - 0.00024 - recipe/view.html",
1068 " view - name_module - name_module - 0.00007 - recipe",
1069 " view - name_step - name_step - 0.00004 - view",
1070 " view - swap_template - swap_template - 0.00161 - <html> ...",
1071 " view - template_args - template_args - 0.00008 - HASH(0x865abf8)",
1072 " view - fill_template - fill_template - 0.00018 - 1",
1073 " view - fill_args - fill_args - 0.00003 - {}",
1074 " view - print_out - print_out - 0.00015 - 1",
1075 " view - post_print - post_print - 0.00003 - 0"
1076 ];
1077
1078 =item exit_nav_loop (method)
1079
1080 This method should not normally used but there is no problem with
1081 using it on a regular basis. Essentially it is a "goto" that allows
1082 for a long jump to the end of all nav_loops (even if they are
1083 recursively nested). This effectively short circuits all remaining
1084 hooks for the current and remaining steps. It is used to allow the
1085 ->jump functionality. If the application has morphed, it will be
1086 unmorphed before returning. Also - the post_navigate method will
1087 still be called.
1088
1089 =item ext_print (method)
1090
1091 Added as suffix to "name_step" during the default file_print hook.
1092
1093 Default value is 'html'.
1094
1095 For example, if name_step returns "foo" and ext_print returns "html"
1096 then the file "foo.html" will be searched for.
1097
1098 See the section on FINDING TEMPLATES for further discussion.
1099
1100 =item ext_val (method)
1101
1102 Added as suffix to "name_step" during the default file_val hook.
1103
1104 Default value is 'val'.
1105
1106 For example, if name_step returns "foo" and ext_val returns "val"
1107 then the file "foo.val" will be searched for.
1108
1109 See the section on FINDING TEMPLATES for further discussion.
1110
1111 =item first_step (method)
1112
1113 Returns the first step of the path. Note that first_step may not be the same
1114 thing as default_step if the path was overridden.
1115
1116 =item form (method)
1117
1118 Returns a hashref of the items passed to the CGI. Returns
1119 $self->{form} which defaults to CGI::Ex::get_form.
1120
1121 =item handle_error (method)
1122
1123 If anything dies during execution, handle_error will be called with
1124 the error that had happened. Default action is to die with that error.
1125
1126 =item history (method)
1127
1128 Returns an arrayref which contains trace history of which hooks of
1129 which steps were ran. Useful for seeing what happened. In general -
1130 each line of the history will show the current step, the hook
1131 requested, and which hook was actually called.
1132
1133 The dump_history method shows a short condensed version of this
1134 history which makes it easier to see what path was followed.
1135
1136 In general, the arrayref is free for anything to push onto which will
1137 help in tracking other occurrences in the program as well.
1138
1139 =item init (method)
1140
1141 Called by the default new method. Allows for any object
1142 initilizations that may need to take place. Default action does
1143 nothing.
1144
1145 =item fill_args (hook)
1146
1147 Returns a hashref of args that will be passed to the CGI::Ex::Fill::fill.
1148 It is augmented with the template to swap and the fill hash. This
1149 could be useful if you needed to only swap a particular form on the template
1150 page. Arguments are passed directly to the fill function.
1151
1152 sub fill_args { {target => 'my_form'} }
1153
1154 =item fill_template (hook)
1155
1156 Arguments are a template and a hashref. Takes the template that was
1157 prepared using swap_template, and swaps html form fields using the
1158 passed hashref. Overriding this method can control the fill behavior.
1159
1160 Calls the fill_args hook prior to calling CGI::Ex::Fill::fill
1161
1162 =item file_print (hook)
1163
1164 Returns a filename of the content to be used in the default print
1165 hook. Adds method base_dir_rel to hook name_module, and name_step and
1166 adds on the default file extension found in $self->ext_print which
1167 defaults to the property $self->{ext_print} which will default to
1168 ".html". Should return a filename relative to base_dir_abs that can be
1169 swapped using CGI::Ex::Template, or should be a scalar reference to
1170 the template content that can be swapped. This will be used by the
1171 hook print.
1172
1173 sub base_dir_abs { '/var/www/templates' }
1174 sub base_dir_rel { 'content' }
1175 sub name_module { 'recipe' }
1176 sub ext_print { 'html' } # default
1177
1178 # ->file_print('this_step')
1179 # would return 'content/recipe/this_step.html'
1180 # the template engine would look in '/var/www/templates'
1181 # for a file by that name
1182
1183 It may also return a reference to a string containing the html template.
1184 This is useful for prototyping applications and/or keeping all of
1185 the data for the application in a single location.
1186
1187 =item file_val (hook)
1188
1189 Returns a filename containing the validation. Performs the same
1190 as file_print, but uses ext_val to get the extension, and it adds
1191 base_dir_abs onto the returned value (file_print is relative to
1192 base_dir_abs, while file_val is fully qualified with base_dir_abs).
1193 If base_dir_abs returns an arrayref of paths, then each path is
1194 checked for the existence of the file.
1195
1196 The file should be readable by CGI::Ex::Validate::get_validation.
1197
1198 This hook is only necessary if the hash_validation hook has not been
1199 overridden.
1200
1201 This method an also return a hashref containing the validation - but
1202 then you may have wanted to override the hash_validation hook.
1203
1204 =item finalize (hook)
1205
1206 Defaults to true. Used to do whatever needs to be done with the data once
1207 prepare has returned true and info_complete has returned true. On failure
1208 the print operations are ran. On success navigation moves on to the next
1209 step.
1210
1211 This is normally were there core logic of a script will occur (such as
1212 adding to a database, or updating a record). At this point, the data
1213 should be validated. It is possible to do additional validation
1214 and return errors using code such as the following.
1215
1216 if (! $user_is_unique) {
1217 $self->add_errors(username => 'The username was already used');
1218 return 0;
1219 }
1220
1221 =item find_hook (method)
1222
1223 Called by run_hook. Arguments are a hook name, a step name. It
1224 should return an arrayref containing the code_ref to run, and the
1225 name of the method looked for. It uses ->can to find the appropriate
1226 hook.
1227
1228 my $code = $self->hook('finalize', 'main');
1229 ### will look first for $self->main_finalize;
1230 ### will then look for $self->finalize;
1231
1232 This system is used to allow for multiple steps to be in the same
1233 file and still allow for moving some steps out to external sub classed
1234 packages (if desired).
1235
1236 If the application has successfully morphed via the morph method and
1237 allow_morph then it is not necessary to add the step name to the
1238 beginning of the method name as the morphed packages method will
1239 override the base package (it is still OK to use the full method name
1240 "${step}_hookname").
1241
1242 See the run_hook method and the morph method for more details.
1243
1244 =item forbidden_step (method)
1245
1246 Defaults to "__forbidden". The name of a step to run should the current
1247 step name be invalid, or if a step found by the default path method
1248 is invalid. See the path method.
1249
1250 =item form_name (hook)
1251
1252 Return the name of the form to attach the js validation to. Used by
1253 js_validation.
1254
1255 =item get_pass_by_user (method)
1256
1257 This method is passed a username and the authentication object. It
1258 should return the password for the given user. See the get_pass_by_user
1259 method of CGI::Ex::Auth for more information. Installed as a hook
1260 to the authentication object during the get_valid_auth method.
1261
1262 =item get_valid_auth (method)
1263
1264 If require_auth is true at either the application level or at the
1265 step level, get_valid_auth will be called.
1266
1267 It will call auth_args to get some default args to pass to
1268 CGI::Ex::Auth->new. It augments the args with sensible defaults that
1269 App already provides (such as form, cookies, and template facilities).
1270 It also installs hooks for the get_pass_by_user, cleanup_user, and verify_user
1271 hooks of CGI::Ex::Auth.
1272
1273 It stores the $auth->last_auth_data in $self->auth_data for later use. For
1274 example, to get the authenticated user:
1275
1276 sub require_auth { 1 }
1277
1278 sub cleanup_user {
1279 my ($self, $user) = @_;
1280 return lc $user;
1281 }
1282
1283 sub get_pass_by_user {
1284 my ($self, $user) = @_;
1285 my $pass = $self->some_method_to_get_the_pass($user);
1286 return $pass;
1287 }
1288
1289 sub auth_args {
1290 return {
1291 login_header => '<h1>My login header</h1>',
1292 login_footer => '[% TRY %][% INCLUDE login/login_footer.htm %][% CATCH %]<!-- [% error %] -->[% END %]',
1293 };
1294 }
1295
1296 sub main_hash_swap {
1297 my $self = shift;
1298 my $user = $self->auth_data->{'user'};
1299 return {user => $user};
1300 }
1301
1302 Successful authentication is cached for the duration of the
1303 nav_loop so multiple steps will run the full authentication routine
1304 only once.
1305
1306 Full customization of the login process and the login template can
1307 be done via the auth_args hash. See the auth_args method and
1308 CGI::Ex::Auth perldoc for more information.
1309
1310 =item hash_base (hook)
1311
1312 A hash of base items to be merged with hash_form - such as pulldown
1313 menus, javascript validation, etc. It will now also be merged with
1314 hash_fill, so it can contain default fillins as well. It can be
1315 populated by passing a hash to ->add_to_base. By default a sub
1316 similar to the following is what is used for hash_common. Note the
1317 use of values that are code refs - so that the js_validation and
1318 form_name hooks are only called if requested:
1319
1320 sub hash_base {
1321 my ($self, $step) = @_;
1322 return $self->{hash_base} ||= {
1323 script_name => $ENV{SCRIPT_NAME},
1324 js_validation => sub { $self->run_hook('js_validation', $step) },
1325 form_name => sub { $self->run_hook('form_name', $step) },
1326 };
1327 }
1328
1329 =item hash_common (hook)
1330
1331 Almost identical in function and purpose to hash_base. It is
1332 intended that hash_base be used for common items used in various
1333 scripts inheriting from a common CGI::Ex::App type parent. Hash_common
1334 is more intended for step level populating of both swap and fill.
1335
1336 =item hash_errors (hook)
1337
1338 Called in preparation for print after failed prepare, info_complete,
1339 or finalize. Should contain a hash of any errors that occurred. Will
1340 be merged into hash_form before the pass to print. Each error that
1341 occurred will be passed to method format_error before being added to
1342 the hash. If an error has occurred, the default validate will
1343 automatically add {has_errors =>1}. To the error hash at the time of
1344 validation. has_errors will also be added during the merge in case the
1345 default validate was not used. Can be populated by passing a hash to
1346 ->add_to_errors or ->add_errors.
1347
1348 =item hash_fill (hook)
1349
1350 Called in preparation for print after failed prepare, info_complete,
1351 or finalize. Should contain a hash of any items needed to be filled
1352 into the html form during print. Items from hash_form, hash_base, and
1353 hash_common will be layered together. Can be populated by passing a
1354 hash to ->add_to_fill.
1355
1356 By default - forms are sticky and data from previous requests will try
1357 and populate the form. You can use the fill_template hook to disable
1358 templating on a single page or on all pages.
1359
1360 This method can be used to pre-populate the form as well (such as on an
1361 edit step). If a form fails validation, hash_fill will also be called
1362 and will only want the submitted form fields to be sticky. You can
1363 use the ready_validate hook to prevent pre-population in these cases as
1364 follows:
1365
1366 sub edit_hash_fill {
1367 my $self = shift;
1368 my $step = shift;
1369 return {} if $self->run_hook('ready_validate', $step);
1370
1371 my %hash;
1372
1373 ### get previous values from the database
1374
1375 return \%hash;
1376 }
1377
1378 =item hash_form (hook)
1379
1380 Called in preparation for print after failed prepare, info_complete,
1381 or finalize. Defaults to ->form. Can be populated by passing a hash
1382 to ->add_to_form.
1383
1384 =item hash_swap (hook)
1385
1386 Called in preparation for print after failed prepare, info_complete,
1387 or finalize. Should contain a hash of any items needed to be swapped
1388 into the html during print. Will be merged with hash_base,
1389 hash_common, hash_form, and hash_errors. Can be populated by passing
1390 a hash to ->add_to_swap.
1391
1392 The hash will be passed as the second argument to swap_template.
1393
1394 =item hash_validation (hook)
1395
1396 Returns a hash of the validation information to check form against.
1397 By default, will look for a filename using the hook file_val and will
1398 pass it to CGI::Ex::Validate::get_validation. If no file_val is
1399 returned or if the get_validation fails, an empty hash will be returned.
1400 Validation is implemented by ->vob which loads a CGI::Ex::Validate object.
1401
1402 =item info_complete (hook)
1403
1404 Calls the ready_validate hook to see if data is ready to validate. If
1405 so it calls the validate hook to validate the data. Should make
1406 sure the data is ready and valid. Will not be run unless
1407 prepare returns true (default).
1408
1409 =item insert_path (method)
1410
1411 Arguments are the steps to insert. Can be called any time. Inserts
1412 the new steps at the current path location.
1413
1414 =item is_authed (method)
1415
1416 Returns true if the object has successful authentication data. It
1417 returns false if the object has not been authenticated.
1418
1419 =item js_uri_path (method)
1420
1421 Return the URI path where the CGI/Ex/yaml_load.js and
1422 CGI/Ex/validate.js files can be found. This will default to
1423 "$ENV{SCRIPT_NAME}/js" if the path method has not been overridden,
1424 otherwise it will default to "$ENV{SCRIPT_NAME}?step=js&js=" (the
1425 latter is more friendly with overridden paths). A default handler for
1426 the "js" step has been provided in "js_run_step" (this handler will
1427 nicely print out the javascript found in the js files which are
1428 included with this distribution. js_run_step will work properly with the
1429 default "path" handler.
1430
1431 =item js_validation (hook)
1432
1433 Requires JSON or YAML. Will return Javascript that is capable of
1434 validating the form. This is done using the capabilities of
1435 CGI::Ex::Validate. This will call the hook hash_validation which will
1436 then be encoded either json or into yaml and placed in a javascript
1437 string. It will also call the hook form_name to determine which html
1438 form to attach the validation to. The method js_uri_path is called to
1439 determine the path to the appropriate validate.js files. If the
1440 method ext_val is htm, then js_validation will return an empty string
1441 as it assumes the htm file will take care of the validation itself.
1442 In order to make use of js_validation, it must be added to the
1443 variables returned by either the hash_base, hash_common, hash_swap or
1444 hash_form hook (see examples of hash_base used in this doc).
1445
1446 By default it will try and use JSON first and then fail to YAML and
1447 then will fail to returning an html comment that does nothing.
1448
1449 =item jump (method)
1450
1451 This method should not normally be used but is fine to use it on a
1452 regular basis. It provides for moving to the next step at any point
1453 during the nav_loop. It effectively short circuits the remaining
1454 hooks for the current step. It does increment the recursion counter
1455 (which has a limit of ->recurse_limit - default 15). It is normally
1456 better to allow the other hooks in the loop to carry on their normal
1457 functions and avoid jumping. (Essentially, this hook behaves like a
1458 goto method to bypass everything else and continue at a different
1459 location in the path - there are times when it is necessary or useful
1460 to do this).
1461
1462 Jump takes a single argument which is the location in the path to jump
1463 to. This argument may be either a step name, the special strings
1464 "FIRST, LAST, CURRENT, PREVIOUS, OR NEXT" or the number of steps to
1465 jump forward (or backward) in the path. The default value, 1,
1466 indicates that CGI::Ex::App should jump to the next step (the default
1467 action for jump). A value of 0 would repeat the current step (watch
1468 out for recursion). A value of -1 would jump to the previous step.
1469 The special value of "LAST" will jump to the last step. The special
1470 value of "FIRST" will jump back to the first step. In each of these
1471 cases, the path array returned by ->path is modified to allow for the
1472 jumping (the path is modified so that the path history is not destroyed
1473 - if we were on step 3 and jumped to one, that path would contain
1474 1, 2, 3, *1, 2, 3, 4, etc and we would be at the *).
1475
1476 ### goto previous step
1477 $self->jump($self->previous_step);
1478 $self->jump('PREVIOUS');
1479 $self->jump(-1);
1480
1481 ### goto next step
1482 $self->jump($self->next_step);
1483 $self->jump('NEXT');
1484 $self->jump(1);
1485 $self->jump;
1486
1487 ### goto current step (repeat)
1488 $self->jump($self->current_step);
1489 $self->jump('CURRENT');
1490 $self->jump(0);
1491
1492 ### goto last step
1493 $self->jump($self->last_step);
1494 $self->jump('LAST');
1495
1496 ### goto first step
1497 $self->jump($self->first_step);
1498 $self->jump('FIRST');
1499
1500 =item last_step (method)
1501
1502 Returns the last step of the path. Can be used to jump to the last step.
1503
1504 =item morph (method)
1505
1506 Allows for temporarily "becoming" another object type for the
1507 execution of the current step. This allows for separating some steps
1508 out into their own packages.
1509
1510 Morph will only run if the method allow_morph returns true.
1511 Additionally if the allow_morph returns a hash ref, morph will only
1512 run if the step being morphed to is in the hash. Morph also passes
1513 the step name to allow_morph.
1514
1515 The morph call occurs at the beginning of the step loop. A
1516 corresponding unmorph call occurs before the loop is exited. An
1517 object can morph several levels deep if allow_nested_morph returns
1518 true. For example, an object running as Foo::Bar that is looping on
1519 the step "my_step" that has allow_morph = 1, will do the following:
1520
1521 Call the morph_package hook (which would default to returning
1522 Foo::Bar::MyStep in this case)
1523
1524 Translate this to a package filename (Foo/Bar/MyStep.pm) and try
1525 and require it, if the file can be required, the object is blessed
1526 into that package.
1527
1528 Call the fixup_after_morph method.
1529
1530 Continue on with the run_step for the current step.
1531
1532 At any exit point of the loop, the unmorph call is made which
1533 re-blesses the object into the original package.
1534
1535 Samples of allowing morph:
1536
1537 sub allow_morph { 1 }
1538
1539 sub allow_morph { {edit => 1} }
1540
1541 sub allow_morph { my ($self, $step) = @_; return $step eq 'edit' }
1542
1543 It is possible to call morph earlier on in the program. An example of
1544 a useful early use of morph would be as in the following code:
1545
1546 sub allow_morph { 1 }
1547
1548 sub pre_navigate {
1549 my $self = shift;
1550 if ($ENV{'PATH_INFO'} && $ENV{'PATH_INFO'} =~ s|^/(\w+)||) {
1551 my $step = $1;
1552 $self->morph($step);
1553 $ENV{'PATH_INFO'} = "/$step";
1554 $self->stash->{'base_morphed'} = 1;
1555 }
1556 return 0;
1557 }
1558
1559 sub post_navigate {
1560 my $self = shift;
1561 $self->unmorph if $self->stash->{'base_morphed'};
1562 }
1563
1564 If this code was in a module Base.pm and the cgi running was cgi/base
1565 and called:
1566
1567 Base->navigate;
1568
1569 and you created a sub module that inherited Base.pm called
1570 Base/Ball.pm -- you could then access it using cgi/base/ball. You
1571 would be able to pass it steps using either cgi/base/ball/step_name or
1572 cgi/base/ball?step=step_name - Or Base/Ball.pm could implement its
1573 own path. It should be noted that if you do an early morph, it is
1574 suggested to provide a call to unmorph. And if you want to let your
1575 early morphed object morph again - you will need to provide
1576
1577 sub allow_nested_morph { 1 }
1578
1579 With allow_nested_morph enabled you could create the file
1580 Base/Ball/StepName.pm which inherits Base/Ball.pm. The Base.pm, with
1581 the custom init and default path method, would automatically morph us
1582 first into a Base::Ball object (during init) and then into a
1583 Base::Ball::StepName object (during the navigation loop).
1584
1585 Since it is complicated to explain - it may be a bit complicated to
1586 those who will try to follow your code later. CGI::Ex::App provides
1587 many ways to do things, but use the best one for your situation.
1588
1589 =item morph_package (hook)
1590
1591 Used by morph. Return the package name to morph into during a morph
1592 call. Defaults to using the current object type as a base. For
1593 example, if the current object running is a Foo::Bar object and the
1594 step running is my_step, then morph_package will return
1595 Foo::Bar::MyStep.
1596
1597 Because of the way that run_hook works, it is possible that several
1598 steps could be located in the same external file and overriding morph_package
1599 could allow for this to happen.
1600
1601 See the morph method.
1602
1603 =item name_module (hook)
1604
1605 Return the name (relative path) that should be pre-pended to name_step
1606 during the default file_print and file_val lookups. Defaults to
1607 the value in $self->{name_module} which in turn defaults to the name
1608 of the current script.
1609
1610 cgi-bin/my_app.pl => my_app
1611 cgi/my_app => my_app
1612
1613 This method is provided so that each cgi or mod_perl application can
1614 have its own directory for storing html for its steps.
1615
1616 See the file_print method for more information.
1617
1618 See the section on FINDING TEMPLATES for further discussion.
1619
1620 =item name_step (hook)
1621
1622 Return the step (appended to name_module) that should used when
1623 looking up the file in file_print and file_val lookups. Defaults to
1624 the current step.
1625
1626 See the section on FINDING TEMPLATES for further discussion.
1627
1628 =item nav_loop (method)
1629
1630 This is the main loop runner. It figures out the current path
1631 and runs all of the appropriate hooks for each step of the path. If
1632 nav_loop runs out of steps to run (which happens if no path is set, or if
1633 all other steps run successfully), it will insert the ->default_step into
1634 the path and run nav_loop again (recursively). This way a step is always
1635 assured to run. There is a method ->recurse_limit (default 15) that
1636 will catch logic errors (such as inadvertently running the same
1637 step over and over and over because there is either no hash_validation,
1638 or the data is valid but the set_ready_validate(0) method was not called).
1639
1640 =item navigate (method)
1641
1642 Takes a class name or a CGI::Ex::App object as arguments. If a class
1643 name is given it will call the "new" method to instantiate an object
1644 by that class (passing any extra arguments to the new method). All
1645 returns from navigate will return the object.
1646
1647 The method navigate is essentially a safe wrapper around the ->nav_loop
1648 method. It will catch any dies and pass them to ->handle_error.
1649
1650 This starts the process flow for the path and its steps.
1651
1652 =item navigate_authenticated (method)
1653
1654 Same as the method navigate but sets require_auth(1) before
1655 running. See the require_auth method.
1656
1657 =item new (class method)
1658
1659 Object creator. Takes a hashref of arguments that will become the
1660 initial properties of the object. Calls the init method once the
1661 object has been blessed to allow for any other initilizations.
1662
1663 my $app = MyApp->new({name_module => 'my_app'});
1664
1665 =item next_step (hook and method)
1666
1667 Returns the next step in the path. If there is no next step, it
1668 returns the default_step.
1669
1670 It can be used as a method to return the next step in the path
1671 to pass to a method such as ->jump.
1672
1673 It is also used as a hook by the refine_path hook. If there is no
1674 more steps, it will call the next_step hook to try and find a step to
1675 append to the path.
1676
1677 =item path (method)
1678
1679 Return an arrayref (modifiable) of the steps in the path. For each
1680 step the run_step hook and all of its remaining hooks will be run.
1681
1682 Hook methods are looked up and ran using the method "run_hook" which
1683 uses the method "find_hook" to lookup the hook. A history of ran
1684 hooks is stored in the array ref returned by $self->history.
1685
1686 If path has not been defined, the method will look first in the form
1687 for a key by the name found in ->step_key. It will then look in
1688 $ENV{'PATH_INFO'}. It will use this step to create a path with that
1689 one step as its contents. If a step is passed in via either of these
1690 ways, the method will call valid_steps to make sure that the step
1691 is valid (by default valid_steps returns undef - which means that
1692 any step is valid). Any step beginning with _ can not be passed in
1693 and are intended for use on private paths. If a non-valid step is
1694 found, then path will be set to contain a single step of ->forbidden_step.
1695
1696 For the best functionality, the arrayref returned should be the same
1697 reference returned for every call to path - this ensures that other
1698 methods can add to the path (and will most likely break if the
1699 arrayref is not the same).
1700
1701 If navigation runs out of steps to run, the default step found in
1702 default_step will be run. This is what allows for us to default
1703 to the "main" step for many applications.
1704
1705 =item path_info_map (hook)
1706
1707 Used to map path_info parts to form variables. Similar to the
1708 path_info_map_base method. See the path_info_map_base method
1709 for a discussion of how to use this hook.
1710
1711 =item path_info_map_base (method)
1712
1713 Called during the default path method. It is used to custom map portions
1714 of $ENV{'PATH_INFO'} to form values. If should return an arrayref of
1715 arrayrefs where each child arrayref contains a regex qr with match parens
1716 as the first element of the array. Subsequent elements of the array are
1717 the key names to store the corresponding matched value from the regex under.
1718 The outer arrayref is iterated until it one of child arrayrefs matches
1719 against $ENV{'PATH_INFO'}. The matched values are only added to the form if
1720 there is not already a defined value for that key in the form.
1721
1722 The default value returned by this method looks something like the following:
1723
1724 sub path_info_map_base {
1725 return [[qr{^/(\w+)}, $self->step_key]];
1726 }
1727
1728 This example would map the following PATH_INFO string as follows:
1729
1730 /my_step
1731
1732 # $self->form->{'step'} now equals "my_step"
1733
1734 The following is another example:
1735
1736 sub path_info_map_base {
1737 return [
1738 [qr{^/([^/]+)/(\w+)}, 'username', $self->step_key],
1739 [qr{^/(\w+)}, $self->step_key],
1740 ];
1741 }
1742
1743 # the PATH_INFO /my_step
1744 # still results in
1745 # $self->form->{'step'} now equals "my_step"
1746
1747 # but with the PATH_INFO /my_user/my_step
1748 # $self->form->{'step'} now equals "my_step"
1749 # and $self->form->{'username'} equals "my_user"
1750
1751 In most cases there is not a need to override the path_info_map_base
1752 method, but rather override the path_info_map hook for a particular step.
1753 When the step is being run, just before the run_step hook is called, the
1754 path_info_map hook is called. The path_info_map hook is similar to
1755 the path_info_map_base method, but is used to allow step level manipulation
1756 of form based on elements in the $ENV{'PATH_INFO'}.
1757
1758 sub my_step_path_info_map {
1759 return [[qr{^/my_step/(\w+)$}, 'username']];
1760 }
1761
1762 # the PATH_INFO /my_step/my_user
1763 # results in
1764 # $self->form->{'step'} equal to "my_step" because of default path_info_map_base
1765 # and $self->form->{'username'} equals "my_user" because of my_step_path_info_map
1766
1767 The section on mapping URIs to steps has additional examples.
1768
1769 =item post_loop (method)
1770
1771 Ran after all of the steps in the loop have been processed (if
1772 prepare, info_complete, and finalize were true for each of the steps).
1773 If it returns a true value the navigation loop will be aborted. If it
1774 does not return true, navigation continues by then inserting the step
1775 $self->default_step and running $self->nav_loop again (recurses) to
1776 fall back to the default step.
1777
1778 =item post_navigate (method)
1779
1780 Called from within navigate. Called after the nav_loop has finished
1781 running but within the eval block to catch errors. Will only run if
1782 there were no errors which died during the nav_loop process.
1783
1784 It can be disabled from running by setting the _no_post_navigate
1785 property.
1786
1787 If per-step authentication is enabled and authentication fails,
1788 the post_navigate method will still be called (the post_navigate
1789 method can check the ->is_authed method to change behavior). If
1790 application level authentication is enabled and authentication
1791 fails, none of the pre_navigate, nav_loop, or post_navigate methods
1792 will be called.
1793
1794 =item post_print (hook)
1795
1796 A hook which occurs after the printing has taken place. Is only run
1797 if the information was not complete. Useful for cases such as
1798 printing rows of a database query after displaying a query form.
1799
1800 =item post_step (hook)
1801
1802 Ran at the end of the step's loop if prepare, info_complete, and
1803 finalize all returned true. Allows for cleanup. If a true value is
1804 returned, execution of navigate is returned and no more steps are
1805 processed.
1806
1807 =item pre_loop (method)
1808
1809 Called right before the navigation loop is started (at the beginning
1810 of nav_loop). At this point the path is set (but could be modified).
1811 The only argument is a reference to the path array. If it returns a
1812 true value - the navigation routine is aborted.
1813
1814 =item pre_navigate (method)
1815
1816 Called at the very beginning of the navigate method, but within the
1817 eval block to catch errors. Called before the nav_loop method is
1818 started. If a true value is returned then navigation is skipped (the
1819 nav_loop is never started).
1820
1821 =item pre_step (hook)
1822
1823 Ran at the beginning of the loop before prepare, info_compelete, and
1824 finalize are called. If it returns true, execution of nav_loop is
1825 returned and no more steps are processed..
1826
1827 =item prepare (hook)
1828
1829 Defaults to true. A hook before checking if the info_complete is true.
1830 Intended to be used to cleanup the form data.
1831
1832 =item prepared_print (hook)
1833
1834 Called when any of prepare, info_complete, or finalize fail. Prepares
1835 a form hash and a fill hash to pass to print. The form hash is primarily
1836 intended for use by the templating system. The fill hash is intended
1837 to be used to fill in any html forms.
1838
1839 =item previous_step (method)
1840
1841 List the step previous to this one. Will return '' if there is no previous step.
1842
1843 =item print (hook)
1844
1845 Take the information generated by prepared_print, format it, and print it out.
1846 Default incarnation uses CGI::Ex::Template which is compatible with
1847 Template::Toolkit. Arguments are: step name (used to call the
1848 file_print hook), swap hashref (passed to call swap_template), and
1849 fill hashref (passed to fill_template).
1850
1851 During the print call, the file_print hook is called which should
1852 return a filename or a scalar reference to the template content is
1853
1854 =item ready_validate (hook)
1855
1856 Should return true if enough information is present to run validate.
1857 Default is to look if $ENV{'REQUEST_METHOD'} is 'POST'. A common
1858 usage is to pass a common flag in the form such as 'processing' => 1
1859 and check for its presence - such as the following:
1860
1861 sub ready_validate { shift->form->{'processing'} }
1862
1863 Changing the behavior of ready_validate can help in making wizard type
1864 applications.
1865
1866 =item refine_path (hook)
1867
1868 Called at the end of nav_loop. Passed a single value indicating
1869 if there are currently more steps in the path.
1870
1871 The default implementation returns if there are still more steps
1872 in the path. Otherwise, it calls the next_step hook and appends
1873 it to the path with the append_path method, and then calls
1874 the set_ready_validate hook and passes it 0.
1875
1876 This allows you to simply put
1877
1878 sub edit_next_step { '_edit_success' }
1879
1880 In your code and it will automatically do the right thing and
1881 go to the _edit_success step.
1882
1883 =item recurse_limit (method)
1884
1885 Default 15. Maximum number of times to allow nav_loop to call itself.
1886 The recurse level will increase every time that ->jump is called, or if
1887 the end of the nav_loop is reached and the process tries to add the
1888 default_step and run it again.
1889
1890 If ->jump is used often - the recurse_limit will be reached more
1891 quickly. It is safe to raise this as high as is necessary - so long
1892 as it is intentional.
1893
1894 Often the limit is reached if a step did not have a validation hash,
1895 or if the set_ready_validate(0) method was not called once the data
1896 had been successfully validated and acted upon.
1897
1898 =item replace_path (method)
1899
1900 Arguments are the steps used to replace. Can be called any time.
1901 Replaces the remaining steps (if any) of the current path.
1902
1903 =item require_auth (method)
1904
1905 Default undef. Can return either a true value or a hashref of step names.
1906
1907 If a hashref of stepnames is returned, authentication will be turned on
1908 at the step level. In this mode if any step is accessed, the get_valid_auth
1909 method will be called. If it fails, then the nav_loop will be stopped
1910 (the post_navigate method will be called - use the is_authed method to perform
1911 different functions). Any step of the path not in the hash will not require
1912 authentication. For example, to add authentication to add authentication
1913 to the add, edit and delete steps you could do:
1914
1915 sub require_auth { {add => 1, edit => 1, delete => 1} }
1916
1917 If a non-hash true value is returned from the require_auth method then
1918 authentication will take place before the pre_navigation or the nav_loop methods.
1919 If authentication fails the navigation process is exited (the post_navigate
1920 method will not be called).
1921
1922 sub require_auth { 1 }
1923
1924 Alternatively you can also could do either of the following:
1925
1926 __PACKAGE__->navigate_authenticated; # instead of __PACKAGE__->navigate;
1927
1928 # OR
1929
1930 sub init { shift->require_auth(1) }
1931
1932 # OR
1933
1934 __PACKAGE__->new({require_auth => 1}->navigate;
1935
1936 If get_valid_auth returns true, in either case, the is_authed method will
1937 return true and the auth_data will contain the authenticated user's data.
1938 If it returns false, auth_data may possibly contain a defined but false
1939 data object with details as to why authentication failed.
1940
1941 See the get_valid_auth method.
1942
1943 =item run_hook (method)
1944
1945 Arguments are a hook name and the step to find the hook for. Calls
1946 the find_hook method to get a code ref which it then calls and returns
1947 the result passing any extra arguments to run_hook as arguments to the
1948 code ref.
1949
1950 Each call to run_hook is logged in the arrayref returned by the
1951 history method. This information is summarized in the dump_history
1952 method and is useful for tracing the flow of the program.
1953
1954 The run_hook method is part of the core of CGI::Ex::App. It allows
1955 for an intermediate layer in normal method calls. Because of
1956 run_hook, it is possible to logically override methods on a step by
1957 step basis, or override a method for all of the steps, or even to
1958 break code out into separate modules.
1959
1960 =item run_step (hook)
1961
1962 Runs all of the hooks specific to each step, beginning with pre_step
1963 and ending with post_step (for a full listing of steps, see the
1964 section on process flow). Called after ->morph($step) has been run.
1965 If this hook returns true, the nav_loop is exited (meaning the
1966 run_step hook displayed a printed page). If it returns false, the
1967 nav_loop continues on to run the next step.
1968
1969 This hook performs the same base functionality as a method defined in
1970 CGI::Applications ->run_modes. The default run_step method provides
1971 much more granular control over the flow of the CGI.
1972
1973 =item set_path (method)
1974
1975 Arguments are the steps to set. Should be called before navigation
1976 begins. This will set the path arrayref to the passed steps.
1977
1978 This method is not normally used.
1979
1980 =item set_ready_validate (hook and method)
1981
1982 Sets that the validation is ready (or not) to validate. Should set the value
1983 checked by the hook ready_validate. The following would complement the
1984 processing flag above:
1985
1986 sub set_ready_validate {
1987 my $self = shift;
1988 my ($step, $is_ready) = (@_ == 2) ? @_ : (undef, shift);
1989 if ($is_ready) {
1990 $self->form->{'processing'} = 1;
1991 } else {
1992 delete $self->form->{'processing'};
1993 }
1994 return $is_ready;
1995 }
1996
1997 Note that for this example the form key "processing" was deleted. This
1998 is so that the call to fill in any html forms won't swap in a value of
1999 zero for form elements named "processing."
2000
2001 Also note that this method may be called as a hook as in
2002
2003 $self->run_hook('set_ready_validate', $step, 0)
2004 # OR
2005 $self->set_ready_validate($step, 0);
2006
2007 Or it can take a single argument and should set the ready status
2008 regardless of the step as in:
2009
2010 $self->set_ready_validate(0);
2011
2012 =item skip (hook)
2013
2014 Ran at the beginning of the loop before prepare, info_complete, and
2015 finalize are called. If it returns true, nav_loop moves on to the
2016 next step (the current step is skipped).
2017
2018 =item stash (method)
2019
2020 Returns a hashref that can store arbitrary user space data without
2021 worrying about overwriting the internals of the application.
2022
2023 =item step_key (method)
2024
2025 Should return the keyname that will be used by the default "path"
2026 method to look for in the form. Default value is 'step'.
2027
2028 =item swap_template (hook)
2029
2030 Takes the template and hash of variables prepared in print, and processes them
2031 through the current template engine (default engine is CGI::Ex::Template).
2032
2033 Arguments are the template and the swap hashref. The template can be either a
2034 scalar reference to the actual content, or the filename of the content. If the
2035 filename is specified - it should be relative to base_dir_abs (which will be
2036 used to initialize INCLUDE_PATH by default).
2037
2038 The default method will create a template object by calling the template_args hook
2039 and passing the returned hashref to the template_obj method. The default template_obj method
2040 returns a CGI::Ex::Template object, but could easily be swapped to use a Template::Toolkit
2041 based object. If a non-Template::Toolkit compatible object is to be used, then
2042 the swap_template hook can be overridden to use another templating engine.
2043
2044 For example to use the HTML::Template engine you could override the swap_template
2045 method as follows:
2046
2047 use HTML::Template;
2048
2049 sub swap_template {
2050 my ($self, $step, $file, $swap) = @_;
2051
2052 my $type = UNIVERSAL::isa($file, 'SCALAR') ? 'scalarref'
2053 : UNIVERSAL::isa($file, 'ARRAY') ? 'arrayref'
2054 : ref($file) ? 'filehandle'
2055 : 'filename';
2056
2057 my $t = HTML::Template->new(source => $file,
2058 type => $type,
2059 path => $self->base_dir_abs,
2060 die_on_bad_params => 0,
2061 );
2062
2063 $t->param($swap);
2064
2065 return $t->output;
2066 }
2067
2068 =item template_args (hook)
2069
2070 Returns a hashref of args that will be passed to the "new" method of CGI::Ex::Template.
2071 The method is normally called from the swap_template hook. The swap_template hook
2072 will add a value for INCLUDE_PATH which is set equal to base_dir_abs, if the INCLUDE_PATH
2073 value is not already set.
2074
2075 The returned hashref can contain any arguments that CGI::Ex::Template would understand.
2076
2077 sub template_args {
2078 return {
2079 PRE_CHOMP => 1,
2080 WRAPPER => 'wrappers/main_wrapper.html',
2081 };
2082 }
2083
2084 =item template_obj (method)
2085
2086 Called from swap_template. It is passed the result of template_args that have
2087 had a default INCLUDE_PATH added. The default implementation uses CGI::Ex::Template
2088 but can easily be changed to use Template::Toolkit by using code similar to the following:
2089
2090 use Template;
2091
2092 sub template_obj {
2093 my ($self, $args) = @_;
2094 return Template->new($args);
2095 }
2096
2097 =item unmorph (method)
2098
2099 Allows for returning an object back to its previous blessed state if
2100 the "morph" method was successful in morphing the App object. This
2101 only happens if the object was previously morphed into another object
2102 type. Before the object is re-blessed the method fixup_before_unmorph
2103 is called.
2104
2105 See allow_morph and morph.
2106
2107 =item valid_steps (method)
2108
2109 Called by the default path method. Should return a hashref of path
2110 steps that are allowed. If the current step is not found in the hash
2111 (or is not the default_step or js_step) the path method will return a
2112 single step of ->forbidden_step and run its hooks. If no hash or undef is
2113 returned, all paths are allowed (default). A key "forbidden_step"
2114 containing the step that was not valid will be placed in the stash.
2115 Often the valid_steps method does not need to be defined as arbitrary
2116 method calls are not possible with CGI::Ex::App.
2117
2118 Any steps that begin with _ are also "not" valid for passing in via the form
2119 or path info. See the path method.
2120
2121 Also, the pre_step, skip, prepare, and info_complete hooks allow for validating
2122 the data before running finalize.
2123
2124 =item validate (hook)
2125
2126 Passed the form from $self->form. Runs validation on the information
2127 contained in the passed form. Uses CGI::Ex::Validate for the default
2128 validation. Calls the hook hash_validation to load validation hashref
2129 (an empty hash means to pass validation). Should return true if the
2130 form passed validation and false otherwise. Errors are stored as a
2131 hash in $self->{hash_errors} via method add_errors and can be checked
2132 for at a later time with method has_errors (if the default validate
2133 was used).
2134
2135 There are many ways and types to validate the data. Please see the
2136 L<CGI::Ex::Validate> module.
2137
2138 Upon success, it will look through all of the items which were
2139 validated, if any of them contain the keys append_path, insert_path,
2140 or replace_path, that method will be called with the value as
2141 arguments. This allows for the validation to apply redirection to the
2142 path. A validation item of:
2143
2144 {field => 'foo', required => 1, append_path => ['bar', 'baz']}
2145
2146 would append 'bar' and 'baz' to the path should all validation succeed.
2147
2148 =item verify_user (method)
2149
2150 Installed as a hook to CGI::Ex::App during get_valid_auth. Should return
2151 true if the user is ok. Default is to always return true. This can be
2152 used to abort early before the get_pass_by_user hook is called.
2153
2154 sub verify_user {
2155 my ($self, $user) = @_;
2156 return 0 if $user eq 'paul'; # don't let paul in
2157 return 1; # let anybody else in
2158 }
2159
2160 =back
2161
2162 =head1 HOW DO I SET COOKIES, REDIRECT, ETC
2163
2164 Often in your program you will want to set cookies or bounce to a differnt URL.
2165 This can be done using either the builtin CGI::Ex object or the built in
2166 CGI object. It is suggested that you only use the CGI::Ex methods as it will
2167 automatically send headers and method calls under cgi, mod_perl1, or mod_perl2.
2168 The following shows how to do basic items using the CGI::Ex object returned by
2169 the ->cgix method.
2170
2171 =over 4
2172
2173 =item printing content-type headers
2174
2175 ### CGI::Ex::App prints headers for you,
2176 ### but if you are printing custom types, you can send your own
2177 $self->cgix->print_content_type;
2178 # SAME AS
2179 # $self->cgix->print_content_type('text/html');
2180
2181 =item setting a cookie
2182
2183 $self->cgix->set_cookie({
2184 -name => "my_key",
2185 -value => 'Some Value',
2186 -expires => '1y',
2187 -path => '/',
2188 });
2189
2190 =item redirecting to another URL
2191
2192 $self->cgix->location_bounce("http://somewhereelse.com");
2193 $self->exit_nav_loop; # normally should do this to long jump out of navigation
2194
2195 =item making a QUERY_STRING
2196
2197 my $data = {foo => "bar", one => "two or three"};
2198 my $query = $self->cgix->make_form($data);
2199 # $query now equals "foo=bar&one=two%20or%20three"
2200
2201 =item getting form parameters
2202
2203 my $form = $self->form;
2204
2205 In this example $form would now contain a hashref of all POST and GET parameters
2206 passed to the server. The form method calls $self->cgix->get_form
2207 which in turn uses CGI->param to parse values. Fields with multiple passed
2208 values will be in the form of an arrayref.
2209
2210 =item getting cookies
2211
2212 my $cookies = $self->cookies;
2213
2214 In this example $cookies would be a hashref of all passed in cookies. The
2215 cookies method calls $self->cgix->get_cookies which in turn uses CGI->cookie
2216 to parse values.
2217
2218 =back
2219
2220 See the CGI::Ex and CGI documentation for more information.
2221
2222 =head1 COMPARISON TO OTHER APPLICATION MODULES
2223
2224 The concepts used in CGI::Ex::App are not novel or unique. However, they
2225 are all commonly used and very useful. All application builders were
2226 built because somebody observed that there are common design patterns
2227 in CGI building. CGI::Ex::App differs in that it has found more common design
2228 patterns of CGI's than other application builders and tries to get in the way
2229 less than others.
2230
2231 CGI::Ex::App is intended to be sub classed, and sub sub classed, and each step
2232 can choose to be sub classed or not. CGI::Ex::App tries to remain simple
2233 while still providing "more than one way to do it." It also tries to avoid
2234 making any sub classes have to call ->SUPER:: (although that is fine too).
2235
2236 And if what you are doing on a particular is far too complicated or custom for
2237 what CGI::Ex::App provides, CGI::Ex::App makes it trivial to override all behavior.
2238
2239 There are certainly other modules for building CGI applications. The
2240 following is a short list of other modules and how CGI::Ex::App is
2241 different.
2242
2243 =over 4
2244
2245 =item C<CGI::Application>
2246
2247 Seemingly the most well know of application builders.
2248 CGI::Ex::App is different in that it:
2249
2250 * Uses Template::Toolkit compatible CGI::Ex::Template by default
2251 CGI::Ex::App can easily use another toolkit by simply
2252 overriding the ->swap_template method.
2253 CGI::Application uses HTML::Template.
2254 * Offers integrated data validation.
2255 CGI::Application has had custom plugins created that
2256 add some of this functionality. CGI::Ex::App has the benefit
2257 that validation is automatically available in javascript as well.
2258 * Allows the user to print at any time (so long as proper headers
2259 are sent. CGI::Application requires data to be pipelined.
2260 * Offers hooks into the various phases of each step ("mode" in
2261 CGI::Application lingo). CGI::Application provides only ->runmode
2262 which is only a dispatch.
2263 * Support for easily jumping around in navigation steps.
2264 * Support for storing some steps in another package.
2265 * Integrated authentication
2266 * Integrated form filling
2267 * Integrated PATH_INFO mapping
2268
2269 CGI::Ex::App and CGI::Application are similar in that they take care
2270 of handling headers and they allow for calling other "runmodes" from
2271 within any given runmode. CGI::Ex::App's ->run_step is essentially
2272 equivalent to a method call defined in CGI::Application's ->run_modes.
2273 The ->run method of CGI::Application starts the application in the same
2274 manner as CGI::Ex::App's ->navigate call. Many of the hooks around
2275 CGI::Ex::App's ->run_step call are similar in nature to those provided by
2276 CGI::Application.
2277
2278 =item C<CGI::Prototype>
2279
2280 There are actually many similarities. One of the nicest things about
2281 CGI::Prototype is that it is extremely short (very very short). The
2282 ->activate starts the application in the same manner as CGI::Ex::App's
2283 ->navigate call. Both use Template::Toolkit as the default template
2284 system (CGI::Ex::App uses CGI::Ex::Template which is TT compatible).
2285 CGI::Ex::App is differrent in that it:
2286
2287 * Offers more hooks into the various phases of each step.
2288 * Support for easily jumping around in navigation steps.
2289 * Support for storing only some steps in another package.
2290 * Integrated data validation
2291 * Integrated authentication
2292 * Integrated form filling
2293 * Integrated PATH_INFO mapping
2294
2295 =back
2296
2297
2298 =head1 SIMPLE EXTENDED EXAMPLE
2299
2300 The following example shows the creation of a basic recipe
2301 database. It requires the use of DBD::SQLite, but that is all.
2302 Once you have configured the db_file and base_dir_abs methods
2303 of the "recipe" file, you will have a working script that
2304 does CRUD for the recipe table. The observant reader may ask - why
2305 not use Catalyst or Ruby on Rails? The observant programmer will
2306 reply that making a framework do something simple is easy, but making
2307 it do something complex is complex and any framework that tries to
2308 do the those complex things for you is too complex. CGI::Ex::App
2309 lets you write the complex logic but gives you the ability to
2310 not worry about the boring details such as template engines,
2311 or sticky forms, or cgi parameters, or data validation. Once
2312 you are setup and are running, you are only left with providing
2313 the core logic of the application.
2314
2315 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2316 ### --------------------------------------------
2317 #!/usr/bin/perl -w
2318
2319 use lib qw(/var/www/lib);
2320 use Recipe;
2321 Recipe->navigate;
2322
2323
2324 ### File: /var/www/lib/Recipe.pm
2325 ### --------------------------------------------
2326 package Recipe;
2327
2328 use strict;
2329 use base qw(CGI::Ex::App);
2330 use CGI::Ex::Dump qw(debug);
2331
2332 use DBI;
2333 use DBD::SQLite;
2334
2335 ###------------------------------------------###
2336
2337 sub post_navigate {
2338 # show what happened
2339 debug shift->dump_history;
2340 }
2341
2342 sub base_dir_abs { '/var/www/templates' }
2343
2344 sub base_dir_rel { 'content' }
2345
2346 sub db_file { '/var/www/recipe.sqlite' }
2347
2348 sub dbh {
2349 my $self = shift;
2350 if (! $self->{'dbh'}) {
2351 my $file = $self->db_file;
2352 my $exists = -e $file;
2353 $self->{'dbh'} = DBI->connect("dbi:SQLite:dbname=$file", '', '',
2354 {RaiseError => 1});
2355 $self->create_tables if ! $exists;
2356 }
2357 return $self->{'dbh'};
2358 }
2359
2360 sub create_tables {
2361 my $self = shift;
2362
2363 $self->dbh->do("CREATE TABLE recipe (
2364 id INTEGER PRIMARY KEY AUTOINCREMENT,
2365 title VARCHAR(50) NOT NULL,
2366 ingredients VARCHAR(255) NOT NULL,
2367 directions VARCHAR(255) NOT NULL,
2368 date_added VARCHAR(20) NOT NULL
2369 )");
2370 }
2371
2372 ###----------------------------------------------------------------###
2373
2374 sub main_info_complete { 0 }
2375
2376 sub main_hash_swap {
2377 my $self = shift;
2378
2379 my $s = "SELECT id, title, date_added
2380 FROM recipe
2381 ORDER BY date_added";
2382 my $data = $self->dbh->selectall_arrayref($s);
2383 my @data = map {my %h; @h{qw(id title date_added)} = @$_; \%h} @$data;
2384
2385 return {
2386 recipies => \@data,
2387 };
2388 }
2389
2390 ###----------------------------------------------------------------###
2391
2392 sub add_name_step { 'edit' }
2393
2394 sub add_hash_validation {
2395 return {
2396 'group order' => [qw(title ingredients directions)],
2397 title => {
2398 required => 1,
2399 max_len => 30,
2400 },
2401 ingredients => {
2402 required => 1,
2403 max_len => 255,
2404 },
2405 directions => {
2406 required => 1,
2407 max_len => 255,
2408 },
2409 };
2410 }
2411
2412 sub add_finalize {
2413 my $self = shift;
2414 my $form = $self->form;
2415
2416 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ?";
2417 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'});
2418 if ($count) {
2419 $self->add_errors(title => 'A recipe by this title already exists');
2420 return 0;
2421 }
2422
2423 $s = "INSERT INTO recipe (title, ingredients, directions, date_added)
2424 VALUES (?, ?, ?, ?)";
2425 $self->dbh->do($s, {}, $form->{'title'},
2426 $form->{'ingredients'},
2427 $form->{'directions'},
2428 scalar(localtime));
2429
2430 $self->add_to_form(success => "Recipe added to the database");
2431
2432 return 1;
2433 }
2434
2435 ###----------------------------------------------------------------###
2436
2437 sub edit_skip { shift->form->{'id'} ? 0 : 1 }
2438
2439 sub edit_hash_common {
2440 my $self = shift;
2441 return {} if $self->ready_validate;
2442
2443 my $sth = $self->dbh->prepare("SELECT * FROM recipe WHERE id = ?");
2444 $sth->execute($self->form->{'id'});
2445 my $hash = $sth->fetchrow_hashref;
2446
2447 return $hash;
2448 }
2449
2450 sub edit_hash_validation { shift->add_hash_validation(@_) }
2451
2452 sub edit_finalize {
2453 my $self = shift;
2454 my $form = $self->form;
2455
2456 my $s = "SELECT COUNT(*) FROM recipe WHERE title = ? AND id != ?";
2457 my ($count) = $self->dbh->selectrow_array($s, {}, $form->{'title'}, $form->{'id'});
2458 if ($count) {
2459 $self->add_errors(title => 'A recipe by this title already exists');
2460 return 0;
2461 }
2462
2463 my $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?";
2464 $self->dbh->do($s, {}, $form->{'title'},
2465 $form->{'ingredients'},
2466 $form->{'directions'},
2467 $form->{'id'});
2468
2469 $self->add_to_form(success => "Recipe updated in the database");
2470
2471 return 1;
2472 }
2473
2474 ###----------------------------------------------------------------###
2475
2476 sub view_skip { shift->edit_skip(@_) }
2477
2478 sub view_hash_common { shift->edit_hash_common(@_) }
2479
2480 ###----------------------------------------------------------------###
2481
2482 sub delete_skip { shift->edit_skip(@_) }
2483
2484 sub delete_info_complete { 1 }
2485
2486 sub delete_finalize {
2487 my $self = shift;
2488 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
2489
2490 $self->add_to_form(success => "Recipe deleted from the database");
2491 return 1;
2492 }
2493
2494 1;
2495
2496 __END__
2497
2498
2499
2500 File: /var/www/templates/content/recipe/main.html
2501 ### --------------------------------------------
2502 <html>
2503 <head>
2504 <title>Recipe DB</title>
2505 </head>
2506 <h1>Recipe DB</h1>
2507
2508 [% IF success %]<span style="color:darkgreen"><h2>[% success %]</h2></span>[% END %]
2509
2510 <table style="border:1px solid blue">
2511 <tr><th>#</th><th>Title</th><th>Date Added</th></tr>
2512
2513 [% FOR row IN recipies %]
2514 <tr>
2515 <td>[% loop.count %].</td>
2516 <td><a href="[% script_name %]/view?id=[% row.id %]">[% row.title %]</a>
2517 (<a href="[% script_name %]/edit?id=[% row.id %]">Edit</a>)
2518 </td>
2519 <td>[% row.date_added %]</td>
2520 </tr>
2521 [% END %]
2522
2523 <tr><td colspan=2 align=right><a href="[% script_name %]/add">Add new recipe</a></td></tr>
2524 </table>
2525
2526 </html>
2527
2528
2529 File: /var/www/templates/content/recipe/edit.html
2530 ### --------------------------------------------
2531 <html>
2532 <head>
2533 <title>[% step == 'add' ? "Add" : "Edit" %] Recipe</title>
2534 </head>
2535 <h1>[% step == 'add' ? "Add" : "Edit" %] Recipe</h1>
2536
2537 <form method=post name=[% form_name %]>
2538 <input type=hidden name=step>
2539
2540 <table>
2541
2542 [% IF step != 'add' ~%]
2543 <tr>
2544 <td><b>Id:</b></td><td>[% id %]</td></tr>
2545 <input type=hidden name=id>
2546 </tr>
2547 <tr>
2548 <td><b>Date Added:</b></td><td>[% date_added %]</td></tr>
2549 </tr>
2550 [% END ~%]
2551
2552 <tr>
2553 <td valign=top><b>Title:</b></td>
2554 <td><input type=text name=title>
2555 <span style='color:red' id=title_error>[% title_error %]</span></td>
2556 </tr>
2557 <tr>
2558 <td valign=top><b>Ingredients:</b></td>
2559 <td><textarea name=ingredients rows=10 cols=40 wrap=physical></textarea>
2560 <span style='color:red' id=ingredients_error>[% ingredients_error %]</span></td>
2561 </tr>
2562 <tr>
2563 <td valign=top><b>Directions:</b></td>
2564 <td><textarea name=directions rows=10 cols=40 wrap=virtual></textarea>
2565 <span style='color:red' id=directions_error>[% directions_error %]</span></td>
2566 </tr>
2567 <tr>
2568 <td colspan=2 align=right>
2569 <input type=submit value="[% step == 'add' ? 'Add' : 'Update' %]"></td>
2570 </tr>
2571 </table>
2572 </form>
2573
2574 (<a href="[% script_name %]">Main Menu</a>)
2575 [% IF step != 'add' ~%]
2576 (<a href="[% script_name %]/delete?id=[% id %]">Delete this recipe</a>)
2577 [%~ END %]
2578
2579 [% js_validation %]
2580
2581 </html>
2582
2583
2584 File: /var/www/templates/content/recipe/view.html
2585 ### --------------------------------------------
2586 <html>
2587 <head>
2588 <title>[% title %] - Recipe DB</title>
2589 </head>
2590 <h1>[% title %]</h1>
2591 <h3>Date Added: [% date_added %]</h3>
2592
2593 <h2>Ingredients</h2>
2594 [% ingredients %]
2595
2596 <h2>Directions</h2>
2597 [% directions %]
2598
2599 <hr>
2600 (<a href="[% script_name %]">Main Menu</a>)
2601 (<a href="[% script_name %]/edit?id=[% id %]">Edit this recipe</a>)
2602
2603 </html>
2604
2605 ### --------------------------------------------
2606
2607 Notes:
2608
2609 The dbh method returns an SQLite dbh handle and auto creates the
2610 schema. You will normally want to use MySQL or Oracle, or Postgres
2611 and you will want your schema to NOT be auto-created.
2612
2613 This sample uses hand rolled SQL. Class::DBI or a similar module
2614 might make this example shorter. However, more complex cases that
2615 need to involve two or three or four tables would probably be better
2616 off using the hand crafted SQL.
2617
2618 This sample uses SQL. You could write the application to use whatever
2619 storage you want - or even to do nothing with the submitted data.
2620
2621 We had to write our own HTML (Catalyst and Ruby on Rails do this for
2622 you). For most development work - the HTML should be in a static
2623 location so that it can be worked on by designers. It is nice that
2624 the other frameworks give you stub html - but that is all it is. It
2625 is worth about as much as copying and pasting the above examples. All
2626 worthwhile HTML will go through a non-automated design/finalization
2627 process.
2628
2629 The add step used the same template as the edit step. We did
2630 this using the add_name_step hook which returned "edit". The template
2631 contains IF conditions to show different information if we were in
2632 add mode or edit mode.
2633
2634 We reused code, validation, and templates. Code and data reuse is a
2635 good thing.
2636
2637 The edit_hash_common returns an empty hashref if the form was ready to
2638 validate. When hash_common is called and the form is ready to
2639 validate, that means the form failed validation and is now printing
2640 out the page. To let us fall back and use the "sticky" form fields
2641 that were just submitted, we need to not provide values in the
2642 hash_common method.
2643
2644 We use hash_common. Values from hash_common are used for both
2645 template swapping and filling. We could have used hash_swap and
2646 hash_fill independently.
2647
2648 The hook main_info_complete is hard coded to 0. This basically says
2649 that we will never try and validate or finalize the main step - which
2650 is most often the case.
2651
2652 =head1 SEPARATING STEPS INTO SEPARATE FILES
2653
2654 It may be useful sometimes to separate some or all of the steps of an
2655 application into separate files. This is the way that CGI::Prototype
2656 works. This is useful in cases were some steps and their hooks are
2657 overly large - or are seldom used.
2658
2659 The following modifications can be made to the previous "recipe db"
2660 example that would move the "delete" step into its own file. Similar
2661 actions can be taken to break other steps into their own file as well.
2662
2663
2664 ### File: /var/www/lib/Recipe.pm
2665 ### Same as before but add the following line:
2666 ### --------------------------------------------
2667
2668 sub allow_morph { 1 }
2669
2670
2671 ### File: /var/www/lib/Recipe/Delete.pm
2672 ### Remove the delete_* subs from lib/Recipe.pm
2673 ### --------------------------------------------
2674 package Recipe::Delete;
2675
2676 use strict;
2677 use base qw(Recipe);
2678
2679 sub skip { shift->edit_skip(@_) }
2680
2681 sub info_complete { 1 }
2682
2683 sub finalize {
2684 my $self = shift;
2685 $self->dbh->do("DELETE FROM recipe WHERE id = ?", {}, $self->form->{'id'});
2686
2687 $self->add_to_form(success => "Recipe deleted from the database");
2688 return 1;
2689 }
2690
2691
2692 Notes:
2693
2694 The hooks that are called (skip, info_complete, and finalize) do not
2695 have to be prefixed with the step name because they are now in their
2696 own individual package space. However, they could still be named
2697 delete_skip, delete_info_complete, and delete_finalize and the
2698 run_hook method will find them (this would allow several steps with
2699 the same "morph_package" to still be stored in the same external
2700 module).
2701
2702 The method allow_morph is passed the step that we are attempting to
2703 morph to. If allow_morph returns true every time, then it will try
2704 and require the extra packages every time that step is ran. You could
2705 limit the morphing process to run only on certain steps by using code
2706 similar to the following:
2707
2708 sub allow_morph { return {delete => 1} }
2709
2710 # OR
2711
2712 sub allow_morph {
2713 my ($self, $step) = @_;
2714 return ($step eq 'delete') ? 1 : 0;
2715 }
2716
2717 The CGI::Ex::App temporarily blesses the object into the
2718 "morph_package" for the duration of the step and re-blesses it into the
2719 original package upon exit. See the morph method and allow_morph for more
2720 information.
2721
2722 =head1 RUNNING UNDER MOD_PERL
2723
2724 The previous samples are essentially suitable for running under flat CGI,
2725 Fast CGI, or mod_perl Registry or mod_perl PerlRun type environments. It
2726 is very easy to move the previous example to be a true mod_perl handler.
2727
2728 To convert the previous recipe example, simply add the following:
2729
2730 ### File: /var/www/lib/Recipe.pm
2731 ### Same as before but add the following lines:
2732 ### --------------------------------------------
2733
2734 sub handler {
2735 Recipe->navigate;
2736 return;
2737 }
2738
2739
2740 ### File: apache2.conf - or whatever your apache conf file is.
2741 ### --------------------------------------------
2742 <Location /recipe>
2743 SetHandler perl-script
2744 PerlHandler Recipe
2745 </Location>
2746
2747 Notes:
2748
2749 Both the /cgi-bin/recipe version and the /recipe version can co-exist.
2750 One of them will be a normal cgi and the other will correctly use
2751 mod_perl hooks for headers.
2752
2753 Setting the location to /recipe means that the $ENV{SCRIPT_NAME} will
2754 also be set to /recipe. This means that name_module method will
2755 resolve to "recipe". If a different URI location is desired such as
2756 "/my_cool_recipe" but the program is to use the same template content
2757 (in the /var/www/templates/content/recipe directory), then we would
2758 need to explicitly set the "name_module" parameter. It could be done
2759 in either of the following ways:
2760
2761 ### File: /var/www/lib/Recipe.pm
2762 ### Same as before but add the following line:
2763 ### --------------------------------------------
2764
2765 sub name_module { 'recipe' }
2766
2767 # OR
2768
2769 sub init {
2770 my $self = shift;
2771 $self->{'name_module'} = 'recipe';
2772 }
2773
2774 In most use cases it isn't necessary to set name_module, but it also
2775 doesn't hurt and in all cases it is more descriptive to anybody who is
2776 going to maintain the code later.
2777
2778 =head1 ADDING AUTHENTICATION TO THE ENTIRE APPLICATION
2779
2780 Having authentication is sometimes a good thing. To force
2781 the entire application to be authenticated (require a valid username
2782 and password before doing anything) you could do the following.
2783
2784 ### File: /var/www/lib/Recipe.pm
2785 ### Same as before but add
2786 ### --------------------------------------------
2787
2788 sub get_pass_by_user {
2789 my $self = shift;
2790 my $user = shift;
2791 my $pass = $self->lookup_and_cache_the_pass($user);
2792 return $pass;
2793 }
2794
2795
2796 ### File: /var/www/cgi-bin/recipe (depending upon Apache configuration)
2797 ### Change the line with ->navigate; to
2798 ### --------------------------------------------
2799
2800 Recipe->navigate_authenticated;
2801
2802 # OR
2803
2804 ### File: /var/www/lib/Recipe.pm
2805 ### Same as before but add
2806 ### --------------------------------------------
2807
2808 sub require_auth { 1 }
2809
2810 # OR
2811
2812 ### File: /var/www/lib/Recipe.pm
2813 ### Same as before but add
2814 ### --------------------------------------------
2815
2816 sub init { shift->require_auth(1) }
2817
2818 See the require_auth, get_valid_auth, and auth_args methods for more information.
2819 Also see the L<CGI::Ex::Auth> perldoc.
2820
2821 =head1 ADDING AUTHENTICATION TO INDIVIDUAL STEPS
2822
2823 Sometimes you may only want to have certain steps require
2824 authentication. For example, in the previous recipe example we
2825 might want to let the main and view steps be accessible to anybody,
2826 but require authentication for the add, edit, and delete steps.
2827
2828 To do this, we would do the following to the original example (the
2829 navigation must start with ->navigate. Starting with ->navigate_authenticated
2830 will cause all steps to require validation):
2831
2832 ### File: /var/www/lib/Recipe.pm
2833 ### Same as before but add
2834 ### --------------------------------------------
2835
2836 sub get_pass_by_user {
2837 my $self = shift;
2838 my $user = shift;
2839 my $pass = $self->lookup_and_cache_the_pass($user);
2840 return $pass;
2841 }
2842
2843 sub require_auth { {add => 1, edit => 1, delete => 1} }
2844
2845 That's it. The add, edit, and delete steps will now require authentication.
2846 See the require_auth, get_valid_auth, and auth_args methods for more information.
2847 Also see the L<CGI::Ex::Auth> perldoc.
2848
2849 =head1 THANKS
2850
2851 The following corporation and individuals contributed in some part to
2852 the original versions.
2853
2854 Bizhosting.com - giving a problem that fit basic design patterns.
2855
2856 Earl Cahill - pushing the idea of more generic frameworks.
2857
2858 Adam Erickson - design feedback, bugfixing, feature suggestions.
2859
2860 James Lance - design feedback, bugfixing, feature suggestions.
2861
2862 =head1 AUTHOR
2863
2864 Paul Seamons <paul at seamons dot com>
2865
2866 =head1 LICENSE
2867
2868 This module may be distributed under the same terms as Perl itself.
2869
2870 =cut
This page took 0.180493 seconds and 4 git commands to generate.