]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole/Manual/Plugins.pod
added lib/Maypole/Manual/Plugins.pod
[maypole.git] / lib / Maypole / Manual / Plugins.pod
1 =head1 NAME
2
3 Maypole::Manual::Plugins - the Maypole Plugin API
4
5 =head1 VERSION
6
7 This version written for Maypole 2.10
8
9 =head1 LOADING PLUGINS
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
13
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:
16
17    package BeerDB;
18    use strict;
19    use warnings;
20
21    use Maypole::Application( 'QuickTable' );
22
23 Note that the leading C<Maypole::Plugin::*> is omitted.
24
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.
27
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>:
30
31    package BeerDB;
32    use strict;
33    use warnings;
34
35    use Maypole::Application( 'Session' );
36
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:
38
39    __PACKAGE__->config->session( { class => "Apache::Session::Flex",
40                                    args  => {
41                                        Store     => 'DB_File',
42                                        Lock      => 'Null',
43                                        Generate  => 'MD5',
44                                        Serialize => 'Storable'
45                                        }
46                                    } );
47
48 The plugin module is responsible for adding slots to L<Maypole::Config>, in this case, the C<session> accessor.
49
50 =head1 WRITING PLUGINS
51
52 =head2 Modifying the Maypole request object
53
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.
58
59 Note that if you need simple accessor methods on the request, you can add them by saying
60
61    Maypole->mk_accessors( qw/ fee fi fo / );
62
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:
65
66    $r->mk_accessors( qw/ fee fi fo / );
67
68 Now the accessors are only added to applications that use this plugin.
69
70 =head2 Initialisation with C<setup>
71
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:
75
76    __PACKAGE__->setup( $dsn, $user, $pass, @more_args );
77
78 All of these arguments will be passed to the C<setup_database> method of the model class.
79
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.
83
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:
86
87    Maypole::Plugin::Foo;
88    use strict;
89    use warnings;
90
91    use NEXT;
92
93    sub setup
94    {
95        my $r = shift;
96
97        $r->NEXT::DISTINCT::setup(@_);
98
99        # Foo initialisation goes here
100        my $option = $r->config->foo_option;
101
102        # do something with $option
103    }
104
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.
109
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>
112 syntax, it won't be.
113
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
116 things.
117
118 You can use the C<setup> method to load modules into the request class namespace. L<Maypole::Plugin::I18N> has:
119
120    sub setup {
121        my $r = shift;
122        $r->NEXT::DISTINCT::setup(@_);
123        require Locale::Maketext::Simple;
124        import Locale::Maketext::Simple
125          Class  => $r,
126          Export => '_loc',
127          Path   => $r->config->lexicon;
128 }
129
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>).
132
133 =head3 More initialisation with C<init>
134
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.
138
139 In CGI applications, C<init> is called at the start of every request.
140
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.
144
145 See B<Hacking the view> for a plugin that uses C<init>.
146
147 =head2 Adding configuration
148
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 >>).
151
152 If your plugin needs some custom configuration settings, you can add methods to the config object by
153 saying
154
155    Maypole::Config->mk_accessors( qw/ foo bar baz / );
156
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.
159
160 =head2 Modifying the Maypole model
161
162 =over 4
163
164 =item Replacing the model
165
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.
169
170 =item Hacking the model
171
172 B<CAVEAT>: the way I do this just seems dirty, so there must be a Better Way.
173
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
176
177    eval "package $model; use $pager";
178
179 Yuk. Note that under mod_perl, you have just forced B<every> application using C<$model> to also use C<$pager>.
180
181 C<Maypole::Plugin::AutoUntaint::setup()> loads an extra method into the model by saying
182
183    no strict 'refs';
184    *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint;
185
186 Yuk again. And again, under mod_perl, now every application using C<$model> has an C<auto_untaint> method
187 added to its model.
188
189 Same plugin, next line has
190
191    eval "package $model; use Class::DBI::Plugin::Type";
192
193 Same yuk, same mod_perl caveat.
194
195
196
197
198 =back
199
200
201 =head2 Modifying the Maypole view
202
203 =over 4
204
205 =item Replacing the view
206
207 Again, just specify a different view in the application configuration.
208
209 =item Hacking the view
210
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.
216
217    sub init
218    {
219        my ( $class ) = @_;
220
221        my $config = $class->config;
222
223        $class->NEXT::DISTINCT::init;
224
225        my $old_view = $class->config->view ||
226            die "Please configure a view in $class before calling init()";
227
228        my $virtual_view = "$class\::__::View";
229
230        eval <<VIEW;
231    package $virtual_view;
232    use base qw( Maypole::FormBuilder::View $old_view );
233    VIEW
234
235        die $@ if $@;
236
237        $config->view( $virtual_view );
238
239        $class->view_object( $virtual_view->new );
240    }
241
242
243 There really must be a Better Way.
244
245 =back
246
247 =head1 AUTHOR
248
249 David Baird, C<< <cpan@riverside-cms.co.uk> >>
250
251 =head1 COPYRIGHT & LICENSE
252
253 Copyright 2005 David Baird, All Rights Reserved.
254
255 This text is free documentation; you can redistribute it and/or modify it
256 under the same terms as the Perl documentation itself.
257
258 =cut