]> git.decadent.org.uk Git - maypole.git/blob - lib/Maypole/Manual/Plugins.pod
updated Changes
[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, 
12 there are 16 plugin modules available - see 
13 http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module
14
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:
17
18    package BeerDB;
19    use strict;
20    use warnings;
21
22    use Maypole::Application( 'QuickTable' );
23
24 Note that the leading C<Maypole::Plugin::*> is omitted.
25
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.
28
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>:
32
33    package BeerDB;
34    use strict;
35    use warnings;
36
37    use Maypole::Application( 'Session' );
38
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:
42
43    __PACKAGE__->config->session( { class => "Apache::Session::Flex",
44                                    args  => {
45                                        Store     => 'DB_File',
46                                        Lock      => 'Null',
47                                        Generate  => 'MD5',
48                                        Serialize => 'Storable'
49                                        }
50                                    } );
51
52 The plugin module is responsible for adding slots to L<Maypole::Config>, in this 
53 case, the C<session> accessor.
54
55 =head1 WRITING PLUGINS
56
57 =head2 Modifying the Maypole request object
58
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 
64 reason not to.
65
66 Note that if you need simple accessor methods on the request, you can add them 
67 by saying
68
69    Maypole->mk_accessors( qw/ fee fi fo / );
70
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:
74
75    $r->mk_accessors( qw/ fee fi fo / );
76
77 Now the accessors are only added to applications that use this plugin.
78
79 =head2 Initialisation with C<setup>
80
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:
85
86    __PACKAGE__->setup( $dsn, $user, $pass, @more_args );
87
88 All of these arguments will be passed to the C<setup_database> method of the 
89 model class.
90
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.
95
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:
99
100    Maypole::Plugin::Foo;
101    use strict;
102    use warnings;
103
104    use NEXT;
105
106    sub setup
107    {
108        my $r = shift;
109
110        $r->NEXT::DISTINCT::setup(@_);
111
112        # Foo initialisation goes here
113        my $option = $r->config->foo_option;
114
115        # do something with $option
116    }
117
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 
123 inheritance chain.
124
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.
128
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.
132
133 You can use the C<setup> method to load modules into the request class 
134 namespace. L<Maypole::Plugin::I18N> has:
135
136    sub setup {
137        my $r = shift;
138        $r->NEXT::DISTINCT::setup(@_);
139        require Locale::Maketext::Simple;
140        import Locale::Maketext::Simple
141          Class  => $r,
142          Export => '_loc',
143          Path   => $r->config->lexicon;
144 }
145
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>).
149
150 =head3 More initialisation with C<init>
151
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.
155
156 In CGI applications, C<init> is called at the start of every request.
157
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.
162
163 See B<Hacking the view> for a plugin that uses C<init>.
164
165 =head2 Adding configuration
166
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 >>).
170
171 If your plugin needs some custom configuration settings, you can add methods to 
172 the config object by saying
173
174    Maypole::Config->mk_accessors( qw/ foo bar baz / );
175
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 
178 object.
179
180 =head2 Modifying the Maypole model
181
182 =over 4
183
184 =item Replacing the model
185
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 
190 users.
191
192 =item Hacking the model
193
194 B<CAVEAT>: the way I do this just seems dirty, so there must be a Better Way.
195
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 
198 by saying
199
200    eval "package $model; use $pager";
201
202 Yuk. Note that under mod_perl, you have just forced B<every> application using 
203 C<$model> to also use C<$pager>.
204
205 C<Maypole::Plugin::AutoUntaint::setup()> loads an extra method into the model by 
206 saying
207
208    no strict 'refs';
209    *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint;
210
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.
213
214 Same plugin, next line has
215
216    eval "package $model; use Class::DBI::Plugin::Type";
217
218 Same yuk, same mod_perl caveat.
219
220
221 =back
222
223
224 =head2 Modifying the Maypole view
225
226 =over 4
227
228 =item Replacing the view
229
230 Again, just specify a different view in the application configuration.
231
232 =item Hacking the view
233
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 
240 config object.
241
242    sub init
243    {
244        my ( $class ) = @_;
245
246        my $config = $class->config;
247
248        $class->NEXT::DISTINCT::init;
249
250        my $old_view = $class->config->view ||
251            die "Please configure a view in $class before calling init()";
252
253        my $virtual_view = "$class\::__::View";
254
255        eval <<VIEW;
256    package $virtual_view;
257    use base qw( Maypole::FormBuilder::View $old_view );
258    VIEW
259
260        die $@ if $@;
261
262        $config->view( $virtual_view );
263
264        $class->view_object( $virtual_view->new );
265    }
266
267
268 There really must be a Better Way.
269
270 =back
271
272 =head1 AUTHOR
273
274 David Baird, C<< <cpan@riverside-cms.co.uk> >>
275
276 =head1 COPYRIGHT & LICENSE
277
278 Copyright 2005 David Baird, All Rights Reserved.
279
280 This text is free documentation; you can redistribute it and/or modify it
281 under the same terms as the Perl documentation itself.
282
283 =cut