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