3 Maypole::Manual::Plugins - the Maypole Plugin API
7 This version written for Maypole 2.10
11 Plugins occupy the C<Maypole::Plugin::*> namespace on CPAN. At time of writing,
12 there are 16 plugin modules available - see
13 http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module
15 Plugins are loaded into a Maypole application by L<Maypole::Application>. For
16 instance, to add L<HTML::QuickTable> support to the BeerDB example application:
22 use Maypole::Application( 'QuickTable' );
24 Note that the leading C<Maypole::Plugin::*> is omitted.
26 For some plugins, that's it. You probably have a bunch of new methods available
27 on your Maypole request objects - see the documentation for the plugin.
29 For others, you will need to set configuration variables or customise other
30 parts of the application. For instance, to add sessions to your application, you
31 can use L<Maypole::Plugin::Session>:
37 use Maypole::Application( 'Session' );
39 That's all, if you're willing to stick with the defaults
40 (L<Apache::Session::File> backend, session and lock files in C</tmp/sessions>
41 and C</tmp/sessionlock>). Otherwise, you need to supply some configuration:
43 __PACKAGE__->config->session( { class => "Apache::Session::Flex",
48 Serialize => 'Storable'
52 The plugin module is responsible for adding slots to L<Maypole::Config>, in this
53 case, the C<session> accessor.
55 =head1 WRITING PLUGINS
57 =head2 Modifying the Maypole request object
59 Plugins are inserted into the C<@ISA> of the Maypole request object. So method
60 calls on the request object will first search the plugin classes, before looking
61 in L<Maypole>. Methods defined in the plugin are therefore directly available on
62 the request. That also goes for methods inherited by the plugin. I'm not aware
63 of any plugins that currently inherit from another package, but there's no
66 Note that if you need simple accessor methods on the request, you can add them
69 Maypole->mk_accessors( qw/ fee fi fo / );
71 at the start of your plugin. Under mod_perl, you've just added these accessors
72 to B<all> Maypole applications on the server, even ones that do not use this
73 plugin. You could instead make the call inside the C<setup> method:
75 $r->mk_accessors( qw/ fee fi fo / );
77 Now the accessors are only added to applications that use this plugin.
79 =head2 Initialisation with C<setup>
81 After loading plugins via L<Maypole::Application>, setting configuration
82 variables in calls to C<< __PACKAGE__->config->foo( 'bar' ) >>, and optionally
83 defining custom request methods, your application should call its C<setup>
84 method, generally including arguments for the database connection:
86 __PACKAGE__->setup( $dsn, $user, $pass, @more_args );
88 All of these arguments will be passed to the C<setup_database> method of the
91 C<Maypole::setup()> is responsible for loading the model class, calling the
92 C<setup_database> method on the model class, and making each table class in the
93 application inherit from the model. It is therefore recommended that you call
94 C<setup> B<after> setting up all your configuration options.
96 Plugins can intercept the call to C<setup> to carry out their own
97 initialisation, as long as they propagate the call up through the hierarchy. A
98 common idiom for this is:
100 Maypole::Plugin::Foo;
110 $r->NEXT::DISTINCT::setup(@_);
112 # Foo initialisation goes here
113 my $option = $r->config->foo_option;
115 # do something with $option
118 L<NEXT> is a replacement for the built-in C<SUPER> syntax. C<SUPER> dispatches a
119 call to the superclass of the current package - B<but> it determines the
120 superclass at compile time. At that time, the superclass is something like
121 C<main::>. L<NEXT> does the superclass lookup at runtime, after
122 L<Maypole::Application> has inserted the plugin into the request class's
125 The C<DISTINCT> modifier ensures each plugin's C<setup> method is only called
126 once, and protects against diamond inheritance. This may or may not be an issue
127 in your app - and if you always use the C<DISTINCT> syntax, it won't be.
129 Notice that the C<setup> call is re-dispatched before running the plugin's own
130 initialisation code. This allows C<Maypole::setup()> to set up the database,
131 model, and table classes, before your plugin starts tweaking things.
133 You can use the C<setup> method to load modules into the request class
134 namespace. L<Maypole::Plugin::I18N> has:
138 $r->NEXT::DISTINCT::setup(@_);
139 require Locale::Maketext::Simple;
140 import Locale::Maketext::Simple
143 Path => $r->config->lexicon;
146 Now the application namespace has a C<_loc> function (exported by
147 L<Locale::Maketext::Simple>), (plus C<lang> and C<maketext> methods inherited
148 from L<Maypole::Plugin::I18N>).
150 =head3 More initialisation with C<init>
152 L<Maypole> also defines an C<init> method. It
153 pulls the name of the view class from the config, loads it, instantiates an
154 object in the view class, and sets this in the C<view_object> config slot.
156 In CGI applications, C<init> is called at the start of every request.
158 Under mod_perl, this method will only ever be called once per server child, at
159 the start of the first request after server startup. If instead, you call this
160 method in your application module (after the call to C<setup>), then the code
161 loaded by this call will be shared by all child servers.
163 See B<Hacking the view> for a plugin that uses C<init>.
165 =head2 Adding configuration
167 The configuration object can be retrieved from the Maypole request object
168 (C<< $r->config >>) or as a class method on the application (e.g.
169 C<< BeerDB->config >>).
171 If your plugin needs some custom configuration settings, you can add methods to
172 the config object by saying
174 Maypole::Config->mk_accessors( qw/ foo bar baz / );
176 at the start of your plugin. In the application, after the
177 C<Maypole::Application> call, these methods will be available on the config
180 =head2 Modifying the Maypole model
184 =item Replacing the model
186 To load a different model, set
187 C<< __PACKAGE__->config->model( 'Custom::Model' ) >> in the application
188 before calling C<setup>. You could instead set C<< $r->config->model >> before
189 re-dispatching the C<setup> call, but this is going to confuse and annoy your
192 =item Hacking the model
194 B<CAVEAT>: the way I do this just seems dirty, so there must be a Better Way.
196 L<Maypole::Plugin::FormBuilder> (part of the L<Maypole::FormBuilder>
197 distribution), in its C<setup> method, loads a custom pager class into the model
200 eval "package $model; use $pager";
202 Yuk. Note that under mod_perl, you have just forced B<every> application using
203 C<$model> to also use C<$pager>.
205 C<Maypole::Plugin::AutoUntaint::setup()> loads an extra method into the model by
209 *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint;
211 Yuk again. And again, under mod_perl, now every application using C<$model> has
212 an C<auto_untaint> method added to its model.
214 Same plugin, next line has
216 eval "package $model; use Class::DBI::Plugin::Type";
218 Same yuk, same mod_perl caveat.
224 =head2 Modifying the Maypole view
228 =item Replacing the view
230 Again, just specify a different view in the application configuration.
232 =item Hacking the view
234 L<Maypole::Plugin::FormBuilder> intercepts the C<init> call to override the
235 C<vars> method in the view class. First it re-dispatches the C<init> call, which
236 will set up either a default view class and object, or those configured in the
237 application. Then it builds a new view class on-the-fly, and makes this new
238 class inherit from L<Maypole::FormBuilder::View> and from the original view
239 class. Finally it replaces the C<view> and C<view_object> in the application's
246 my $config = $class->config;
248 $class->NEXT::DISTINCT::init;
250 my $old_view = $class->config->view ||
251 die "Please configure a view in $class before calling init()";
253 my $virtual_view = "$class\::__::View";
256 package $virtual_view;
257 use base qw( Maypole::FormBuilder::View $old_view );
262 $config->view( $virtual_view );
264 $class->view_object( $virtual_view->new );
268 There really must be a Better Way.
274 David Baird, C<< <cpan@riverside-cms.co.uk> >>
276 =head1 COPYRIGHT & LICENSE
278 Copyright 2005 David Baird, All Rights Reserved.
280 This text is free documentation; you can redistribute it and/or modify it
281 under the same terms as the Perl documentation itself.