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