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