1Maypole::Manual::PluginUss(e3r)Contributed Perl DocumentMaatyipoonle::Manual::Plugins(3)
2
3
4

NAME

6       Maypole::Manual::Plugins - the Maypole Plugin API
7

VERSION

9       This version written for Maypole 2.10
10

LOADING PLUGINS

12       Plugins occupy the "Maypole::Plugin::*" namespace on CPAN. At time of
13       writing, there are 16 plugin modules available - see
14       http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module
15
16       Plugins are loaded into a Maypole application by Maypole::Application.
17       For instance, to add HTML::QuickTable support to the BeerDB example
18       application:
19
20          package BeerDB;
21          use strict;
22          use warnings;
23
24          use Maypole::Application( 'QuickTable' );
25
26       Note that the leading "Maypole::Plugin::*" is omitted.
27
28       For some plugins, that's it. You probably have a bunch of new methods
29       available on your Maypole request objects - see the documentation for
30       the plugin.
31
32       For others, you will need to set configuration variables or customise
33       other parts of the application. For instance, to add sessions to your
34       application, you can use Maypole::Plugin::Session:
35
36          package BeerDB;
37          use strict;
38          use warnings;
39
40          use Maypole::Application( 'Session' );
41
42       That's all, if you're willing to stick with the defaults
43       (Apache::Session::File backend, session and lock files in
44       "/tmp/sessions" and "/tmp/sessionlock"). Otherwise, you need to supply
45       some configuration:
46
47          __PACKAGE__->config->session( { class => "Apache::Session::Flex",
48                                          args  => {
49                                              Store     => 'DB_File',
50                                              Lock      => 'Null',
51                                              Generate  => 'MD5',
52                                              Serialize => 'Storable'
53                                              }
54                                          } );
55
56       The plugin module is responsible for adding slots to Maypole::Config,
57       in this case, the "session" accessor.
58

WRITING PLUGINS

60   Modifying the Maypole request object
61       Plugins are inserted into the @ISA of the Maypole request object. So
62       method calls on the request object will first search the plugin
63       classes, before looking in Maypole. Methods defined in the plugin are
64       therefore directly available on the request. That also goes for methods
65       inherited by the plugin. I'm not aware of any plugins that currently
66       inherit from another package, but there's no reason not to.
67
68       Note that if you need simple accessor methods on the request, you can
69       add them by saying
70
71          Maypole->mk_accessors( qw/ fee fi fo / );
72
73       at the start of your plugin. Under mod_perl, you've just added these
74       accessors to all Maypole applications on the server, even ones that do
75       not use this plugin. You could instead make the call inside the "setup"
76       method:
77
78          $r->mk_accessors( qw/ fee fi fo / );
79
80       Now the accessors are only added to applications that use this plugin.
81
82   Initialisation with "setup"
83       After loading plugins via Maypole::Application, setting configuration
84       variables in calls to "__PACKAGE__->config->foo( 'bar' )", and
85       optionally defining custom request methods, your application should
86       call its "setup" method, generally including arguments for the database
87       connection:
88
89          __PACKAGE__->setup( $dsn, $user, $pass, @more_args );
90
91       All of these arguments will be passed to the "setup_database" method of
92       the model class.
93
94       "Maypole::setup()" is responsible for loading the model class, calling
95       the "setup_database" method on the model class, and making each table
96       class in the application inherit from the model. It is therefore
97       recommended that you call "setup" after setting up all your
98       configuration options.
99
100       Plugins can intercept the call to "setup" to carry out their own
101       initialisation, as long as they propagate the call up through the
102       hierarchy. A common idiom for this is:
103
104          Maypole::Plugin::Foo;
105          use strict;
106          use warnings;
107
108          use NEXT;
109
110          sub setup
111          {
112              my $r = shift;
113
114              $r->NEXT::DISTINCT::setup(@_);
115
116              # Foo initialisation goes here
117              my $option = $r->config->foo_option;
118
119              # do something with $option
120          }
121
122       NEXT is a replacement for the built-in "SUPER" syntax. "SUPER"
123       dispatches a call to the superclass of the current package - but it
124       determines the superclass at compile time. At that time, the superclass
125       is something like "main::". NEXT does the superclass lookup at runtime,
126       after Maypole::Application has inserted the plugin into the request
127       class's inheritance chain.
128
129       The "DISTINCT" modifier ensures each plugin's "setup" method is only
130       called once, and protects against diamond inheritance. This may or may
131       not be an issue in your app - and if you always use the "DISTINCT"
132       syntax, it won't be.
133
134       Notice that the "setup" call is re-dispatched before running the
135       plugin's own initialisation code. This allows "Maypole::setup()" to set
136       up the database, model, and table classes, before your plugin starts
137       tweaking things.
138
139       You can use the "setup" method to load modules into the request class
140       namespace. Maypole::Plugin::I18N has:
141
142          sub setup {
143              my $r = shift;
144              $r->NEXT::DISTINCT::setup(@_);
145              require Locale::Maketext::Simple;
146              import Locale::Maketext::Simple
147                Class  => $r,
148                Export => '_loc',
149                Path   => $r->config->lexicon;
150       }
151
152       Now the application namespace has a "_loc" function (exported by
153       Locale::Maketext::Simple), (plus "lang" and "maketext" methods
154       inherited from Maypole::Plugin::I18N).
155
156       More initialisation with "init"
157
158       Maypole also defines an "init" method. It pulls the name of the view
159       class from the config, loads it, instantiates an object in the view
160       class, and sets this in the "view_object" config slot.
161
162       In CGI applications, "init" is called at the start of every request.
163
164       Under mod_perl, this method will only ever be called once per server
165       child, at the start of the first request after server startup. If
166       instead, you call this method in your application module (after the
167       call to "setup"), then the code loaded by this call will be shared by
168       all child servers.
169
170       See Hacking the view for a plugin that uses "init".
171
172   Adding configuration
173       The configuration object can be retrieved from the Maypole request
174       object ("$r->config") or as a class method on the application (e.g.
175       "BeerDB->config").
176
177       If your plugin needs some custom configuration settings, you can add
178       methods to the config object by saying
179
180          Maypole::Config->mk_accessors( qw/ foo bar baz / );
181
182       at the start of your plugin. In the application, after the
183       "Maypole::Application" call, these methods will be available on the
184       config object.
185
186   Modifying the Maypole model
187       Replacing the model
188           To load a different model, set "__PACKAGE__->config->model(
189           'Custom::Model' )" in the application before calling "setup". You
190           could instead set "$r->config->model" before re-dispatching the
191           "setup" call, but this is going to confuse and annoy your users.
192
193       Hacking the model
194           CAVEAT: the way I do this just seems dirty, so there must be a
195           Better Way.
196
197           Maypole::Plugin::FormBuilder (part of the Maypole::FormBuilder
198           distribution), in its "setup" method, loads a custom pager class
199           into the model by saying
200
201              eval "package $model; use $pager";
202
203           Yuk. Note that under mod_perl, you have just forced every
204           application using $model to also use $pager.
205
206           "Maypole::Plugin::AutoUntaint::setup()" loads an extra method into
207           the model by saying
208
209              no strict 'refs';
210              *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint;
211
212           Yuk again. And again, under mod_perl, now every application using
213           $model has an "auto_untaint" method added to its model.
214
215           Same plugin, next line has
216
217              eval "package $model; use Class::DBI::Plugin::Type";
218
219           Same yuk, same mod_perl caveat.
220
221   Modifying the Maypole view
222       Replacing the view
223           Again, just specify a different view in the application
224           configuration.
225
226       Hacking the view
227           Maypole::Plugin::FormBuilder intercepts the "init" call to override
228           the "vars" method in the view class. First it re-dispatches the
229           "init" call, which will set up either a default view class and
230           object, or those configured in the application. Then it builds a
231           new view class on-the-fly, and makes this new class inherit from
232           Maypole::FormBuilder::View and from the original view class.
233           Finally it replaces the "view" and "view_object" in the
234           application's config object.
235
236              sub init
237              {
238                  my ( $class ) = @_;
239
240                  my $config = $class->config;
241
242                  $class->NEXT::DISTINCT::init;
243
244                  my $old_view = $class->config->view ||
245                      die "Please configure a view in $class before calling init()";
246
247                  my $virtual_view = "$class\::__::View";
248
249                  eval <<VIEW;
250              package $virtual_view;
251              use base qw( Maypole::FormBuilder::View $old_view );
252              VIEW
253
254                  die $@ if $@;
255
256                  $config->view( $virtual_view );
257
258                  $class->view_object( $virtual_view->new );
259              }
260
261           There really must be a Better Way.
262

AUTHOR

264       David Baird, "<cpan@riverside-cms.co.uk>"
265
267       Copyright 2005 David Baird, All Rights Reserved.
268
269       This text is free documentation; you can redistribute it and/or modify
270       it under the same terms as the Perl documentation itself.
271
272
273
274perl v5.34.0                      2022-01-21       Maypole::Manual::Plugins(3)
Impressum