]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole.pm
fix to request options for mp1.x
[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.121';
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     my ($self) = @_;
989
990     # Previous versions unconditionally set table, action and args to whatever 
991     # was in @pi (or else to defaults, if @pi is empty).
992     # Adding preprocess_path(), and then setting table, action and args 
993     # conditionally, broke lots of tests, hence this:
994     $self->$_(undef) for qw/action table args/;
995     $self->preprocess_path;
996
997     # use frontpage template for frontpage
998     unless ($self->path && $self->path ne '/') {
999       $self->path('frontpage');
1000     }
1001
1002     my @pi = grep {length} split '/', $self->path;
1003
1004     $self->table  || $self->table(shift @pi);
1005     $self->action || $self->action( shift @pi or 'index' );
1006     $self->args   || $self->args(\@pi);
1007 }
1008
1009 =item preprocess_path
1010
1011 Sometimes when you don't want to rewrite or over-ride parse_path but
1012 want to rewrite urls or extract data from them before it is parsed,
1013 the preprocess_path/location methods allow you to munge paths and urls
1014 before maypole maps them to actions, classes, etc.
1015
1016 This method is called after parse_location has populated the request
1017 information and before parse_path has populated the model and action
1018 information, and is passed the request object.
1019
1020 You can set action, args or table in this method and parse_path will
1021 then leave those values in place or populate them based on the current
1022 value of the path attribute if they are not present.
1023
1024 =cut
1025
1026 sub preprocess_path { };
1027
1028 =item preprocess_location
1029
1030 This method is called at the start of parse_location, after the headers in, and allows you
1031 to rewrite the url used by maypole, or dynamically set configuration
1032 like the base_uri based on the hostname or path.
1033
1034 =cut
1035
1036 sub preprocess_location { };
1037
1038 =item make_path( %args or \%args or @args )
1039
1040 This is the counterpart to C<parse_path>. It generates a path to use
1041 in links, form actions etc. To implement your own path scheme, just override
1042 this method and C<parse_path>.
1043
1044     %args = ( table      => $table,
1045               action     => $action,        
1046               additional => $additional,    # optional - generally an object ID
1047               );
1048               
1049     \%args = as above, but a ref
1050     
1051     @args = ( $table, $action, $additional );   # $additional is optional
1052
1053 C<id> can be used as an alternative key to C<additional>.
1054
1055 C<$additional> can be a string, an arrayref, or a hashref. An arrayref is
1056 expanded into extra path elements, whereas a hashref is translated into a query
1057 string. 
1058
1059 =cut
1060
1061
1062 sub make_path
1063 {
1064     my $r = shift;
1065     
1066     my %args;
1067     
1068     if (@_ == 1 and ref $_[0] and ref $_[0] eq 'HASH')
1069     {
1070         %args = %{$_[0]};
1071     }
1072     elsif ( @_ > 1 and @_ < 4 )
1073     {
1074         $args{table}      = shift;
1075         $args{action}     = shift;
1076         $args{additional} = shift;
1077     }
1078     else
1079     {
1080         %args = @_;
1081     }
1082     
1083     do { die "no $_" unless $args{$_} } for qw( table action );    
1084
1085     my $additional = $args{additional} || $args{id};
1086     
1087     my @add = ();
1088     
1089     if ($additional)
1090     {
1091         # if $additional is a href, make_uri() will transform it into a query
1092         @add = (ref $additional eq 'ARRAY') ? @$additional : ($additional);
1093     }    
1094     
1095     my $uri = $r->make_uri($args{table}, $args{action}, @add);
1096     
1097     return $uri->as_string;
1098 }
1099
1100
1101
1102 =item make_uri( @segments )
1103
1104 Make a L<URI> object given table, action etc. Automatically adds
1105 the C<uri_base>. 
1106
1107 If the final element in C<@segments> is a hash ref, C<make_uri> will render it
1108 as a query string.
1109
1110 =cut
1111
1112 sub make_uri
1113 {
1114     my ($r, @segments) = @_;
1115
1116     my $query = (ref $segments[-1] eq 'HASH') ? pop(@segments) : undef;
1117     
1118     my $base = $r->config->uri_base; 
1119     $base =~ s|/$||;
1120     
1121     my $uri = URI->new($base);
1122     $uri->path_segments($uri->path_segments, grep {length} @segments);
1123     
1124     my $abs_uri = $uri->abs('/');
1125     $abs_uri->query_form($query) if $query;
1126     return $abs_uri;
1127 }
1128
1129 =item parse_args
1130
1131 Turns post data and query string paramaters into a hash of C<params>.
1132
1133 You should only need to define this method if you are writing a new Maypole
1134 backend.
1135
1136 =cut 
1137
1138 sub parse_args
1139 {
1140     die "parse_args() is a virtual method. Do not use Maypole directly; ".
1141             "use Apache::MVC or similar";
1142 }
1143
1144 =item get_template_root
1145
1146 Implementation-specific path to template root.
1147
1148 You should only need to define this method if you are writing a new Maypole
1149 backend. Otherwise, see L<Maypole::Config/"template_root">
1150
1151 =cut
1152
1153 =back
1154
1155 =head2 Request properties
1156
1157 =over 4
1158
1159 =item model_class
1160
1161 Returns the perl package name that will serve as the model for the
1162 request. It corresponds to the request C<table> attribute.
1163
1164
1165 =item objects
1166
1167 Get/set a list of model objects. The objects will be accessible in the view
1168 templates.
1169
1170 If the first item in C<$self-E<gt>args> can be C<retrieve()>d by the model
1171 class, it will be removed from C<args> and the retrieved object will be added to
1172 the C<objects> list. See L<Maypole::Model> for more information.
1173
1174
1175 =item object
1176
1177 Alias to get/set the first/only model object. The object will be accessible
1178 in the view templates.
1179
1180 When used to set the object, will overwrite the request objects
1181 with a single object.
1182
1183 =cut
1184
1185 sub object {
1186   my ($r,$object) = @_;
1187   $r->objects([$object]) if ($object);
1188   return undef unless $r->objects();
1189   return $r->objects->[0];
1190 }
1191
1192 =item template_args
1193
1194     $self->template_args->{foo} = 'bar';
1195
1196 Get/set a hash of template variables.
1197
1198 Maypole reserved words for template variables will over-ride values in template_variables.
1199
1200 Reserved words are : r, request, object, objects, base, config and errors, as well as the
1201 current class or object name.
1202
1203 =item stash
1204
1205 A place to put custom application data. Not used by Maypole itself.
1206
1207 =item template
1208
1209 Get/set the template to be used by the view. By default, it returns
1210 C<$self-E<gt>action>
1211
1212
1213 =item error
1214
1215 Get/set a request error
1216
1217 =item output
1218
1219 Get/set the response output. This is usually populated by the view class. You
1220 can skip view processing by setting the C<output>.
1221
1222 =item table
1223
1224 The table part of the Maypole request path
1225
1226 =item action
1227
1228 The action part of the Maypole request path
1229
1230 =item args
1231
1232 A list of remaining parts of the request path after table and action
1233 have been
1234 removed
1235
1236 =item headers_in
1237
1238 A L<Maypole::Headers> object containing HTTP headers for the request
1239
1240 =item headers_out
1241
1242 A L<HTTP::Headers> object that contains HTTP headers for the output
1243
1244 =item document_encoding
1245
1246 Get/set the output encoding. Default: utf-8.
1247
1248 =item content_type
1249
1250 Get/set the output content type. Default: text/html
1251
1252 =item get_protocol
1253
1254 Returns the protocol the request was made with, i.e. https
1255
1256 =cut
1257
1258 sub get_protocol {
1259   die "get_protocol is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1260 }
1261
1262 =back
1263
1264 =head2 Request parameters
1265
1266 The source of the parameters may vary depending on the Maypole backend, but they
1267 are usually populated from request query string and POST data.
1268
1269 Maypole supplies several approaches for accessing the request parameters. Note
1270 that the current implementation (via a hashref) of C<query> and C<params> is
1271 likely to change in a future version of Maypole. So avoid direct access to these
1272 hashrefs:
1273
1274     $r->{params}->{foo}      # bad
1275     $r->params->{foo}        # better
1276
1277     $r->{query}->{foo}       # bad
1278     $r->query->{foo}         # better
1279
1280     $r->param('foo')         # best
1281
1282 =over 4
1283
1284 =item param
1285
1286 An accessor (get or set) for request parameters. It behaves similarly to
1287 CGI::param() for accessing CGI parameters, i.e.
1288
1289     $r->param                   # returns list of keys
1290     $r->param($key)             # returns value for $key
1291     $r->param($key => $value)   # returns old value, sets to new value
1292
1293 =cut
1294
1295 sub param 
1296
1297     my ($self, $key) = (shift, shift);
1298     
1299     return keys %{$self->params} unless defined $key;
1300     
1301     return unless exists $self->params->{$key};
1302     
1303     my $val = $self->params->{$key};
1304     
1305     if (@_)
1306     {
1307         my $new_val = shift;
1308         $self->params->{$key} = $new_val;
1309     }
1310     
1311     return (ref $val eq 'ARRAY') ? @$val : ($val) if wantarray;
1312         
1313     return (ref $val eq 'ARRAY') ? $val->[0] : $val;
1314 }
1315
1316
1317 =item params
1318
1319 Returns a hashref of request parameters. 
1320
1321 B<Note:> Where muliple values of a parameter were supplied, the C<params> value
1322 will be an array reference.
1323
1324 =item query
1325
1326 Alias for C<params>.
1327
1328 =back
1329
1330 =head3 Utility methods
1331
1332 =over 4
1333
1334 =item redirect_request
1335
1336 Sets output headers to redirect based on the arguments provided
1337
1338 Accepts either a single argument of the full url to redirect to, or a hash of
1339 named parameters :
1340
1341 $r->redirect_request('http://www.example.com/path');
1342
1343 or
1344
1345 $r->redirect_request(protocol=>'https', domain=>'www.example.com', path=>'/path/file?arguments', status=>'302', url=>'..');
1346
1347 The named parameters are protocol, domain, path, status and url
1348
1349 Only 1 named parameter is required but other than url, they can be combined as
1350 required and current values (from the request) will be used in place of any
1351 missing arguments. The url argument must be a full url including protocol and
1352 can only be combined with status.
1353
1354 =cut
1355
1356 sub redirect_request {
1357   die "redirect_request is a virtual method. Do not use Maypole directly; use Apache::MVC or similar";
1358 }
1359
1360 # =item redirect_internal_request
1361 #
1362 # =cut
1363 #
1364 # sub redirect_internal_request {
1365 #
1366 # }
1367
1368
1369 =item make_random_id
1370
1371 returns a unique id for this request can be used to prevent or detect repeat
1372 submissions.
1373
1374 =cut
1375
1376 # Session and Repeat Submission Handling
1377 sub make_random_id {
1378     use Maypole::Session;
1379     return Maypole::Session::generate_unique_id();
1380 }
1381
1382 =back
1383
1384 =head1 SEQUENCE DIAGRAMS
1385
1386 See L<Maypole::Manual::Workflow> for a detailed discussion of the sequence of 
1387 calls during processing of a request. This is a brief summary:
1388
1389     INITIALIZATION
1390                                Model e.g.
1391          BeerDB           Maypole::Model::CDBI
1392            |                        |
1393    setup   |                        |
1394  o-------->||                       |
1395            || setup_model           |     setup_database() creates
1396            ||------+                |      a subclass of the Model
1397            |||<----+                |        for each table
1398            |||                      |                |
1399            |||   setup_database     |                |
1400            |||--------------------->|| 'create'      *
1401            |||                      ||----------> $subclass
1402            |||                      |                  |
1403            ||| load_model_subclass  |                  |
1404  foreach   |||------+  ($subclass)  |                  |
1405  $subclass ||||<----+               |    require       |
1406            ||||--------------------------------------->|
1407            |||                      |                  |
1408            |||   adopt($subclass)   |                  |
1409            |||--------------------->||                 |
1410            |                        |                  |
1411            |                        |                  |
1412            |-----+ init             |                  |
1413            ||<---+                  |                  |
1414            ||                       |     new          |     view_object: e.g.
1415            ||---------------------------------------------> Maypole::View::TT
1416            |                        |                  |          |
1417            |                        |                  |          |
1418            |                        |                  |          |
1419            |                        |                  |          |
1420            |                        |                  |          |
1421            
1422
1423
1424     HANDLING A REQUEST
1425
1426
1427           BeerDB                                Model  $subclass  view_object
1428             |                                      |       |         |
1429     handler |                                      |       |         |
1430   o-------->| new                                  |       |         |
1431             |-----> r:BeerDB                       |       |         |
1432             |         |                            |       |         |
1433             |         |                            |       |         |
1434             |         ||                           |       |         |
1435             |         ||-----+ parse_location      |       |         |
1436             |         |||<---+                     |       |         |
1437             |         ||                           |       |         |
1438             |         ||-----+ start_request_hook  |       |         |
1439             |         |||<---+                     |       |         |
1440             |         ||                           |       |         |
1441             |         ||-----+ get_session         |       |         |
1442             |         |||<---+                     |       |         |
1443             |         ||                           |       |         |
1444             |         ||-----+ get_user            |       |         |
1445             |         |||<---+                     |       |         |
1446             |         ||                           |       |         |
1447             |         ||-----+ handler_guts        |       |         |
1448             |         |||<---+                     |       |         |
1449             |         |||     class_of($table)     |       |         |
1450             |         |||------------------------->||      |         |
1451             |         |||       $subclass          ||      |         |
1452             |         |||<-------------------------||      |         |
1453             |         |||                          |       |         |
1454             |         |||-----+ is_model_applicable|       |         |
1455             |         ||||<---+                    |       |         |
1456             |         |||                          |       |         |
1457             |         |||-----+ call_authenticate  |       |         |
1458             |         ||||<---+                    |       |         |
1459             |         |||                          |       |         |
1460             |         |||-----+ additional_data    |       |         |
1461             |         ||||<---+                    |       |         |
1462             |         |||             process      |       |         |
1463             |         |||--------------------------------->||  fetch_objects
1464             |         |||                          |       ||-----+  |
1465             |         |||                          |       |||<---+  |
1466             |         |||                          |       ||        |
1467             |         |||                          |       ||   $action
1468             |         |||                          |       ||-----+  |
1469             |         |||                          |       |||<---+  |            
1470             |         |||         process          |       |         |
1471             |         |||------------------------------------------->|| template
1472             |         |||                          |       |         ||-----+
1473             |         |||                          |       |         |||<---+
1474             |         |||                          |       |         |
1475             |         ||     send_output           |       |         |
1476             |         ||-----+                     |       |         |
1477             |         |||<---+                     |       |         |
1478    $status  |         ||                           |       |         |
1479    <------------------||                           |       |         |
1480             |         |                            |       |         |
1481             |         X                            |       |         |           
1482             |                                      |       |         |
1483             |                                      |       |         |
1484             |                                      |       |         |
1485            
1486            
1487
1488 =head1 SEE ALSO
1489
1490 There's more documentation, examples, and information on our mailing lists
1491 at the Maypole web site:
1492
1493 L<http://maypole.perl.org/>
1494
1495 L<Maypole::Application>, L<Apache::MVC>, L<CGI::Maypole>.
1496
1497 =head1 AUTHOR
1498
1499 Maypole is currently maintained by Aaron Trevena.
1500
1501 =head1 AUTHOR EMERITUS
1502
1503 Simon Cozens, C<simon#cpan.org>
1504
1505 Simon Flack maintained Maypole from 2.05 to 2.09
1506
1507 Sebastian Riedel, C<sri#oook.de> maintained Maypole from 1.99_01 to 2.04
1508
1509 =head1 THANKS TO
1510
1511 Sebastian Riedel, Danijel Milicevic, Dave Slack, Jesse Sheidlower, Jody Belka,
1512 Marcus Ramberg, Mickael Joanne, Randal Schwartz, Simon Flack, Steve Simms,
1513 Veljko Vidovic and all the others who've helped.
1514
1515 =head1 LICENSE
1516
1517 You may distribute this code under the same terms as Perl itself.
1518
1519 =cut
1520
1521 1;
1522
1523 __END__
1524
1525  =item register_cleanup($coderef)
1526
1527 Analogous to L<Apache>'s C<register_cleanup>. If an Apache request object is
1528 available, this call simply redispatches there. If not, the cleanup is
1529 registered in the Maypole request, and executed when the request is
1530 C<DESTROY>ed.
1531
1532 This method is only useful in persistent environments, where you need to ensure
1533 that some code runs when the request finishes, no matter how it finishes (e.g.
1534 after an unexpected error). 
1535
1536  =cut
1537
1538 {
1539     my @_cleanups;
1540
1541     sub register_cleanup
1542     {
1543         my ($self, $cleanup) = @_;
1544         
1545         die "register_cleanup() is an instance method, not a class method" 
1546             unless ref $self;
1547         die "Cleanup must be a coderef" unless ref($cleanup) eq 'CODE';
1548         
1549         if ($self->can('ar') && $self->ar)
1550         {
1551             $self->ar->register_cleanup($cleanup);
1552         }
1553         else
1554         {
1555             push @_cleanups, $cleanup;
1556         }
1557     }
1558
1559     sub DESTROY
1560     {
1561         my ($self) = @_;
1562         
1563         while (my $cleanup = shift @_cleanups)
1564         {
1565             eval { $cleanup->() };
1566             if ($@)
1567             {
1568                 warn "Error during request cleanup: $@";
1569             }
1570         }        
1571     }    
1572 }
1573