]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole.pm
Updated patches for 2.13.
[maypole.git] / lib / Maypole.pm
1 package Maypole;
2 use base qw(Class::Accessor::Fast Class::Data::Inheritable);
3 use UNIVERSAL::require;
4 use strict;
5 use warnings;
6 use Data::Dumper;
7 use Maypole::Config;
8 use Maypole::Constants;
9 use Maypole::Headers;
10 use URI();
11 use URI::QueryParam;
12 use NEXT;
13 use File::MMagic::XS qw(:compat);
14
15 our $VERSION = '2.13';
16 our $mmagic = File::MMagic::XS->new();
17
18 # proposed privacy conventions:
19 # - no leading underscore     - public to custom application code and plugins
20 # - single leading underscore - private to the main Maypole stack - *not*
21 #     including plugins
22 # - double leading underscore - private to the current package
23
24 =head1 NAME
25
26 Maypole - MVC web application framework
27
28 =head1 SYNOPSIS
29
30 The canonical example used in the Maypole documentation is the beer database:
31
32     package BeerDB;
33     use strict;
34     use warnings; 
35     
36     # choose a frontend, initialise the config object, and load a plugin
37     use Maypole::Application qw/Relationship/;
38
39     # set everything up
40     __PACKAGE__->setup("dbi:SQLite:t/beerdb.db");
41     
42     # get the empty config object created by Maypole::Application
43     my $config = __PACKAGE__->config;
44     
45     # basic settings
46     $config->uri_base("http://localhost/beerdb");
47     $config->template_root("/path/to/templates");
48     $config->rows_per_page(10);
49     $config->display_tables([qw/beer brewery pub style/]);
50
51     # table relationships
52     $config->relationships([
53         "a brewery produces beers",
54         "a style defines beers",
55         "a pub has beers on handpumps",
56         ]);
57         
58     # validation
59     BeerDB::Brewery->untaint_columns( printable => [qw/name notes url/] );
60     BeerDB::Pub->untaint_columns( printable => [qw/name notes url/] );
61     BeerDB::Style->untaint_columns( printable => [qw/name notes/] );
62     BeerDB::Beer->untaint_columns(
63         printable => [qw/abv name price notes/],
64         integer => [qw/style brewery score/],
65         date => [ qw/date/],
66     );
67
68     # note : set up model before calling this method
69     BeerDB::Beer->required_columns([qw/name/]); 
70
71     1;    
72
73 =head1 DESCRIPTION
74
75 This documents the Maypole request object. See the L<Maypole::Manual>, for a
76 detailed guide to using Maypole.
77
78 Maypole is a Perl web application framework similar to Java's struts. It is 
79 essentially completely abstracted, and so doesn't know anything about
80 how to talk to the outside world.
81
82 To use it, you need to create a driver package which represents your entire
83 application. This is the C<BeerDB> package used as an example in the manual.
84
85 This needs to first use L<Maypole::Application> which will make your package
86 inherit from the appropriate platform driver such as C<Apache::MVC> or
87 C<CGI::Maypole>. Then, the driver calls C<setup>. This sets up the model classes
88 and configures your application. The default model class for Maypole uses
89 L<Class::DBI> to map a database to classes, but this can be changed by altering
90 configuration (B<before> calling setup.)
91
92
93 =head1 DOCUMENTATION AND SUPPORT
94
95 Note that some details in some of these resources may be out of date.
96
97 =over 4
98
99 =item The Maypole Manual
100
101 The primary documentation is the Maypole manual. This lives in the 
102 C<Maypole::Manual> pod documents included with the distribution. 
103
104 =item Embedded POD
105
106 Individual packages within the distribution contain (more or less) detailed
107 reference documentation for their API.
108
109 =item Mailing lists
110
111 There are two mailing lists - maypole-devel and maypole-users - see
112 http://maypole.perl.org/?MailingList
113
114 =item The Maypole Wiki
115
116 The Maypole wiki provides a useful store of extra documentation -
117 http://maypole.perl.org
118
119 In particular, there's a FAQ (http://maypole.perl.org/?FAQ) and a cookbook
120 (http://maypole.perl.org/?Cookbook). Again, certain information on these pages
121 may be out of date.
122
123 =item Web applications with Maypole
124
125 A tutorial written by Simon Cozens for YAPC::EU 2005 -
126 http://www.aarontrevena.co.uk/opensource/maypole/maypole-tutorial.pdf [228KB].
127
128 =item A Database-Driven Web Application in 18 Lines of Code
129
130 By Paul Barry, published in Linux Journal, March 2005.
131
132 http://www.linuxjournal.com/article/7937
133
134 "From zero to Web-based database application in eight easy steps".
135
136 Maypole won a 2005 Linux Journal Editor's Choice Award
137 (http://www.linuxjournal.com/article/8293) after featuring in this article. 
138
139 =item Build Web apps with Maypole
140
141 By Simon Cozens, on IBM's DeveloperWorks website, May 2004.
142
143 http://www-128.ibm.com/developerworks/linux/library/l-maypole/
144
145 =item Rapid Web Application Deployment with Maypole
146
147 By Simon Cozens, on O'Reilly's Perl website, April 2004.
148
149 http://www.perl.com/pub/a/2004/04/15/maypole.html
150
151 =item Authentication
152
153 Some notes written by Simon Cozens. A little bit out of date, but still 
154 very useful: http://www.aarontrevena.co.uk/opensource/maypole/authentication.html
155
156 =item CheatSheet
157
158 There's a refcard for the Maypole (and Class::DBI) APIs on the wiki -
159 http://maypole.perl.org/?CheatSheet. Probably a little out of date now - it's a
160 wiki, so feel free to fix any errors!
161
162 =item Plugins and add-ons
163
164 There are a large and growing number of plugins and other add-on modules
165 available on CPAN - http://search.cpan.org/search?query=maypole&mode=module
166
167 =item del.icio.us
168
169 You can find a range of useful Maypole links, particularly to several thoughtful
170 blog entries, starting here: http://del.icio.us/search/?all=maypole
171
172 =item CPAN ratings
173
174 There are a couple of short reviews here:
175 http://cpanratings.perl.org/dist/Maypole
176
177 =back
178
179 =cut
180
181 __PACKAGE__->mk_classdata($_) for qw( config init_done view_object model_classes_loaded);
182
183 __PACKAGE__->mk_accessors(
184     qw( params query objects model_class template_args output path
185         args action template error document_encoding content_type table
186         headers_in headers_out stash status parent build_form_elements
187         user session)
188 );
189
190 __PACKAGE__->config( Maypole::Config->new({additional => { }, request_options => { }, view_options => { },}) );
191
192 __PACKAGE__->init_done(0);
193
194 __PACKAGE__->model_classes_loaded(0);
195
196 =head1 HOOKABLE METHODS
197
198 As a framework, Maypole provides a number of B<hooks> - methods that are
199 intended to be overridden. Some of these methods come with useful default
200 behaviour, others do nothing by default. Hooks include:
201
202     Class methods
203     -------------
204     debug 
205     setup 
206     setup_model 
207     load_model_subclass
208     init
209     
210     Instance methods
211     ----------------
212     start_request_hook
213     is_model_applicable
214     get_session
215     authenticate
216     exception
217     additional_data
218     preprocess_path
219
220 =head1 CLASS METHODS
221
222 =over 4
223
224 =item debug
225
226     sub My::App::debug {1}
227
228 Returns the debugging flag. Override this in your application class to
229 enable/disable debugging.
230
231 You can also set the C<debug> flag via L<Maypole::Application>.
232
233 Some packages respond to higher debug levels, try increasing it to 2 or 3.
234
235
236 =cut
237
238 sub debug { 0 }
239
240 =item config
241
242 Returns the L<Maypole::Config> object
243
244 =item setup
245
246    My::App->setup($data_source, $user, $password, \%attr);
247
248 Initialise the Maypole application and plugins and model classes.
249 Your application should call this B<after> setting up configuration data via
250 L<"config">.
251
252 It calls the hook  C<setup_model> to setup the model. The %attr hash contains
253 options and arguments used to set up the model. See the particular model's
254 documentation. However here is the most usage of setup where
255 Maypole::Model::CDBI is the base class.
256
257  My::App->setup($data_source, $user, $password,
258        {  options => {  # These are DB connection options
259                AutoCommit => 0,
260                RaiseError => 1,
261                ...
262           },
263           # These are Class::DBI::Loader arguments.
264           relationships  => 1,
265           ...
266        }
267  );
268
269 Also, see  L<Maypole::Manual::Plugins>.
270
271 =cut
272
273
274 sub setup
275 {
276     my $class = shift;
277     
278     $class->setup_model(@_);    
279 }
280
281 =item setup_model
282
283 Called by C<setup>. This method builds the Maypole model hierarchy. 
284
285 A likely target for over-riding, if you need to build a customised model.
286
287 This method also ensures any code in custom model classes is loaded, so you
288 don't need to load them in the driver.
289
290 =cut
291
292 sub setup_model {
293   my $class = shift;
294   $class = ref $class if ref $class;
295   my $config = $class->config;
296   $config->model || $config->model('Maypole::Model::CDBI');
297   $config->model->require or die sprintf
298     "Couldn't load the model class %s: %s", $config->model, $@;
299
300   # among other things, this populates $config->classes
301   $config->model->setup_database($config, $class, @_);
302
303   $config->model->add_model_superclass($config);
304
305   # Load custom model code, if it exists - nb this must happen after the
306   # adding the model superclass, to allow code attributes to work, but before adopt(),
307   # in case adopt() calls overridden methods on $subclass
308   foreach my $subclass ( @{ $config->classes } ) {
309     $class->load_model_subclass($subclass) unless ($class->model_classes_loaded());
310     $config->model->adopt($subclass) if $config->model->can("adopt");
311   }
312
313 }
314
315 =item load_model_subclass($subclass)
316
317 This method is called from C<setup_model()>. It attempts to load the
318 C<$subclass> package, if one exists. So if you make a customized C<BeerDB::Beer>
319 package, you don't need to explicitly load it. 
320
321 If automatic loading causes problems, Override load_model_subclass in your driver.
322
323 sub load_model_subclass {};
324
325 Or perhaps during development, if you don't want to load up custom classes, you 
326 can override this method and load them manually. 
327
328 =cut
329
330 sub load_model_subclass {
331   my ($class, $subclass) = @_;
332
333   my $config = $class->config;
334
335   # Load any external files for the model base class or subclasses
336   # (e.g. BeerDB/DBI.pm or BeerDB/Beer.pm) based on code borrowed from
337   # Maypole::Plugin::Loader and Class::DBI.
338   if ( $subclass->require ) {
339     warn "Loaded external module for '$subclass'\n" if $class->debug > 1;
340   } else {
341     (my $filename = $subclass) =~ s!::!/!g;
342     die "Loading '$subclass' failed: $@\n"
343       unless $@ =~ /Can\'t locate \Q$filename\E\.pm/;
344     warn "No external module for '$subclass'"
345       if $class->debug > 1;
346   }
347 }
348
349 =item init
350
351 Loads the view class and instantiates the view object.
352
353 You should not call this directly, but you may wish to override this to add
354 application-specific initialisation - see L<Maypole::Manual::Plugins>.
355
356 =cut
357
358 sub init 
359 {
360     my $class  = shift;
361     my $config = $class->config;
362     $config->view || $config->view("Maypole::View::TT");
363     $config->view->require;
364     die "Couldn't load the view class " . $config->view . ": $@" if $@;
365     $config->display_tables
366       || $config->display_tables( $class->config->tables );
367     $class->view_object( $class->config->view->new );
368     $class->init_done(1);
369 }
370
371 =item new
372
373 Constructs a very minimal new Maypole request object.
374
375 =cut
376
377 sub new
378 {
379     my ($class) = @_;
380     my $self = bless {
381         config        => $class->config,
382     }, $class;
383
384     $self->stash({});
385     $self->params({});
386     $self->query({});
387     $self->template_args({});
388     $self->args([]);
389     $self->objects([]);
390     return $self;
391 }
392
393 =item view_object
394
395 Get/set the Maypole::View object
396
397 =back
398
399 =head1 INSTANCE METHODS
400
401 =head2 Workflow
402
403 =over 4
404
405 =item handler
406
407 This method sets up the class if it's not done yet, sets some defaults and
408 leaves the dirty work to C<handler_guts>.
409
410 =cut
411
412 # handler() has a method attribute so that mod_perl will invoke
413 # BeerDB->handler() as a method rather than a plain function
414 # BeerDB::handler() and so this inherited implementation will be
415 # found. See e.g. "Practical mod_perl" by Bekman & Cholet for
416 # more information <http://modperlbook.org/html/ch25_01.html>
417 sub handler : method  {
418   # See Maypole::Workflow before trying to understand this.
419   my ($class, $req) = @_;
420     
421   $class->init unless $class->init_done;
422
423   my $self = $class->new;
424     
425   # initialise the request
426   $self->headers_out(Maypole::Headers->new);
427   $self->get_request($req);
428
429   $self->parse_location;
430
431   # hook useful for declining static requests e.g. images, or perhaps for 
432   # sanitizing request parameters
433   $self->status(Maypole::Constants::OK()); # set the default
434   $self->__call_hook('start_request_hook');
435   return $self->status unless $self->status == Maypole::Constants::OK();
436   die "status undefined after start_request_hook()" unless defined
437     $self->status;
438
439   my $session = $self->get_session;
440   $self->session($self->{session} || $session);
441   my $user = $self->get_user;
442   $self->user($self->{user} || $user);
443
444   my $status = $self->handler_guts;
445   return $status unless $status == OK;
446   # TODO: require send_output to return a status code
447   $self->send_output;
448   return $status;
449 }
450
451 =item component
452
453   Run Maypole sub-requests as a component of the request
454
455   [% request.component("/beer/view_as_component/20") %]
456
457   Allows you to integrate the results of a Maypole request into an existing
458 request. You'll need to set up actions and templates
459 which return fragments of HTML rather than entire pages, but once you've
460 done that, you can use the C<component> method of the Maypole request object
461 to call those actions. You may pass a query string in the usual URL style.
462
463 You should not fully qualify the Maypole URLs.
464
465 Note: any HTTP POST or URL parameters passed to the parent are not passed to the
466 component sub-request, only what is included in the url passed as an argument
467 to the method
468
469 =cut
470
471 sub component {
472     my ( $r, $path ) = @_;
473     my $self = bless { parent => $r, config => $r->{config}, } , ref $r;
474     $self->stash({});
475     $self->params({});
476     $self->query({});
477     $self->template_args({});
478     $self->args([]);
479     $self->objects([]);
480
481     $self->session($self->get_session);
482     $self->user($self->get_user);
483
484     my $url = URI->new($path);
485     $self->{path} = $url->path;
486     $self->parse_path;
487     $self->params( $url->query_form_hash );
488     $self->handler_guts;
489     return $self->output;
490 }
491
492 sub get_template_root {
493     my $self = shift;
494     my $r    = shift;
495     return $r->parent->get_template_root if $r->{parent};
496     return $self->NEXT::DISTINCT::get_template_root( $r, @_ );
497 }
498
499 sub view_object {
500     my $self = shift;
501     my $r    = shift;
502     return $r->parent->view_object if $r->{parent};
503     return $self->NEXT::DISTINCT::view_object( $r, @_ );
504 }
505
506 # Instead of making plugin authors use the NEXT::DISTINCT hoopla to ensure other 
507 # plugins also get to call the hook, we can cycle through the application's 
508 # @ISA and call them all here. Doesn't work for setup() though, because it's 
509 # too ingrained in the stack. We could add a run_setup() method, but we'd break 
510 # lots of existing code.
511 sub __call_hook
512 {
513     my ($self, $hook) = @_;
514     
515     my @plugins;
516     {
517         my $class = ref($self);
518         no strict 'refs';
519         @plugins = @{"$class\::ISA"};
520     }
521     
522     # this is either a custom method in the driver, or the method in the 1st 
523     # plugin, or the 'null' method in the frontend (i.e. inherited from 
524     # Maypole.pm) - we need to be careful to only call it once
525     my $first_hook = $self->can($hook);
526     $self->$first_hook;  
527     
528     my %seen = ( $first_hook => 1 );
529
530     # @plugins includes the frontend
531     foreach my $plugin (@plugins)
532     {
533         next unless my $plugin_hook = $plugin->can($hook);
534         next if $seen{$plugin_hook}++;
535         $self->$plugin_hook;
536     }
537 }
538
539 =item handler_guts
540
541 This is the main request handling method and calls various methods to handle the
542 request/response and defines the workflow within Maypole.
543
544 =cut
545
546 # The root of all evil
547 sub handler_guts {
548   my ($self) = @_;
549   $self->build_form_elements(1) unless (defined ($self->config->build_form_elements) && $self->config->build_form_elements == 0);
550   $self->__load_request_model;
551
552   my $applicable = $self->is_model_applicable == OK;
553
554   my $status;
555
556   # handle authentication
557   eval { $status = $self->call_authenticate };
558   if ( my $error = $@ ) {
559     $status = $self->call_exception($error, "authentication");
560     if ( $status != OK ) {
561       $self->warn("caught authenticate error: $error");
562       return $self->debug ? 
563         $self->view_object->error($self, $error) : ERROR;
564     }
565   }
566   if ( $self->debug and $status != OK and $status != DECLINED ) {
567     $self->view_object->error( $self,
568                                "Got unexpected status $status from calling authentication" );
569   }
570
571   return $status unless $status == OK;
572
573   # We run additional_data for every request
574   $self->additional_data;
575
576   # process request with model if applicable and template not set.
577   if ($applicable) {
578     unless ($self->{template}) {
579       eval { $self->model_class->process($self) };
580       if ( my $error = $@ ) {
581         $status = $self->call_exception($error, "model");
582         if ( $status != OK ) {
583           $self->warn("caught model error: $error");
584           return $self->debug ? 
585             $self->view_object->error($self, $error) : ERROR;
586         }
587       }
588     }
589   } else {
590     $self->__setup_plain_template;
591   }
592
593   # less frequent path - perhaps output has been set to an error message
594   if ($self->output) {
595     $self->{content_type}      ||= $self->__get_mime_type();
596     $self->{document_encoding} ||= "utf-8";
597     return OK;
598   }
599
600   # normal path - no output has been generated yet
601   my $processed_view_ok = $self->__call_process_view;
602
603   $self->{content_type}      ||= $self->__get_mime_type();
604   $self->{document_encoding} ||= "utf-8";
605
606   return $processed_view_ok;
607 }
608
609 my %filetypes = (
610                  'js' => 'text/javascript',
611                  'css' => 'text/css',
612                  'htm' => 'text/html',
613                  'html' => 'text/html',
614                 );
615
616 sub __get_mime_type {
617   my $self = shift;
618   my $type = 'text/html';
619   if ($self->path =~ m/.*\.(\w{2,4})$/) {
620     $type = $filetypes{$1};
621   } else {
622     my $output = $self->output;
623     if (defined $output) {
624       $type = $mmagic->checktype_contents($output);
625     }
626   }
627   return $type;
628 }
629
630 sub __load_request_model
631 {
632     my ($self) = @_;
633         # We may get a made up class from class_of
634     my $mclass = $self->config->model->class_of($self, $self->table);
635     if ( eval {$mclass->isa('Maypole::Model::Base')} ) {
636         $self->model_class( $mclass );
637     }
638     elsif ($self->debug > 1) {
639       $self->warn("***Warning:  No $mclass class appropriate for model. @_");
640     }
641 }
642
643
644 # is_applicable() returned false, so set up a plain template. Model processing 
645 # will be skipped, but need to remove the model anyway so the template can't 
646 # access it. 
647 sub __setup_plain_template
648 {
649     my ($self) = @_;
650
651     # It's just a plain template
652     $self->build_form_elements(0);
653     $self->model_class(undef);
654
655     unless ($self->template) {
656       # FIXME: this is likely to be redundant and is definately causing problems.
657       my $path = $self->path;
658       $path =~ s{/$}{};    # De-absolutify
659       $self->path($path);
660       $self->template($self->path);
661     }
662 }
663
664 # The model has been processed or skipped (if is_applicable returned false), 
665 # any exceptions have been handled, and there's no content in $self->output
666 sub __call_process_view {
667   my ($self) = @_;
668
669   my $status = eval { $self->view_object->process($self) };
670
671   my $error = $@ || $self->{error};
672
673   if ( $error ) {
674     $status = $self->call_exception($error, "view");
675
676     if ( $status != OK ) {
677       warn "caught view error: $error" if $self->debug;
678       return $self->debug ? 
679         $self->view_object->error($self, $error) : ERROR;
680     }
681   }
682
683   return $status;
684 }
685
686 =item warn
687
688 $r->warn('its all gone pete tong');
689
690 Warn must be implemented by the backend, i.e. Apache::MVC
691 and warn to stderr or appropriate logfile.
692
693 You can also over-ride this in your Maypole driver, should you
694 want to use something like Log::Log4perl instead.
695
696 =cut
697
698 sub warn { }
699
700 =item build_form_elements
701
702 $r->build_form_elements(0);
703
704 Specify (in an action) whether to build HTML form elements and populate
705 the cgi element of classmetadata in the view.
706
707 You can set this globally using the accessor of the same name in Maypole::Config,
708 this method allows you to over-ride that setting per action.
709
710 =cut
711
712 =item get_request
713
714 You should only need to define this method if you are writing a new
715 Maypole backend. It should return something that looks like an Apache
716 or CGI request object, it defaults to blank.
717
718 =cut
719
720 sub get_request { }
721
722 =item parse_location
723
724 Turns the backend request (e.g. Apache::MVC, Maypole, CGI) into a Maypole
725 request. It does this by setting the C<path>, and invoking C<parse_path> and
726 C<parse_args>.
727
728 You should only need to define this method if you are writing a new Maypole
729 backend.
730
731 =cut
732
733 sub parse_location 
734 {
735     die "parse_location is a virtual method. Do not use Maypole directly; " . 
736                 "use Apache::MVC or similar";
737 }
738
739 =item start_request_hook
740
741 This is called immediately after setting up the basic request. The default
742 method does nothing. 
743
744 The value of C<< $r->status >> is set to C<OK> before this hook is run. Your 
745 implementation can change the status code, or leave it alone. 
746
747 After this hook has run, Maypole will check the value of C<status>. For any
748 value other than C<OK>, Maypole returns the C<status> immediately. 
749
750 This is useful for filtering out requests for static files, e.g. images, which
751 should not be processed by Maypole or by the templating engine:
752
753     sub start_request_hook
754     {
755         my ($r) = @_;
756         
757         $r->status(DECLINED) if $r->path =~ /\.jpg$/;
758     }
759     
760 Multiple plugins, and the driver, can define this hook - Maypole will call all
761 of them. You should check for and probably not change any non-OK C<status>
762 value:
763
764     package Maypole::Plugin::MyApp::SkipFavicon;
765     
766     sub start_request_hook
767     {
768         my ($r) = @_;
769         
770         # check if a previous plugin has already DECLINED this request
771         # - probably unnecessary in this example, but you get the idea
772         return unless $r->status == OK;
773         
774         # then do our stuff
775         $r->status(DECLINED) if $r->path =~ /favicon\.ico/;
776     }        
777      
778 =cut
779
780 sub start_request_hook { }
781
782 =item is_applicable
783
784 B<This method is deprecated> as of version 2.11. If you have overridden it,
785 please override C<is_model_applicable> instead, and change the return type
786 from a Maypole:Constant to a true/false value.
787
788 Returns a Maypole::Constant to indicate whether the request is valid.
789
790 =cut
791
792 sub is_applicable { return shift->is_model_applicable(@_); }
793
794 =item is_model_applicable
795
796 Returns true or false to indicate whether the request is valid.
797
798 The default implementation checks that C<< $r->table >> is publicly
799 accessible and that the model class is configured to handle the
800 C<< $r->action >>.
801
802 =cut
803
804 sub is_model_applicable {
805     my ($self) = @_;
806
807     # Establish which tables should be processed by the model
808     my $config = $self->config;
809     
810     $config->ok_tables || $config->ok_tables( $config->display_tables );
811     
812     $config->ok_tables( { map { $_ => 1 } @{ $config->ok_tables } } )
813         if ref $config->ok_tables eq "ARRAY";
814         
815     my $ok_tables = $config->ok_tables;
816       
817     # Does this request concern a table to be processed by the model?
818     my $table = $self->table;
819     
820     my $ok = 0;
821     
822     if (exists $ok_tables->{$table}) 
823     {
824         $ok = 1;
825     } 
826
827     if (not $ok) 
828     {
829         $self->warn ("We don't have that table ($table).\n"
830             . "Available tables are: "
831             . join( ",", keys %$ok_tables ))
832                 if $self->debug and not $ok_tables->{$table};
833                 
834         return DECLINED;
835     }
836     
837     # Is the action public?
838     my $action = $self->action;
839     return OK if $self->model_class->is_public($action);
840     
841     $self->warn("The action '$action' is not applicable to the table '$table'")
842          if $self->debug;
843     
844     return DECLINED;
845 }
846
847 =item get_session
848
849 Called immediately after C<start_request_hook()>.
850
851 This method should return a session, which will be stored in the request's
852 C<session> attribute.
853
854 The default method is empty. 
855
856 =cut
857
858 sub get_session { }
859
860 =item get_user
861
862 Called immediately after C<get_session>.
863
864 This method should return a user, which will be stored in the request's C<user>
865 attribute.
866
867 The default method is empty.
868
869 =cut
870
871 sub get_user {}
872
873 =item call_authenticate
874
875 This method first checks if the relevant model class
876 can authenticate the user, or falls back to the default
877 authenticate method of your Maypole application.
878
879 =cut
880
881 sub call_authenticate 
882 {
883     my ($self) = @_;
884
885     # Check if we have a model class with an authenticate() to delegate to
886     return $self->model_class->authenticate($self) 
887         if $self->model_class and $self->model_class->can('authenticate');
888     
889     # Interface consistency is a Good Thing - 
890     # the invocant and the argument may one day be different things 
891     # (i.e. controller and request), like they are when authenticate() 
892     # is called on a model class (i.e. model and request)
893     return $self->authenticate($self);   
894 }
895
896 =item authenticate
897
898 Returns a Maypole::Constant to indicate whether the user is authenticated for
899 the Maypole request.
900
901 The default implementation returns C<OK>
902
903 =cut
904
905 sub authenticate { return OK }
906
907
908 =item call_exception
909
910 This model is called to catch exceptions, first after authenticate, then after
911 processing the model class, and finally to check for exceptions from the view
912 class.
913
914 This method first checks if the relevant model class
915 can handle exceptions the user, or falls back to the default
916 exception method of your Maypole application.
917
918 =cut
919
920 sub call_exception 
921 {
922     my ($self, $error, $when) = @_;
923
924     # Check if we have a model class with an exception() to delegate to
925     if ( $self->model_class && $self->model_class->can('exception') )
926     {
927         my $status = $self->model_class->exception( $self, $error, $when );
928         return $status if $status == OK;
929     }
930     
931     return $self->exception($error, $when);
932 }
933
934
935 =item exception
936
937 This method is called if any exceptions are raised during the authentication or
938 model/view processing. It should accept the exception as a parameter and return
939 a Maypole::Constant to indicate whether the request should continue to be
940 processed.
941
942 =cut
943
944 sub exception { 
945     my ($self, $error, $when) = @_;
946     if (ref $self->view_object && $self->view_object->can("report_error") and $self->debug) {
947         $self->view_object->report_error($self, $error, $when);
948         return OK;
949     }
950     return ERROR;
951 }
952
953 =item additional_data
954
955 Called before the model processes the request, this method gives you a chance to
956 do some processing for each request, for example, manipulating C<template_args>.
957
958 =cut
959
960 sub additional_data { }
961
962 =item send_output
963
964 Sends the output and additional headers to the user.
965
966 =cut
967
968 sub send_output {
969     die "send_output is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
970 }
971
972
973 =back
974
975 =head2 Path processing and manipulation
976
977 =over 4
978
979 =item path
980
981 Returns the request path
982
983 =item parse_path
984
985 Parses the request path and sets the C<args>, C<action> and C<table>
986 properties. Calls C<preprocess_path> before parsing path and setting properties.
987
988 =cut
989
990 sub parse_path {
991     my ($self) = @_;
992
993     # Previous versions unconditionally set table, action and args to whatever 
994     # was in @pi (or else to defaults, if @pi is empty).
995     # Adding preprocess_path(), and then setting table, action and args 
996     # conditionally, broke lots of tests, hence this:
997     $self->$_(undef) for qw/action table args/;
998     $self->preprocess_path;
999
1000     # use frontpage template for frontpage
1001     unless ($self->path && $self->path ne '/') {
1002       $self->path('frontpage');
1003     }
1004
1005     my @pi = grep {length} split '/', $self->path;
1006
1007     $self->table  || $self->table(shift @pi);
1008     $self->action || $self->action( shift @pi or 'index' );
1009     $self->args   || $self->args(\@pi);
1010 }
1011
1012 =item preprocess_path
1013
1014 Sometimes when you don't want to rewrite or over-ride parse_path but
1015 want to rewrite urls or extract data from them before it is parsed,
1016 the preprocess_path/location methods allow you to munge paths and urls
1017 before maypole maps them to actions, classes, etc.
1018
1019 This method is called after parse_location has populated the request
1020 information and before parse_path has populated the model and action
1021 information, and is passed the request object.
1022
1023 You can set action, args or table in this method and parse_path will
1024 then leave those values in place or populate them based on the current
1025 value of the path attribute if they are not present.
1026
1027 =cut
1028
1029 sub preprocess_path { };
1030
1031 =item preprocess_location
1032
1033 This method is called at the start of parse_location, after the headers in, and allows you
1034 to rewrite the url used by maypole, or dynamically set configuration
1035 like the base_uri based on the hostname or path.
1036
1037 =cut
1038
1039 sub preprocess_location { };
1040
1041 =item make_path( %args or \%args or @args )
1042
1043 This is the counterpart to C<parse_path>. It generates a path to use
1044 in links, form actions etc. To implement your own path scheme, just override
1045 this method and C<parse_path>.
1046
1047     %args = ( table      => $table,
1048               action     => $action,        
1049               additional => $additional,    # optional - generally an object ID
1050               );
1051               
1052     \%args = as above, but a ref
1053     
1054     @args = ( $table, $action, $additional );   # $additional is optional
1055
1056 C<id> can be used as an alternative key to C<additional>.
1057
1058 C<$additional> can be a string, an arrayref, or a hashref. An arrayref is
1059 expanded into extra path elements, whereas a hashref is translated into a query
1060 string. 
1061
1062 =cut
1063
1064
1065 sub make_path
1066 {
1067     my $r = shift;
1068     
1069     my %args;
1070     
1071     if (@_ == 1 and ref $_[0] and ref $_[0] eq 'HASH')
1072     {
1073         %args = %{$_[0]};
1074     }
1075     elsif ( @_ > 1 and @_ < 4 )
1076     {
1077         $args{table}      = shift;
1078         $args{action}     = shift;
1079         $args{additional} = shift;
1080     }
1081     else
1082     {
1083         %args = @_;
1084     }
1085     
1086     do { die "no $_" unless $args{$_} } for qw( table action );    
1087
1088     my $additional = $args{additional} || $args{id};
1089     
1090     my @add = ();
1091     
1092     if ($additional)
1093     {
1094         # if $additional is a href, make_uri() will transform it into a query
1095         @add = (ref $additional eq 'ARRAY') ? @$additional : ($additional);
1096     }    
1097     
1098     my $uri = $r->make_uri($args{table}, $args{action}, @add);
1099     
1100     return $uri->as_string;
1101 }
1102
1103
1104
1105 =item make_uri( @segments )
1106
1107 Make a L<URI> object given table, action etc. Automatically adds
1108 the C<uri_base>. 
1109
1110 If the final element in C<@segments> is a hash ref, C<make_uri> will render it
1111 as a query string.
1112
1113 =cut
1114
1115 sub make_uri
1116 {
1117     my ($r, @segments) = @_;
1118
1119     my $query = (ref $segments[-1] eq 'HASH') ? pop(@segments) : undef;
1120     
1121     my $base = $r->config->uri_base; 
1122     $base =~ s|/$||;
1123     
1124     my $uri = URI->new($base);
1125     $uri->path_segments($uri->path_segments, grep {length} @segments);
1126     
1127     my $abs_uri = $uri->abs('/');
1128     $abs_uri->query_form($query) if $query;
1129     return $abs_uri;
1130 }
1131
1132 =item parse_args
1133
1134 Turns post data and query string paramaters into a hash of C<params>.
1135
1136 You should only need to define this method if you are writing a new Maypole
1137 backend.
1138
1139 =cut 
1140
1141 sub parse_args
1142 {
1143     die "parse_args() is a virtual method. Do not use Maypole directly; ".
1144             "use Apache::MVC or similar";
1145 }
1146
1147 =item get_template_root
1148
1149 Implementation-specific path to template root.
1150
1151 You should only need to define this method if you are writing a new Maypole
1152 backend. Otherwise, see L<Maypole::Config/"template_root">
1153
1154 =cut
1155
1156 =back
1157
1158 =head2 Request properties
1159
1160 =over 4
1161
1162 =item model_class
1163
1164 Returns the perl package name that will serve as the model for the
1165 request. It corresponds to the request C<table> attribute.
1166
1167
1168 =item objects
1169
1170 Get/set a list of model objects. The objects will be accessible in the view
1171 templates.
1172
1173 If the first item in C<$self-E<gt>args> can be C<retrieve()>d by the model
1174 class, it will be removed from C<args> and the retrieved object will be added to
1175 the C<objects> list. See L<Maypole::Model> for more information.
1176
1177
1178 =item object
1179
1180 Alias to get/set the first/only model object. The object will be accessible
1181 in the view templates.
1182
1183 When used to set the object, will overwrite the request objects
1184 with a single object.
1185
1186 =cut
1187
1188 sub object {
1189   my ($r,$object) = @_;
1190   $r->objects([$object]) if ($object);
1191   return undef unless $r->objects();
1192   return $r->objects->[0];
1193 }
1194
1195 =item template_args
1196
1197     $self->template_args->{foo} = 'bar';
1198
1199 Get/set a hash of template variables.
1200
1201 Maypole reserved words for template variables will over-ride values in template_variables.
1202
1203 Reserved words are : r, request, object, objects, base, config and errors, as well as the
1204 current class or object name.
1205
1206 =item stash
1207
1208 A place to put custom application data. Not used by Maypole itself.
1209
1210 =item template
1211
1212 Get/set the template to be used by the view. By default, it returns
1213 C<$self-E<gt>action>
1214
1215
1216 =item error
1217
1218 Get/set a request error
1219
1220 =item output
1221
1222 Get/set the response output. This is usually populated by the view class. You
1223 can skip view processing by setting the C<output>.
1224
1225 =item table
1226
1227 The table part of the Maypole request path
1228
1229 =item action
1230
1231 The action part of the Maypole request path
1232
1233 =item args
1234
1235 A list of remaining parts of the request path after table and action
1236 have been
1237 removed
1238
1239 =item headers_in
1240
1241 A L<Maypole::Headers> object containing HTTP headers for the request
1242
1243 =item headers_out
1244
1245 A L<HTTP::Headers> object that contains HTTP headers for the output
1246
1247 =item document_encoding
1248
1249 Get/set the output encoding. Default: utf-8.
1250
1251 =item content_type
1252
1253 Get/set the output content type. Default: text/html
1254
1255 =item get_protocol
1256
1257 Returns the protocol the request was made with, i.e. https
1258
1259 =cut
1260
1261 sub get_protocol {
1262   die "get_protocol is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1263 }
1264
1265 =back
1266
1267 =head2 Request parameters
1268
1269 The source of the parameters may vary depending on the Maypole backend, but they
1270 are usually populated from request query string and POST data.
1271
1272 Maypole supplies several approaches for accessing the request parameters. Note
1273 that the current implementation (via a hashref) of C<query> and C<params> is
1274 likely to change in a future version of Maypole. So avoid direct access to these
1275 hashrefs:
1276
1277     $r->{params}->{foo}      # bad
1278     $r->params->{foo}        # better
1279
1280     $r->{query}->{foo}       # bad
1281     $r->query->{foo}         # better
1282
1283     $r->param('foo')         # best
1284
1285 =over 4
1286
1287 =item param
1288
1289 An accessor (get or set) for request parameters. It behaves similarly to
1290 CGI::param() for accessing CGI parameters, i.e.
1291
1292     $r->param                   # returns list of keys
1293     $r->param($key)             # returns value for $key
1294     $r->param($key => $value)   # returns old value, sets to new value
1295
1296 =cut
1297
1298 sub param 
1299
1300     my ($self, $key) = (shift, shift);
1301     
1302     return keys %{$self->params} unless defined $key;
1303     
1304     return unless exists $self->params->{$key};
1305     
1306     my $val = $self->params->{$key};
1307     
1308     if (@_)
1309     {
1310         my $new_val = shift;
1311         $self->params->{$key} = $new_val;
1312     }
1313     
1314     return (ref $val eq 'ARRAY') ? @$val : ($val) if wantarray;
1315         
1316     return (ref $val eq 'ARRAY') ? $val->[0] : $val;
1317 }
1318
1319
1320 =item params
1321
1322 Returns a hashref of request parameters. 
1323
1324 B<Note:> Where muliple values of a parameter were supplied, the C<params> value
1325 will be an array reference.
1326
1327 =item query
1328
1329 Alias for C<params>.
1330
1331 =back
1332
1333 =head3 Utility methods
1334
1335 =over 4
1336
1337 =item redirect_request
1338
1339 Sets output headers to redirect based on the arguments provided
1340
1341 Accepts either a single argument of the full url to redirect to, or a hash of
1342 named parameters :
1343
1344 $r->redirect_request('http://www.example.com/path');
1345
1346 or
1347
1348 $r->redirect_request(protocol=>'https', domain=>'www.example.com', path=>'/path/file?arguments', status=>'302', url=>'..');
1349
1350 The named parameters are protocol, domain, path, status and url
1351
1352 Only 1 named parameter is required but other than url, they can be combined as
1353 required and current values (from the request) will be used in place of any
1354 missing arguments. The url argument must be a full url including protocol and
1355 can only be combined with status.
1356
1357 =cut
1358
1359 sub redirect_request {
1360   die "redirect_request is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1361 }
1362
1363 # =item redirect_internal_request
1364 #
1365 # =cut
1366 #
1367 # sub redirect_internal_request {
1368 #
1369 # }
1370
1371
1372 =item make_random_id
1373
1374 returns a unique id for this request can be used to prevent or detect repeat
1375 submissions.
1376
1377 =cut
1378
1379 # Session and Repeat Submission Handling
1380 sub make_random_id {
1381     use Maypole::Session;
1382     return Maypole::Session::generate_unique_id();
1383 }
1384
1385 =back
1386
1387 =head1 SEQUENCE DIAGRAMS
1388
1389 See L<Maypole::Manual::Workflow> for a detailed discussion of the sequence of 
1390 calls during processing of a request. This is a brief summary:
1391
1392     INITIALIZATION
1393                                Model e.g.
1394          BeerDB           Maypole::Model::CDBI
1395            |                        |
1396    setup   |                        |
1397  o-------->||                       |
1398            || setup_model           |     setup_database() creates
1399            ||------+                |      a subclass of the Model
1400            |||<----+                |        for each table
1401            |||                      |                |
1402            |||   setup_database     |                |
1403            |||--------------------->|| 'create'      *
1404            |||                      ||----------> $subclass
1405            |||                      |                  |
1406            ||| load_model_subclass  |                  |
1407  foreach   |||------+  ($subclass)  |                  |
1408  $subclass ||||<----+               |    require       |
1409            ||||--------------------------------------->|
1410            |||                      |                  |
1411            |||   adopt($subclass)   |                  |
1412            |||--------------------->||                 |
1413            |                        |                  |
1414            |                        |                  |
1415            |-----+ init             |                  |
1416            ||<---+                  |                  |
1417            ||                       |     new          |     view_object: e.g.
1418            ||---------------------------------------------> Maypole::View::TT
1419            |                        |                  |          |
1420            |                        |                  |          |
1421            |                        |                  |          |
1422            |                        |                  |          |
1423            |                        |                  |          |
1424            
1425
1426
1427     HANDLING A REQUEST
1428
1429
1430           BeerDB                                Model  $subclass  view_object
1431             |                                      |       |         |
1432     handler |                                      |       |         |
1433   o-------->| new                                  |       |         |
1434             |-----> r:BeerDB                       |       |         |
1435             |         |                            |       |         |
1436             |         |                            |       |         |
1437             |         ||                           |       |         |
1438             |         ||-----+ parse_location      |       |         |
1439             |         |||<---+                     |       |         |
1440             |         ||                           |       |         |
1441             |         ||-----+ start_request_hook  |       |         |
1442             |         |||<---+                     |       |         |
1443             |         ||                           |       |         |
1444             |         ||-----+ get_session         |       |         |
1445             |         |||<---+                     |       |         |
1446             |         ||                           |       |         |
1447             |         ||-----+ get_user            |       |         |
1448             |         |||<---+                     |       |         |
1449             |         ||                           |       |         |
1450             |         ||-----+ handler_guts        |       |         |
1451             |         |||<---+                     |       |         |
1452             |         |||     class_of($table)     |       |         |
1453             |         |||------------------------->||      |         |
1454             |         |||       $subclass          ||      |         |
1455             |         |||<-------------------------||      |         |
1456             |         |||                          |       |         |
1457             |         |||-----+ is_model_applicable|       |         |
1458             |         ||||<---+                    |       |         |
1459             |         |||                          |       |         |
1460             |         |||-----+ call_authenticate  |       |         |
1461             |         ||||<---+                    |       |         |
1462             |         |||                          |       |         |
1463             |         |||-----+ additional_data    |       |         |
1464             |         ||||<---+                    |       |         |
1465             |         |||             process      |       |         |
1466             |         |||--------------------------------->||  fetch_objects
1467             |         |||                          |       ||-----+  |
1468             |         |||                          |       |||<---+  |
1469             |         |||                          |       ||        |
1470             |         |||                          |       ||   $action
1471             |         |||                          |       ||-----+  |
1472             |         |||                          |       |||<---+  |            
1473             |         |||         process          |       |         |
1474             |         |||------------------------------------------->|| template
1475             |         |||                          |       |         ||-----+
1476             |         |||                          |       |         |||<---+
1477             |         |||                          |       |         |
1478             |         ||     send_output           |       |         |
1479             |         ||-----+                     |       |         |
1480             |         |||<---+                     |       |         |
1481    $status  |         ||                           |       |         |
1482    <------------------||                           |       |         |
1483             |         |                            |       |         |
1484             |         X                            |       |         |           
1485             |                                      |       |         |
1486             |                                      |       |         |
1487             |                                      |       |         |
1488            
1489            
1490
1491 =head1 SEE ALSO
1492
1493 There's more documentation, examples, and information on our mailing lists
1494 at the Maypole web site:
1495
1496 L<http://maypole.perl.org/>
1497
1498 L<Maypole::Application>, L<Apache::MVC>, L<CGI::Maypole>.
1499
1500 =head1 AUTHOR
1501
1502 Maypole is currently maintained by Aaron Trevena.
1503
1504 =head1 AUTHOR EMERITUS
1505
1506 Simon Cozens, C<simon#cpan.org>
1507
1508 Simon Flack maintained Maypole from 2.05 to 2.09
1509
1510 Sebastian Riedel, C<sri#oook.de> maintained Maypole from 1.99_01 to 2.04
1511
1512 =head1 THANKS TO
1513
1514 Sebastian Riedel, Danijel Milicevic, Dave Slack, Jesse Sheidlower, Jody Belka,
1515 Marcus Ramberg, Mickael Joanne, Randal Schwartz, Simon Flack, Steve Simms,
1516 Veljko Vidovic and all the others who've helped.
1517
1518 =head1 LICENSE
1519
1520 You may distribute this code under the same terms as Perl itself.
1521
1522 =cut
1523
1524 1;
1525
1526 __END__
1527
1528  =item register_cleanup($coderef)
1529
1530 Analogous to L<Apache>'s C<register_cleanup>. If an Apache request object is
1531 available, this call simply redispatches there. If not, the cleanup is
1532 registered in the Maypole request, and executed when the request is
1533 C<DESTROY>ed.
1534
1535 This method is only useful in persistent environments, where you need to ensure
1536 that some code runs when the request finishes, no matter how it finishes (e.g.
1537 after an unexpected error). 
1538
1539  =cut
1540
1541 {
1542     my @_cleanups;
1543
1544     sub register_cleanup
1545     {
1546         my ($self, $cleanup) = @_;
1547         
1548         die "register_cleanup() is an instance method, not a class method" 
1549             unless ref $self;
1550         die "Cleanup must be a coderef" unless ref($cleanup) eq 'CODE';
1551         
1552         if ($self->can('ar') && $self->ar)
1553         {
1554             $self->ar->register_cleanup($cleanup);
1555         }
1556         else
1557         {
1558             push @_cleanups, $cleanup;
1559         }
1560     }
1561
1562     sub DESTROY
1563     {
1564         my ($self) = @_;
1565         
1566         while (my $cleanup = shift @_cleanups)
1567         {
1568             eval { $cleanup->() };
1569             if ($@)
1570             {
1571                 warn "Error during request cleanup: $@";
1572             }
1573         }        
1574     }    
1575 }
1576