X-Git-Url: https://git.decadent.org.uk/gitweb/?a=blobdiff_plain;f=lib%2FMaypole%2FManual%2FPlugins.pod;h=7389b60875798bdb0807142c905258e0c4d49791;hb=1b05e3ca38fdb958cf9ced4d89e1478dc1e21257;hp=f0582c63225344c0b16b7d1c42f948be75cba65f;hpb=8b45000d65db9833d72ce55c559d509019cc367f;p=maypole.git diff --git a/lib/Maypole/Manual/Plugins.pod b/lib/Maypole/Manual/Plugins.pod index f0582c6..7389b60 100644 --- a/lib/Maypole/Manual/Plugins.pod +++ b/lib/Maypole/Manual/Plugins.pod @@ -8,11 +8,12 @@ This version written for Maypole 2.10 =head1 LOADING PLUGINS -Plugins occupy the C namespace on CPAN. At time of writing, there are 16 plugin modules -available - see http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module +Plugins occupy the C namespace on CPAN. At time of writing, +there are 16 plugin modules available - see +http://search.cpan.org/search?query=Maypole%3A%3APlugin&mode=module -Plugins are loaded into a Maypole application by L. For instance, to add L -support to the BeerDB example application: +Plugins are loaded into a Maypole application by L. For +instance, to add L support to the BeerDB example application: package BeerDB; use strict; @@ -22,11 +23,12 @@ support to the BeerDB example application: Note that the leading C is omitted. -For some plugins, that's it. You probably have a bunch of new methods available on your Maypole request objects - -see the documentation for the plugin. +For some plugins, that's it. You probably have a bunch of new methods available +on your Maypole request objects - see the documentation for the plugin. For others, you will need to set configuration variables or customise other -parts of the application. For instance, to add sessions to your application, you can use L: +parts of the application. For instance, to add sessions to your application, you +can use L: package BeerDB; use strict; @@ -34,7 +36,9 @@ parts of the application. For instance, to add sessions to your application, you use Maypole::Application( 'Session' ); -That's all, if you're willing to stick with the defaults (L backend, session and lock files in C and C). Otherwise, you need to supply some configuration: +That's all, if you're willing to stick with the defaults +(L backend, session and lock files in C +and C). Otherwise, you need to supply some configuration: __PACKAGE__->config->session( { class => "Apache::Session::Flex", args => { @@ -45,23 +49,28 @@ That's all, if you're willing to stick with the defaults (L, in this case, the C accessor. +The plugin module is responsible for adding slots to L, in this +case, the C accessor. =head1 WRITING PLUGINS =head2 Modifying the Maypole request object -Plugins are inserted into the C<@ISA> of the Maypole request object. So method calls on the request object will -first search the plugin classes, before looking in L. Methods defined in the plugin are -therefore directly available on the request. That also goes for methods inherited by the plugin. I'm not aware -of any plugins that currently inherit from another package, but there's no reason not to. +Plugins are inserted into the C<@ISA> of the Maypole request object. So method +calls on the request object will first search the plugin classes, before looking +in L. Methods defined in the plugin are therefore directly available on +the request. That also goes for methods inherited by the plugin. I'm not aware +of any plugins that currently inherit from another package, but there's no +reason not to. -Note that if you need simple accessor methods on the request, you can add them by saying +Note that if you need simple accessor methods on the request, you can add them +by saying Maypole->mk_accessors( qw/ fee fi fo / ); -at the start of your plugin. Under mod_perl, you've just added these accessors to B Maypole applications -on the server, even ones that do not use this plugin. You could instead make the call inside the C method: +at the start of your plugin. Under mod_perl, you've just added these accessors +to B Maypole applications on the server, even ones that do not use this +plugin. You could instead make the call inside the C method: $r->mk_accessors( qw/ fee fi fo / ); @@ -69,20 +78,24 @@ Now the accessors are only added to applications that use this plugin. =head2 Initialisation with C -After loading plugins via L, setting configuration variables in calls to -C<< __PACKAGE__->config->foo( 'bar' ) >>, and optionally defining custom request methods, your -application should call its C method, generally including arguments for the database connection: +After loading plugins via L, setting configuration +variables in calls to C<< __PACKAGE__->config->foo( 'bar' ) >>, and optionally +defining custom request methods, your application should call its C +method, generally including arguments for the database connection: __PACKAGE__->setup( $dsn, $user, $pass, @more_args ); -All of these arguments will be passed to the C method of the model class. +All of these arguments will be passed to the C method of the +model class. -C is responsible for loading the model class, calling the C method -on the model class, and making each table class in the application inherit from the model. It is therefore -recommended that you call C B setting up all your configuration options. +C is responsible for loading the model class, calling the +C method on the model class, and making each table class in the +application inherit from the model. It is therefore recommended that you call +C B setting up all your configuration options. -Plugins can intercept the call to C to carry out their own initialisation, as long as they propagate -the call up through the hierarchy. A common idiom for this is: +Plugins can intercept the call to C to carry out their own +initialisation, as long as they propagate the call up through the hierarchy. A +common idiom for this is: Maypole::Plugin::Foo; use strict; @@ -102,20 +115,23 @@ the call up through the hierarchy. A common idiom for this is: # do something with $option } -L is a replacement for the built-in C syntax. C dispatches a call to the superclass -of the current package - B it determines the superclass at compile time. At that time, the superclass -is something like C. L does the superclass lookup at runtime, after L has -inserted the plugin into the request class's inheritance chain. +L is a replacement for the built-in C syntax. C dispatches a +call to the superclass of the current package - B it determines the +superclass at compile time. At that time, the superclass is something like +C. L does the superclass lookup at runtime, after +L has inserted the plugin into the request class's +inheritance chain. -The C modifier ensures each plugin's C method is only called once, and protects against -diamond inheritance. This may or may not be an issue in your app - and if you always use the C -syntax, it won't be. +The C modifier ensures each plugin's C method is only called +once, and protects against diamond inheritance. This may or may not be an issue +in your app - and if you always use the C syntax, it won't be. -Notice that the C call is re-dispatched before running the plugin's own initialisation code. This -allows C to set up the database, model, and table classes, before your plugin starts tweaking -things. +Notice that the C call is re-dispatched before running the plugin's own +initialisation code. This allows C to set up the database, +model, and table classes, before your plugin starts tweaking things. -You can use the C method to load modules into the request class namespace. L has: +You can use the C method to load modules into the request class +namespace. L has: sub setup { my $r = shift; @@ -127,35 +143,39 @@ You can use the C method to load modules into the request class namespace Path => $r->config->lexicon; } -Now the application namespace has a C<_loc> function (exported by L), (plus C and -C methods inherited from L). +Now the application namespace has a C<_loc> function (exported by +L), (plus C and C methods inherited +from L). =head3 More initialisation with C L also defines an C method. It -pulls the name of the view class from the config, loads it, instantiates an object in the view class, and -sets this in the C config slot. +pulls the name of the view class from the config, loads it, instantiates an +object in the view class, and sets this in the C config slot. In CGI applications, C is called at the start of every request. -Under mod_perl, this method will only ever be called once per server child, at the start of the first request after -server startup. If instead, you call this method in your application module (after the call to C), -then the code loaded by this call will be shared by all child servers. +Under mod_perl, this method will only ever be called once per server child, at +the start of the first request after server startup. If instead, you call this +method in your application module (after the call to C), then the code +loaded by this call will be shared by all child servers. See B for a plugin that uses C. =head2 Adding configuration -The configuration object can be retrieved from the Maypole request object (C<< $r->config >>) or as a class method -on the application (e.g. C<< BeerDB->config >>). +The configuration object can be retrieved from the Maypole request object +(C<< $r->config >>) or as a class method on the application (e.g. +C<< BeerDB->config >>). -If your plugin needs some custom configuration settings, you can add methods to the config object by -saying +If your plugin needs some custom configuration settings, you can add methods to +the config object by saying Maypole::Config->mk_accessors( qw/ foo bar baz / ); -at the start of your plugin. In the application, after the C call, these methods will -be available on the config object. +at the start of your plugin. In the application, after the +C call, these methods will be available on the config +object. =head2 Modifying the Maypole model @@ -163,28 +183,33 @@ be available on the config object. =item Replacing the model -To load a different model, set C<< __PACKAGE__->config->model( 'Custom::Model' ) >> in the application -before calling C. You could instead set C<< $r->config->model >> before re-dispatching the C call, -but this is going to confuse and annoy your users. +To load a different model, set +C<< __PACKAGE__->config->model( 'Custom::Model' ) >> in the application +before calling C. You could instead set C<< $r->config->model >> before +re-dispatching the C call, but this is going to confuse and annoy your +users. =item Hacking the model B: the way I do this just seems dirty, so there must be a Better Way. -L (part of the L distribution), in its C method, -loads a custom pager class into the model by saying +L (part of the L +distribution), in its C method, loads a custom pager class into the model +by saying eval "package $model; use $pager"; -Yuk. Note that under mod_perl, you have just forced B application using C<$model> to also use C<$pager>. +Yuk. Note that under mod_perl, you have just forced B application using +C<$model> to also use C<$pager>. -C loads an extra method into the model by saying +C loads an extra method into the model by +saying no strict 'refs'; *{"$model\::auto_untaint"} = \&Class::DBI::Plugin::AutoUntaint::auto_untaint; -Yuk again. And again, under mod_perl, now every application using C<$model> has an C method -added to its model. +Yuk again. And again, under mod_perl, now every application using C<$model> has +an C method added to its model. Same plugin, next line has @@ -193,8 +218,6 @@ Same plugin, next line has Same yuk, same mod_perl caveat. - - =back @@ -208,11 +231,13 @@ Again, just specify a different view in the application configuration. =item Hacking the view -L intercepts the C call to override the C method in the view class. -First it re-dispatches the C call, which will set up either a default view class and object, or those -configured in the application. Then it builds a new view class on-the-fly, and makes this new class inherit from -L and from the original view class. Finally it replaces the C and C -in the application's config object. +L intercepts the C call to override the +C method in the view class. First it re-dispatches the C call, which +will set up either a default view class and object, or those configured in the +application. Then it builds a new view class on-the-fly, and makes this new +class inherit from L and from the original view +class. Finally it replaces the C and C in the application's +config object. sub init {