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, there are 16 plugin modules
12 available - see http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module
14 Plugins are loaded into a Maypole application by L<Maypole::Application>. For instance, to add L<HTML::QuickTable>
15 support to the BeerDB example application:
21 use Maypole::Application( 'QuickTable' );
23 Note that the leading C<Maypole::Plugin::*> is omitted.
25 For some plugins, that's it. You probably have a bunch of new methods available on your Maypole request objects -
26 see the documentation for the plugin.
28 For others, you will need to set configuration variables or customise other
29 parts of the application. For instance, to add sessions to your application, you can use L<Maypole::Plugin::Session>:
35 use Maypole::Application( 'Session' );
37 That's all, if you're willing to stick with the defaults (L<Apache::Session::File> backend, session and lock files in C</tmp/sessions> and C</tmp/sessionlock>). Otherwise, you need to supply some configuration:
39 __PACKAGE__->config->session( { class => "Apache::Session::Flex",
44 Serialize => 'Storable'
48 The plugin module is responsible for adding slots to L<Maypole::Config>, in this case, the C<session> accessor.
50 =head1 WRITING PLUGINS
52 =head2 Modifying the Maypole request object
54 Plugins are inserted into the C<@ISA> of the Maypole request object. So method calls on the request object will
55 first search the plugin classes, before looking in L<Maypole>. Methods defined in the plugin are
56 therefore directly available on the request. That also goes for methods inherited by the plugin. I'm not aware
57 of any plugins that currently inherit from another package, but there's no reason not to.
59 Note that if you need simple accessor methods on the request, you can add them by saying
61 Maypole->mk_accessors( qw/ fee fi fo / );
63 at the start of your plugin. Under mod_perl, you've just added these accessors to B<all> Maypole applications
64 on the server, even ones that do not use this plugin. You could instead make the call inside the C<setup> method:
66 $r->mk_accessors( qw/ fee fi fo / );
68 Now the accessors are only added to applications that use this plugin.
70 =head2 Initialisation with C<setup>
72 After loading plugins via L<Maypole::Application>, setting configuration variables in calls to
73 C<< __PACKAGE__->config->foo( 'bar' ) >>, and optionally defining custom request methods, your
74 application should call its C<setup> method, generally including arguments for the database connection:
76 __PACKAGE__->setup( $dsn, $user, $pass, @more_args );
78 All of these arguments will be passed to the C<setup_database> method of the model class.
80 C<Maypole::setup()> is responsible for loading the model class, calling the C<setup_database> method
81 on the model class, and making each table class in the application inherit from the model. It is therefore
82 recommended that you call C<setup> B<after> setting up all your configuration options.
84 Plugins can intercept the call to C<setup> to carry out their own initialisation, as long as they propagate
85 the call up through the hierarchy. A common idiom for this is:
97 $r->NEXT::DISTINCT::setup(@_);
99 # Foo initialisation goes here
100 my $option = $r->config->foo_option;
102 # do something with $option
105 L<NEXT> is a replacement for the built-in C<SUPER> syntax. C<SUPER> dispatches a call to the superclass
106 of the current package - B<but> it determines the superclass at compile time. At that time, the superclass
107 is something like C<main::>. L<NEXT> does the superclass lookup at runtime, after L<Maypole::Application> has
108 inserted the plugin into the request class's inheritance chain.
110 The C<DISTINCT> modifier ensures each plugin's C<setup> method is only called once, and protects against
111 diamond inheritance. This may or may not be an issue in your app - and if you always use the C<DISTINCT>
114 Notice that the C<setup> call is re-dispatched before running the plugin's own initialisation code. This
115 allows C<Maypole::setup()> to set up the database, model, and table classes, before your plugin starts tweaking
118 You can use the C<setup> method to load modules into the request class namespace. L<Maypole::Plugin::I18N> has:
122 $r->NEXT::DISTINCT::setup(@_);
123 require Locale::Maketext::Simple;
124 import Locale::Maketext::Simple
127 Path => $r->config->lexicon;
130 Now the application namespace has a C<_loc> function (exported by L<Locale::Maketext::Simple>), (plus C<lang> and
131 C<maketext> methods inherited from L<Maypole::Plugin::I18N>).
133 =head3 More initialisation with C<init>
135 L<Maypole> also defines an C<init> method. It
136 pulls the name of the view class from the config, loads it, instantiates an object in the view class, and
137 sets this in the C<view_object> config slot.
139 In CGI applications, C<init> is called at the start of every request.
141 Under mod_perl, this method will only ever be called once per server child, at the start of the first request after
142 server startup. If instead, you call this method in your application module (after the call to C<setup>),
143 then the code loaded by this call will be shared by all child servers.
145 See B<Hacking the view> for a plugin that uses C<init>.
147 =head2 Adding configuration
149 The configuration object can be retrieved from the Maypole request object (C<< $r->config >>) or as a class method
150 on the application (e.g. C<< BeerDB->config >>).
152 If your plugin needs some custom configuration settings, you can add methods to the config object by
155 Maypole::Config->mk_accessors( qw/ foo bar baz / );
157 at the start of your plugin. In the application, after the C<Maypole::Application> call, these methods will
158 be available on the config object.
160 =head2 Modifying the Maypole model
164 =item Replacing the model
166 To load a different model, set C<< __PACKAGE__->config->model( 'Custom::Model' ) >> in the application
167 before calling C<setup>. You could instead set C<< $r->config->model >> before re-dispatching the C<setup> call,
168 but this is going to confuse and annoy your users.
170 =item Hacking the model
172 B<CAVEAT>: the way I do this just seems dirty, so there must be a Better Way.
174 L<Maypole::Plugin::FormBuilder> (part of the L<Maypole::FormBuilder> distribution), in its C<setup> method,
175 loads a custom pager class into the model by saying
177 eval "package $model; use $pager";
179 Yuk. Note that under mod_perl, you have just forced B<every> application using C<$model> to also use C<$pager>.
181 C<Maypole::Plugin::AutoUntaint::setup()> loads an extra method into the model by saying
184 *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint;
186 Yuk again. And again, under mod_perl, now every application using C<$model> has an C<auto_untaint> method
189 Same plugin, next line has
191 eval "package $model; use Class::DBI::Plugin::Type";
193 Same yuk, same mod_perl caveat.
201 =head2 Modifying the Maypole view
205 =item Replacing the view
207 Again, just specify a different view in the application configuration.
209 =item Hacking the view
211 L<Maypole::Plugin::FormBuilder> intercepts the C<init> call to override the C<vars> method in the view class.
212 First it re-dispatches the C<init> call, which will set up either a default view class and object, or those
213 configured in the application. Then it builds a new view class on-the-fly, and makes this new class inherit from
214 L<Maypole::FormBuilder::View> and from the original view class. Finally it replaces the C<view> and C<view_object>
215 in the application's config object.
221 my $config = $class->config;
223 $class->NEXT::DISTINCT::init;
225 my $old_view = $class->config->view ||
226 die "Please configure a view in $class before calling init()";
228 my $virtual_view = "$class\::__::View";
231 package $virtual_view;
232 use base qw( Maypole::FormBuilder::View $old_view );
237 $config->view( $virtual_view );
239 $class->view_object( $virtual_view->new );
243 There really must be a Better Way.
249 David Baird, C<< <cpan@riverside-cms.co.uk> >>
251 =head1 COPYRIGHT & LICENSE
253 Copyright 2005 David Baird, All Rights Reserved.
255 This text is free documentation; you can redistribute it and/or modify it
256 under the same terms as the Perl documentation itself.