]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole.pm
made setting user() and session() backward compatible
[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.12_pre1';
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() );
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   if ($applicable) {
577     eval { $self->model_class->process($self) };
578     if ( my $error = $@ ) {
579       $status = $self->call_exception($error, "model");
580       if ( $status != OK ) {
581         $self->warn("caught model error: $error");
582         return $self->debug ? 
583           $self->view_object->error($self, $error) : ERROR;
584       }
585     }
586   } else {
587     $self->__setup_plain_template;
588   }
589
590   # less frequent path - perhaps output has been set to an error message
591   if ($self->output) {
592     $self->{content_type}      ||= $self->__get_mime_type();
593     $self->{document_encoding} ||= "utf-8";
594     return OK;
595   }
596
597   # normal path - no output has been generated yet
598   my $processed_view_ok = $self->__call_process_view;
599
600   $self->{content_type}      ||= $self->__get_mime_type();
601   $self->{document_encoding} ||= "utf-8";
602
603   return $processed_view_ok;
604 }
605
606 my %filetypes = (
607                  'js' => 'text/javascript',
608                  'css' => 'text/css',
609                  'htm' => 'text/html',
610                  'html' => 'text/html',
611                 );
612
613 sub __get_mime_type {
614   my $self = shift;
615   my $type = 'text/html';
616   if ($self->path =~ m/.*\.(\w{3,4})$/) {
617     $type = $filetypes{$1};
618   } else {
619     my $output = $self->output;
620     if (defined $output) {
621       $type = $mmagic->checktype_contents($output);
622     }
623   }
624   return $type;
625 }
626
627 sub __load_request_model
628 {
629     my ($self) = @_;
630         # We may get a made up class from class_of
631     my $mclass = $self->config->model->class_of($self, $self->table);
632     if ( eval {$mclass->isa('Maypole::Model::Base')} ) {
633         $self->model_class( $mclass );
634     }
635     elsif ($self->debug > 1) {
636       $self->warn("***Warning:  No $mclass class appropriate for model. @_");
637     }
638 }
639
640
641 # is_applicable() returned false, so set up a plain template. Model processing 
642 # will be skipped, but need to remove the model anyway so the template can't 
643 # access it. 
644 sub __setup_plain_template
645 {
646     my ($self) = @_;
647
648     # It's just a plain template
649     $self->build_form_elements(0);
650     $self->model_class(undef);
651
652     unless ($self->template) {
653       # FIXME: this is likely to be redundant and is definately causing problems.
654       my $path = $self->path;
655       $path =~ s{/$}{};    # De-absolutify
656       $self->path($path);
657       $self->template($self->path);
658     }
659 }
660
661 # The model has been processed or skipped (if is_applicable returned false), 
662 # any exceptions have been handled, and there's no content in $self->output
663 sub __call_process_view {
664   my ($self) = @_;
665
666   my $status = eval { $self->view_object->process($self) };
667
668   my $error = $@ || $self->{error};
669
670   if ( $error ) {
671     $status = $self->call_exception($error, "view");
672
673     if ( $status != OK ) {
674       warn "caught view error: $error" if $self->debug;
675       return $self->debug ? 
676         $self->view_object->error($self, $error) : ERROR;
677     }
678   }
679
680   return $status;
681 }
682
683 =item warn
684
685 $r->warn('its all gone pete tong');
686
687 Warn must be implemented by the backend, i.e. Apache::MVC
688 and warn to stderr or appropriate logfile.
689
690 You can also over-ride this in your Maypole driver, should you
691 want to use something like Log::Log4perl instead.
692
693 =cut
694
695 sub warn { }
696
697 =item build_form_elements
698
699 $r->build_form_elements(0);
700
701 Specify (in an action) whether to build HTML form elements and populate
702 the cgi element of classmetadata in the view.
703
704 You can set this globally using the accessor of the same name in Maypole::Config,
705 this method allows you to over-ride that setting per action.
706
707 =cut
708
709 =item get_request
710
711 You should only need to define this method if you are writing a new
712 Maypole backend. It should return something that looks like an Apache
713 or CGI request object, it defaults to blank.
714
715 =cut
716
717 sub get_request { }
718
719 =item parse_location
720
721 Turns the backend request (e.g. Apache::MVC, Maypole, CGI) into a Maypole
722 request. It does this by setting the C<path>, and invoking C<parse_path> and
723 C<parse_args>.
724
725 You should only need to define this method if you are writing a new Maypole
726 backend.
727
728 =cut
729
730 sub parse_location 
731 {
732     die "parse_location is a virtual method. Do not use Maypole directly; " . 
733                 "use Apache::MVC or similar";
734 }
735
736 =item start_request_hook
737
738 This is called immediately after setting up the basic request. The default
739 method does nothing. 
740
741 The value of C<< $r->status >> is set to C<OK> before this hook is run. Your 
742 implementation can change the status code, or leave it alone. 
743
744 After this hook has run, Maypole will check the value of C<status>. For any
745 value other than C<OK>, Maypole returns the C<status> immediately. 
746
747 This is useful for filtering out requests for static files, e.g. images, which
748 should not be processed by Maypole or by the templating engine:
749
750     sub start_request_hook
751     {
752         my ($r) = @_;
753         
754         $r->status(DECLINED) if $r->path =~ /\.jpg$/;
755     }
756     
757 Multiple plugins, and the driver, can define this hook - Maypole will call all
758 of them. You should check for and probably not change any non-OK C<status>
759 value:
760
761     package Maypole::Plugin::MyApp::SkipFavicon;
762     
763     sub start_request_hook
764     {
765         my ($r) = @_;
766         
767         # check if a previous plugin has already DECLINED this request
768         # - probably unnecessary in this example, but you get the idea
769         return unless $r->status == OK;
770         
771         # then do our stuff
772         $r->status(DECLINED) if $r->path =~ /favicon\.ico/;
773     }        
774      
775 =cut
776
777 sub start_request_hook { }
778
779 =item is_applicable
780
781 B<This method is deprecated> as of version 2.11. If you have overridden it,
782 please override C<is_model_applicable> instead, and change the return type
783 from a Maypole:Constant to a true/false value.
784
785 Returns a Maypole::Constant to indicate whether the request is valid.
786
787 =cut
788
789 sub is_applicable { return shift->is_model_applicable(@_); }
790
791 =item is_model_applicable
792
793 Returns true or false to indicate whether the request is valid.
794
795 The default implementation checks that C<< $r->table >> is publicly
796 accessible and that the model class is configured to handle the
797 C<< $r->action >>.
798
799 =cut
800
801 sub is_model_applicable {
802     my ($self) = @_;
803
804     # Establish which tables should be processed by the model
805     my $config = $self->config;
806     
807     $config->ok_tables || $config->ok_tables( $config->display_tables );
808     
809     $config->ok_tables( { map { $_ => 1 } @{ $config->ok_tables } } )
810         if ref $config->ok_tables eq "ARRAY";
811         
812     my $ok_tables = $config->ok_tables;
813       
814     # Does this request concern a table to be processed by the model?
815     my $table = $self->table;
816     
817     my $ok = 0;
818     
819     if (exists $ok_tables->{$table}) 
820     {
821         $ok = 1;
822     } 
823
824     if (not $ok) 
825     {
826         $self->warn ("We don't have that table ($table).\n"
827             . "Available tables are: "
828             . join( ",", keys %$ok_tables ))
829                 if $self->debug and not $ok_tables->{$table};
830                 
831         return DECLINED;
832     }
833     
834     # Is the action public?
835     my $action = $self->action;
836     return OK if $self->model_class->is_public($action);
837     
838     $self->warn("The action '$action' is not applicable to the table '$table'")
839          if $self->debug;
840     
841     return DECLINED;
842 }
843
844 =item get_session
845
846 Called immediately after C<start_request_hook()>.
847
848 This method should return a session, which will be stored in the request's
849 C<session> attribute.
850
851 The default method is empty. 
852
853 =cut
854
855 sub get_session { }
856
857 =item get_user
858
859 Called immediately after C<get_session>.
860
861 This method should return a user, which will be stored in the request's C<user>
862 attribute.
863
864 The default method is empty.
865
866 =cut
867
868 sub get_user {}
869
870 =item call_authenticate
871
872 This method first checks if the relevant model class
873 can authenticate the user, or falls back to the default
874 authenticate method of your Maypole application.
875
876 =cut
877
878 sub call_authenticate 
879 {
880     my ($self) = @_;
881
882     # Check if we have a model class with an authenticate() to delegate to
883     return $self->model_class->authenticate($self) 
884         if $self->model_class and $self->model_class->can('authenticate');
885     
886     # Interface consistency is a Good Thing - 
887     # the invocant and the argument may one day be different things 
888     # (i.e. controller and request), like they are when authenticate() 
889     # is called on a model class (i.e. model and request)
890     return $self->authenticate($self);   
891 }
892
893 =item authenticate
894
895 Returns a Maypole::Constant to indicate whether the user is authenticated for
896 the Maypole request.
897
898 The default implementation returns C<OK>
899
900 =cut
901
902 sub authenticate { return OK }
903
904
905 =item call_exception
906
907 This model is called to catch exceptions, first after authenticate, then after
908 processing the model class, and finally to check for exceptions from the view
909 class.
910
911 This method first checks if the relevant model class
912 can handle exceptions the user, or falls back to the default
913 exception method of your Maypole application.
914
915 =cut
916
917 sub call_exception 
918 {
919     my ($self, $error, $when) = @_;
920
921     # Check if we have a model class with an exception() to delegate to
922     if ( $self->model_class && $self->model_class->can('exception') )
923     {
924         my $status = $self->model_class->exception( $self, $error, $when );
925         return $status if $status == OK;
926     }
927     
928     return $self->exception($error, $when);
929 }
930
931
932 =item exception
933
934 This method is called if any exceptions are raised during the authentication or
935 model/view processing. It should accept the exception as a parameter and return
936 a Maypole::Constant to indicate whether the request should continue to be
937 processed.
938
939 =cut
940
941 sub exception { 
942     my ($self, $error, $when) = @_;
943     if (ref $self->view_object && $self->view_object->can("report_error") and $self->debug) {
944         $self->view_object->report_error($self, $error, $when);
945         return OK;
946     }
947     return ERROR;
948 }
949
950 =item additional_data
951
952 Called before the model processes the request, this method gives you a chance to
953 do some processing for each request, for example, manipulating C<template_args>.
954
955 =cut
956
957 sub additional_data { }
958
959 =item send_output
960
961 Sends the output and additional headers to the user.
962
963 =cut
964
965 sub send_output {
966     die "send_output is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
967 }
968
969
970 =back
971
972 =head2 Path processing and manipulation
973
974 =over 4
975
976 =item path
977
978 Returns the request path
979
980 =item parse_path
981
982 Parses the request path and sets the C<args>, C<action> and C<table>
983 properties. Calls C<preprocess_path> before parsing path and setting properties.
984
985 =cut
986
987 sub parse_path 
988 {
989     my ($self) = @_;
990
991     # Previous versions unconditionally set table, action and args to whatever 
992     # was in @pi (or else to defaults, if @pi is empty).
993     # Adding preprocess_path(), and then setting table, action and args 
994     # conditionally, broke lots of tests, hence this:
995     $self->$_(undef) for qw/action table args/;
996     $self->preprocess_path;
997
998     # use frontpage template for frontpage
999     unless ($self->path && $self->path ne '/') {
1000       $self->path('frontpage');
1001     }
1002
1003     my @pi = grep {length} split '/', $self->path;
1004
1005     $self->table  || $self->table(shift @pi);
1006     $self->action || $self->action( shift @pi or 'index' );
1007     $self->args   || $self->args(\@pi);
1008 }
1009
1010 =item preprocess_path
1011
1012 Sometimes when you don't want to rewrite or over-ride parse_path but
1013 want to rewrite urls or extract data from them before it is parsed.
1014
1015 This method is called after parse_location has populated the request
1016 information and before parse_path has populated the model and action
1017 information, and is passed the request object.
1018
1019 You can set action, args or table in this method and parse_path will
1020 then leave those values in place or populate them if not present
1021
1022 =cut
1023
1024 sub preprocess_path { };
1025
1026 =item make_path( %args or \%args or @args )
1027
1028 This is the counterpart to C<parse_path>. It generates a path to use
1029 in links, form actions etc. To implement your own path scheme, just override
1030 this method and C<parse_path>.
1031
1032     %args = ( table      => $table,
1033               action     => $action,        
1034               additional => $additional,    # optional - generally an object ID
1035               );
1036               
1037     \%args = as above, but a ref
1038     
1039     @args = ( $table, $action, $additional );   # $additional is optional
1040
1041 C<id> can be used as an alternative key to C<additional>.
1042
1043 C<$additional> can be a string, an arrayref, or a hashref. An arrayref is
1044 expanded into extra path elements, whereas a hashref is translated into a query
1045 string. 
1046
1047 =cut
1048
1049 sub make_path
1050 {
1051     my $r = shift;
1052     
1053     my %args;
1054     
1055     if (@_ == 1 and ref $_[0] and ref $_[0] eq 'HASH')
1056     {
1057         %args = %{$_[0]};
1058     }
1059     elsif ( @_ > 1 and @_ < 4 )
1060     {
1061         $args{table}      = shift;
1062         $args{action}     = shift;
1063         $args{additional} = shift;
1064     }
1065     else
1066     {
1067         %args = @_;
1068     }
1069     
1070     do { die "no $_" unless $args{$_} } for qw( table action );    
1071
1072     my $additional = $args{additional} || $args{id};
1073     
1074     my @add = ();
1075     
1076     if ($additional)
1077     {
1078         # if $additional is a href, make_uri() will transform it into a query
1079         @add = (ref $additional eq 'ARRAY') ? @$additional : ($additional);
1080     }    
1081     
1082     my $uri = $r->make_uri($args{table}, $args{action}, @add);
1083     
1084     return $uri->as_string;
1085 }
1086
1087
1088
1089 =item make_uri( @segments )
1090
1091 Make a L<URI> object given table, action etc. Automatically adds
1092 the C<uri_base>. 
1093
1094 If the final element in C<@segments> is a hash ref, C<make_uri> will render it
1095 as a query string.
1096
1097 =cut
1098
1099 sub make_uri
1100 {
1101     my ($r, @segments) = @_;
1102
1103     my $query = (ref $segments[-1] eq 'HASH') ? pop(@segments) : undef;
1104     
1105     my $base = $r->config->uri_base; 
1106     $base =~ s|/$||;
1107     
1108     my $uri = URI->new($base);
1109     $uri->path_segments($uri->path_segments, grep {length} @segments);
1110     
1111     my $abs_uri = $uri->abs('/');
1112     $abs_uri->query_form($query) if $query;
1113     return $abs_uri;
1114 }
1115
1116 =item parse_args
1117
1118 Turns post data and query string paramaters into a hash of C<params>.
1119
1120 You should only need to define this method if you are writing a new Maypole
1121 backend.
1122
1123 =cut 
1124
1125 sub parse_args
1126 {
1127     die "parse_args() is a virtual method. Do not use Maypole directly; ".
1128             "use Apache::MVC or similar";
1129 }
1130
1131 =item get_template_root
1132
1133 Implementation-specific path to template root.
1134
1135 You should only need to define this method if you are writing a new Maypole
1136 backend. Otherwise, see L<Maypole::Config/"template_root">
1137
1138 =cut
1139
1140 =back
1141
1142 =head2 Request properties
1143
1144 =over 4
1145
1146 =item model_class
1147
1148 Returns the perl package name that will serve as the model for the
1149 request. It corresponds to the request C<table> attribute.
1150
1151
1152 =item objects
1153
1154 Get/set a list of model objects. The objects will be accessible in the view
1155 templates.
1156
1157 If the first item in C<$self-E<gt>args> can be C<retrieve()>d by the model
1158 class, it will be removed from C<args> and the retrieved object will be added to
1159 the C<objects> list. See L<Maypole::Model> for more information.
1160
1161
1162 =item object
1163
1164 Alias to get/set the first/only model object. The object will be accessible
1165 in the view templates.
1166
1167 When used to set the object, will overwrite the request objects
1168 with a single object.
1169
1170 =cut
1171
1172 sub object {
1173   my ($r,$object) = @_;
1174   $r->objects([$object]) if ($object);
1175   return undef unless $r->objects();
1176   return $r->objects->[0];
1177 }
1178
1179 =item template_args
1180
1181     $self->template_args->{foo} = 'bar';
1182
1183 Get/set a hash of template variables.
1184
1185 Maypole reserved words for template variables will over-ride values in template_variables.
1186
1187 Reserved words are : r, request, object, objects, base, config and errors, as well as the
1188 current class or object name.
1189
1190 =item stash
1191
1192 A place to put custom application data. Not used by Maypole itself.
1193
1194 =item template
1195
1196 Get/set the template to be used by the view. By default, it returns
1197 C<$self-E<gt>action>
1198
1199
1200 =item error
1201
1202 Get/set a request error
1203
1204 =item output
1205
1206 Get/set the response output. This is usually populated by the view class. You
1207 can skip view processing by setting the C<output>.
1208
1209 =item table
1210
1211 The table part of the Maypole request path
1212
1213 =item action
1214
1215 The action part of the Maypole request path
1216
1217 =item args
1218
1219 A list of remaining parts of the request path after table and action
1220 have been
1221 removed
1222
1223 =item headers_in
1224
1225 A L<Maypole::Headers> object containing HTTP headers for the request
1226
1227 =item headers_out
1228
1229 A L<HTTP::Headers> object that contains HTTP headers for the output
1230
1231 =item document_encoding
1232
1233 Get/set the output encoding. Default: utf-8.
1234
1235 =item content_type
1236
1237 Get/set the output content type. Default: text/html
1238
1239 =item get_protocol
1240
1241 Returns the protocol the request was made with, i.e. https
1242
1243 =cut
1244
1245 sub get_protocol {
1246   die "get_protocol is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1247 }
1248
1249 =back
1250
1251 =head2 Request parameters
1252
1253 The source of the parameters may vary depending on the Maypole backend, but they
1254 are usually populated from request query string and POST data.
1255
1256 Maypole supplies several approaches for accessing the request parameters. Note
1257 that the current implementation (via a hashref) of C<query> and C<params> is
1258 likely to change in a future version of Maypole. So avoid direct access to these
1259 hashrefs:
1260
1261     $r->{params}->{foo}      # bad
1262     $r->params->{foo}        # better
1263
1264     $r->{query}->{foo}       # bad
1265     $r->query->{foo}         # better
1266
1267     $r->param('foo')         # best
1268
1269 =over 4
1270
1271 =item param
1272
1273 An accessor (get or set) for request parameters. It behaves similarly to
1274 CGI::param() for accessing CGI parameters, i.e.
1275
1276     $r->param                   # returns list of keys
1277     $r->param($key)             # returns value for $key
1278     $r->param($key => $value)   # returns old value, sets to new value
1279
1280 =cut
1281
1282 sub param 
1283
1284     my ($self, $key) = (shift, shift);
1285     
1286     return keys %{$self->params} unless defined $key;
1287     
1288     return unless exists $self->params->{$key};
1289     
1290     my $val = $self->params->{$key};
1291     
1292     if (@_)
1293     {
1294         my $new_val = shift;
1295         $self->params->{$key} = $new_val;
1296     }
1297     
1298     return (ref $val eq 'ARRAY') ? @$val : ($val) if wantarray;
1299         
1300     return (ref $val eq 'ARRAY') ? $val->[0] : $val;
1301 }
1302
1303
1304 =item params
1305
1306 Returns a hashref of request parameters. 
1307
1308 B<Note:> Where muliple values of a parameter were supplied, the C<params> value
1309 will be an array reference.
1310
1311 =item query
1312
1313 Alias for C<params>.
1314
1315 =back
1316
1317 =head3 Utility methods
1318
1319 =over 4
1320
1321 =item redirect_request
1322
1323 Sets output headers to redirect based on the arguments provided
1324
1325 Accepts either a single argument of the full url to redirect to, or a hash of
1326 named parameters :
1327
1328 $r->redirect_request('http://www.example.com/path');
1329
1330 or
1331
1332 $r->redirect_request(protocol=>'https', domain=>'www.example.com', path=>'/path/file?arguments', status=>'302', url=>'..');
1333
1334 The named parameters are protocol, domain, path, status and url
1335
1336 Only 1 named parameter is required but other than url, they can be combined as
1337 required and current values (from the request) will be used in place of any
1338 missing arguments. The url argument must be a full url including protocol and
1339 can only be combined with status.
1340
1341 =cut
1342
1343 sub redirect_request {
1344   die "redirect_request is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1345 }
1346
1347 # =item redirect_internal_request
1348 #
1349 # =cut
1350 #
1351 # sub redirect_internal_request {
1352 #
1353 # }
1354
1355
1356 =item make_random_id
1357
1358 returns a unique id for this request can be used to prevent or detect repeat
1359 submissions.
1360
1361 =cut
1362
1363 # Session and Repeat Submission Handling
1364 sub make_random_id {
1365     use Maypole::Session;
1366     return Maypole::Session::generate_unique_id();
1367 }
1368
1369 =back
1370
1371 =head1 SEQUENCE DIAGRAMS
1372
1373 See L<Maypole::Manual::Workflow> for a detailed discussion of the sequence of 
1374 calls during processing of a request. This is a brief summary:
1375
1376     INITIALIZATION
1377                                Model e.g.
1378          BeerDB           Maypole::Model::CDBI
1379            |                        |
1380    setup   |                        |
1381  o-------->||                       |
1382            || setup_model           |     setup_database() creates
1383            ||------+                |      a subclass of the Model
1384            |||<----+                |        for each table
1385            |||                      |                |
1386            |||   setup_database     |                |
1387            |||--------------------->|| 'create'      *
1388            |||                      ||----------> $subclass
1389            |||                      |                  |
1390            ||| load_model_subclass  |                  |
1391  foreach   |||------+  ($subclass)  |                  |
1392  $subclass ||||<----+               |    require       |
1393            ||||--------------------------------------->|
1394            |||                      |                  |
1395            |||   adopt($subclass)   |                  |
1396            |||--------------------->||                 |
1397            |                        |                  |
1398            |                        |                  |
1399            |-----+ init             |                  |
1400            ||<---+                  |                  |
1401            ||                       |     new          |     view_object: e.g.
1402            ||---------------------------------------------> Maypole::View::TT
1403            |                        |                  |          |
1404            |                        |                  |          |
1405            |                        |                  |          |
1406            |                        |                  |          |
1407            |                        |                  |          |
1408            
1409
1410
1411     HANDLING A REQUEST
1412
1413
1414           BeerDB                                Model  $subclass  view_object
1415             |                                      |       |         |
1416     handler |                                      |       |         |
1417   o-------->| new                                  |       |         |
1418             |-----> r:BeerDB                       |       |         |
1419             |         |                            |       |         |
1420             |         |                            |       |         |
1421             |         ||                           |       |         |
1422             |         ||-----+ parse_location      |       |         |
1423             |         |||<---+                     |       |         |
1424             |         ||                           |       |         |
1425             |         ||-----+ start_request_hook  |       |         |
1426             |         |||<---+                     |       |         |
1427             |         ||                           |       |         |
1428             |         ||-----+ get_session         |       |         |
1429             |         |||<---+                     |       |         |
1430             |         ||                           |       |         |
1431             |         ||-----+ get_user            |       |         |
1432             |         |||<---+                     |       |         |
1433             |         ||                           |       |         |
1434             |         ||-----+ handler_guts        |       |         |
1435             |         |||<---+                     |       |         |
1436             |         |||     class_of($table)     |       |         |
1437             |         |||------------------------->||      |         |
1438             |         |||       $subclass          ||      |         |
1439             |         |||<-------------------------||      |         |
1440             |         |||                          |       |         |
1441             |         |||-----+ is_model_applicable|       |         |
1442             |         ||||<---+                    |       |         |
1443             |         |||                          |       |         |
1444             |         |||-----+ call_authenticate  |       |         |
1445             |         ||||<---+                    |       |         |
1446             |         |||                          |       |         |
1447             |         |||-----+ additional_data    |       |         |
1448             |         ||||<---+                    |       |         |
1449             |         |||             process      |       |         |
1450             |         |||--------------------------------->||  fetch_objects
1451             |         |||                          |       ||-----+  |
1452             |         |||                          |       |||<---+  |
1453             |         |||                          |       ||        |
1454             |         |||                          |       ||   $action
1455             |         |||                          |       ||-----+  |
1456             |         |||                          |       |||<---+  |            
1457             |         |||         process          |       |         |
1458             |         |||------------------------------------------->|| template
1459             |         |||                          |       |         ||-----+
1460             |         |||                          |       |         |||<---+
1461             |         |||                          |       |         |
1462             |         ||     send_output           |       |         |
1463             |         ||-----+                     |       |         |
1464             |         |||<---+                     |       |         |
1465    $status  |         ||                           |       |         |
1466    <------------------||                           |       |         |
1467             |         |                            |       |         |
1468             |         X                            |       |         |           
1469             |                                      |       |         |
1470             |                                      |       |         |
1471             |                                      |       |         |
1472            
1473            
1474
1475 =head1 SEE ALSO
1476
1477 There's more documentation, examples, and information on our mailing lists
1478 at the Maypole web site:
1479
1480 L<http://maypole.perl.org/>
1481
1482 L<Maypole::Application>, L<Apache::MVC>, L<CGI::Maypole>.
1483
1484 =head1 AUTHOR
1485
1486 Maypole is currently maintained by Aaron Trevena.
1487
1488 =head1 AUTHOR EMERITUS
1489
1490 Simon Cozens, C<simon#cpan.org>
1491
1492 Simon Flack maintained Maypole from 2.05 to 2.09
1493
1494 Sebastian Riedel, C<sri#oook.de> maintained Maypole from 1.99_01 to 2.04
1495
1496 =head1 THANKS TO
1497
1498 Sebastian Riedel, Danijel Milicevic, Dave Slack, Jesse Sheidlower, Jody Belka,
1499 Marcus Ramberg, Mickael Joanne, Randal Schwartz, Simon Flack, Steve Simms,
1500 Veljko Vidovic and all the others who've helped.
1501
1502 =head1 LICENSE
1503
1504 You may distribute this code under the same terms as Perl itself.
1505
1506 =cut
1507
1508 1;
1509
1510 __END__
1511
1512  =item register_cleanup($coderef)
1513
1514 Analogous to L<Apache>'s C<register_cleanup>. If an Apache request object is
1515 available, this call simply redispatches there. If not, the cleanup is
1516 registered in the Maypole request, and executed when the request is
1517 C<DESTROY>ed.
1518
1519 This method is only useful in persistent environments, where you need to ensure
1520 that some code runs when the request finishes, no matter how it finishes (e.g.
1521 after an unexpected error). 
1522
1523  =cut
1524
1525 {
1526     my @_cleanups;
1527
1528     sub register_cleanup
1529     {
1530         my ($self, $cleanup) = @_;
1531         
1532         die "register_cleanup() is an instance method, not a class method" 
1533             unless ref $self;
1534         die "Cleanup must be a coderef" unless ref($cleanup) eq 'CODE';
1535         
1536         if ($self->can('ar') && $self->ar)
1537         {
1538             $self->ar->register_cleanup($cleanup);
1539         }
1540         else
1541         {
1542             push @_cleanups, $cleanup;
1543         }
1544     }
1545
1546     sub DESTROY
1547     {
1548         my ($self) = @_;
1549         
1550         while (my $cleanup = shift @_cleanups)
1551         {
1552             eval { $cleanup->() };
1553             if ($@)
1554             {
1555                 warn "Error during request cleanup: $@";
1556             }
1557         }        
1558     }    
1559 }
1560