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