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