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