File Coverage

blib/lib/Module/Pluggable.pm
Criterion Covered Total %
statement 49 63 77.7
branch 3 18 16.6
condition 4 11 36.3
subroutine 9 11 81.8
pod n/a
total 65 103 63.1


line stmt bran cond sub pod time code
1             package Module::Pluggable;
2              
3 40     40   3434688 use strict;
  40         65  
  40         1168  
4 40     40   15408 use Module::Pluggable::Object;
  40         89  
  40         1531  
5              
6 40     40   253 use if $] > 5.017, 'deprecate';
  40         66  
  40         635  
7              
8             # ObQuote:
9             # Bob Porter: Looks like you've been missing a lot of work lately.
10             # Peter Gibbons: I wouldn't say I've been missing it, Bob!
11              
12              
13             our $VERSION = '6.3';
14             our $FORCE_SEARCH_ALL_PATHS = 0;
15              
16             sub import {
17 50     50   643 my $class = shift;
18 50         145 my %opts = @_;
19              
20 50         140 my ($pkg, $file) = caller;
21             # the default name for the method is 'plugins'
22 50   100     315 my $sub = $opts{'sub_name'} || 'plugins';
23             # get our package
24 50   66     212 my ($package) = $opts{'package'} || $pkg;
25 50         86 $opts{filename} = $file;
26 50         73 $opts{package} = $package;
27 50 50       120 $opts{force_search_all_paths} = $FORCE_SEARCH_ALL_PATHS unless exists $opts{force_search_all_paths};
28              
29              
30 50         214 my $finder = Module::Pluggable::Object->new(%opts);
31 50     71   201 my $subroutine = sub { my $self = shift; return $finder->plugins(@_) };
  71         5463655  
  71         457  
32              
33             my $search_path_sub = sub {
34 0     0   0 my $self = shift;
35 0         0 my ($action,@paths) = @_;
36              
37 0 0 0     0 $finder->{'search_path'} = ["${package}::Plugin"] if ($action eq 'add' and not $finder->{'search_path'} );
38 0 0       0 push @{$finder->{'search_path'}}, @paths if ($action eq 'add');
  0         0  
39 0 0       0 $finder->{'search_path'} = \@paths if ($action eq 'new');
40 0         0 return $finder->{'search_path'};
41 50         183 };
42              
43             my $search_dirs_sub = sub {
44 0     0   0 my $self = shift;
45 0         0 my ($action,@paths) = @_;
46              
47 0 0 0     0 $finder->{'search_dirs'} = ["${package}::Plugin"] if ($action eq 'add' and not $finder->{'search_dirs'} );
48 0 0       0 push @{$finder->{'search_dirs'}}, @paths if ($action eq 'add');
  0         0  
49 0 0       0 $finder->{'search_dirs'} = \@paths if ($action eq 'new');
50 0         0 return $finder->{'search_dirs'};
51 50         167 };
52              
53             my $onlysub = sub {
54 3     3   1278 my ($self, $only) = @_;
55              
56 3 50       11 if (defined $only) {
57 3         9 $finder->{'only'} = $only;
58             };
59              
60 3         6 return $finder->{'only'};
61 50         148 };
62              
63             my $exceptsub = sub {
64 3     3   1603 my ($self, $except) = @_;
65              
66 3 50       12 if (defined $except) {
67 3         9 $finder->{'except'} = $except;
68             };
69              
70 3         7 return $finder->{'except'};
71 50         131 };
72              
73              
74 40     40   18968 no strict 'refs';
  40         77  
  40         1498  
75 40     40   152 no warnings qw(redefine prototype);
  40         76  
  40         7771  
76              
77 50         65 *{"$package\::$sub"} = $subroutine;
  50         271  
78 50         197 *{"$package\::search_path"} = $search_path_sub;
  50         268  
79 50         148 *{"$package\::search_dirs"} = $search_dirs_sub;
  50         146  
80 50         93 *{"$package\::only"} = $onlysub;
  50         145  
81 50         59 *{"$package\::except"} = $exceptsub;
  50         41731  
82              
83             }
84              
85             1;
86              
87             =pod
88              
89             =head1 NAME
90              
91             Module::Pluggable - automatically give your module the ability to have plugins
92              
93             =head1 SYNOPSIS
94              
95              
96             Simple use Module::Pluggable -
97              
98             package MyClass;
99             use Module::Pluggable;
100              
101              
102             and then later ...
103              
104             use MyClass;
105             my $mc = MyClass->new();
106             # returns the names of all plugins installed under MyClass::Plugin::*
107             my @plugins = $mc->plugins();
108              
109             =head1 EXAMPLE
110              
111             Why would you want to do this? Say you have something that wants to pass an
112             object to a number of different plugins in turn. For example you may
113             want to extract meta-data from every email you get sent and do something
114             with it. Plugins make sense here because then you can keep adding new
115             meta data parsers and all the logic and docs for each one will be
116             self contained and new handlers are easy to add without changing the
117             core code. For that, you might do something like ...
118              
119             package Email::Examiner;
120              
121             use strict;
122             use Email::Simple;
123             use Module::Pluggable require => 1;
124              
125             sub handle_email {
126             my $self = shift;
127             my $email = shift;
128              
129             foreach my $plugin ($self->plugins) {
130             $plugin->examine($email);
131             }
132              
133             return 1;
134             }
135              
136              
137              
138             .. and all the plugins will get a chance in turn to look at it.
139              
140             This can be trivially extended so that plugins could save the email
141             somewhere and then no other plugin should try and do that.
142             Simply have it so that the C<examine> method returns C<1> if
143             it has saved the email somewhere. You might also want to be paranoid
144             and check to see if the plugin has an C<examine> method.
145              
146             foreach my $plugin ($self->plugins) {
147             next unless $plugin->can('examine');
148             last if $plugin->examine($email);
149             }
150              
151              
152             And so on. The sky's the limit.
153              
154              
155             =head1 DESCRIPTION
156              
157             Provides a simple but, hopefully, extensible way of having 'plugins' for
158             your module. Obviously this isn't going to be the be all and end all of
159             solutions but it works for me.
160              
161             Essentially all it does is export a method into your namespace that
162             looks through a search path for .pm files and turn those into class names.
163              
164             Optionally it instantiates those classes for you.
165              
166             =head1 ADVANCED USAGE
167              
168             Alternatively, if you don't want to use 'plugins' as the method ...
169              
170             package MyClass;
171             use Module::Pluggable sub_name => 'foo';
172              
173              
174             and then later ...
175              
176             my @plugins = $mc->foo();
177              
178              
179             Or if you want to look in another namespace
180              
181             package MyClass;
182             use Module::Pluggable search_path => ['Acme::MyClass::Plugin', 'MyClass::Extend'];
183              
184             or directory
185              
186             use Module::Pluggable search_dirs => ['mylibs/Foo'];
187              
188              
189             Or if you want to instantiate each plugin rather than just return the name
190              
191             package MyClass;
192             use Module::Pluggable instantiate => 'new';
193              
194             and then
195              
196             # whatever is passed to 'plugins' will be passed
197             # to 'new' for each plugin
198             my @plugins = $mc->plugins(@options);
199              
200              
201             alternatively you can just require the module without instantiating it
202              
203             package MyClass;
204             use Module::Pluggable require => 1;
205              
206             since requiring automatically searches inner packages, which may not be desirable, you can turn this off
207              
208              
209             package MyClass;
210             use Module::Pluggable require => 1, inner => 0;
211              
212              
213             You can limit the plugins loaded using the except option, either as a string,
214             array ref or regex
215              
216             package MyClass;
217             use Module::Pluggable except => 'MyClass::Plugin::Foo';
218              
219             or
220              
221             package MyClass;
222             use Module::Pluggable except => ['MyClass::Plugin::Foo', 'MyClass::Plugin::Bar'];
223              
224             or
225              
226             package MyClass;
227             use Module::Pluggable except => qr/^MyClass::Plugin::(Foo|Bar)$/;
228              
229              
230             and similarly for only which will only load plugins which match.
231              
232             Remember you can use the module more than once
233              
234             package MyClass;
235             use Module::Pluggable search_path => 'MyClass::Filters', sub_name => 'filters';
236             use Module::Pluggable search_path => 'MyClass::Plugins', sub_name => 'plugins';
237              
238             and then later ...
239              
240             my @filters = $self->filters;
241             my @plugins = $self->plugins;
242              
243             =head1 PLUGIN SEARCHING
244              
245             Every time you call 'plugins' the whole search path is walked again. This allows
246             for dynamically loading plugins even at run time. However this can get expensive
247             and so if you don't expect to want to add new plugins at run time you could do
248              
249              
250             package Foo;
251             use strict;
252             use Module::Pluggable sub_name => '_plugins';
253              
254             our @PLUGINS;
255             sub plugins { @PLUGINS ||= shift->_plugins }
256             1;
257              
258             =head1 INNER PACKAGES
259              
260             If you have, for example, a file B<lib/Something/Plugin/Foo.pm> that
261             contains package definitions for both C<Something::Plugin::Foo> and
262             C<Something::Plugin::Bar> then as long as you either have either
263             the B<require> or B<instantiate> option set then we'll also find
264             C<Something::Plugin::Bar>. Nifty!
265              
266             =head1 OPTIONS
267              
268             You can pass a hash of options when importing this module.
269              
270             The options can be ...
271              
272             =head2 sub_name
273              
274             The name of the subroutine to create in your namespace.
275              
276             By default this is 'plugins'
277              
278             =head2 search_path
279              
280             An array ref of namespaces to look in.
281              
282             =head2 search_dirs
283              
284             An array ref of directories to look in before @INC.
285              
286             =head2 instantiate
287              
288             Call this method on the class. In general this will probably be 'new'
289             but it can be whatever you want. Whatever arguments are passed to 'plugins'
290             will be passed to the method.
291              
292             The default is 'undef' i.e just return the class name.
293              
294             =head2 require
295              
296             Just require the class, don't instantiate (overrides 'instantiate');
297              
298             =head2 inner
299              
300             If set to 0 will B<not> search inner packages.
301             If set to 1 will override C<require>.
302              
303             =head2 only
304              
305             Takes a string, array ref or regex describing the names of the only plugins to
306             return. Whilst this may seem perverse ... well, it is. But it also
307             makes sense. Trust me.
308              
309             =head2 except
310              
311             Similar to C<only> it takes a description of plugins to exclude
312             from returning. This is slightly less perverse.
313              
314             =head2 package
315              
316             This is for use by extension modules which build on C<Module::Pluggable>:
317             passing a C<package> option allows you to place the plugin method in a
318             different package other than your own.
319              
320             =head2 file_regex
321              
322             By default C<Module::Pluggable> only looks for I<.pm> files.
323              
324             By supplying a new C<file_regex> then you can change this behaviour e.g
325              
326             file_regex => qr/\.plugin$/
327              
328             =head2 include_editor_junk
329              
330             By default C<Module::Pluggable> ignores files that look like they were
331             left behind by editors. Currently this means files ending in F<~> (~),
332             the extensions F<.swp> or F<.swo>, or files beginning with F<.#>.
333              
334             Setting C<include_editor_junk> changes C<Module::Pluggable> so it does
335             not ignore any files it finds.
336              
337             =head2 follow_symlinks
338              
339             Whether, when searching directories, to follow symlinks.
340              
341             Defaults to 1 i.e do follow symlinks.
342              
343             =head2 min_depth, max_depth
344              
345             This will allow you to set what 'depth' of plugin will be allowed.
346              
347             So, for example, C<MyClass::Plugin::Foo> will have a depth of 3 and
348             C<MyClass::Plugin::Foo::Bar> will have a depth of 4 so to only get the former
349             (i.e C<MyClass::Plugin::Foo>) do
350              
351             package MyClass;
352             use Module::Pluggable max_depth => 3;
353              
354             and to only get the latter (i.e C<MyClass::Plugin::Foo::Bar>)
355              
356             package MyClass;
357             use Module::Pluggable min_depth => 4;
358              
359              
360             =head1 TRIGGERS
361              
362             Various triggers can also be passed in to the options.
363              
364             If any of these triggers return 0 then the plugin will not be returned.
365              
366             =head2 before_require <plugin>
367              
368             Gets passed the plugin name.
369              
370             If 0 is returned then this plugin will not be required either.
371              
372             =head2 on_require_error <plugin> <err>
373              
374             Gets called when there's an error on requiring the plugin.
375              
376             Gets passed the plugin name and the error.
377              
378             The default on_require_error handler is to C<carp> the error and return 0.
379              
380             =head2 after_require <plugin>
381              
382             Gets passed the plugin name.
383              
384             If 0 is returned then this plugin will be required but not instantiated or
385             returned as a plugin.
386              
387             =head2 before_instantiate <plugin>
388              
389             Gets passed the plugin name.
390              
391             If 0 is returned, then instantiation will not occur.
392              
393             =head2 on_instantiate_error <plugin> <err>
394              
395             Gets called when there's an error on instantiating the plugin.
396              
397             Gets passed the plugin name and the error.
398              
399             The default on_instantiate_error handler is to C<carp> the error and return 0.
400              
401             =head2 after_instantiate <plugin> <obj>
402              
403             Gets passed the plugin name and the object that was instentiated.
404             i.e. the return value of C<Plugin->new()>
405              
406             The return value must be <obj> and will be returned AS the plugin.
407             If the return value is not true, then nothing will be returned as a plugin.
408              
409             =head1 METHODs
410              
411             =head2 search_path
412              
413             The method C<search_path> is exported into you namespace as well.
414             You can call that at any time to change or replace the
415             search_path.
416              
417             $self->search_path( add => "New::Path" ); # add
418             $self->search_path( new => "New::Path" ); # replace
419              
420             =head1 BEHAVIOUR UNDER TEST ENVIRONMENT
421              
422             In order to make testing reliable we exclude anything not from blib if blib.pm is
423             in %INC.
424              
425             However if the module being tested used another module that itself used C<Module::Pluggable>
426             then the second module would fail. This was fixed by checking to see if the caller
427             had (^|/)blib/ in their filename.
428              
429             There's an argument that this is the wrong behaviour and that modules should explicitly
430             trigger this behaviour but that particular code has been around for 7 years now and I'm
431             reluctant to change the default behaviour.
432              
433             You can now (as of version 4.1) force Module::Pluggable to look outside blib in a test environment by doing either
434              
435             require Module::Pluggable;
436             $Module::Pluggable::FORCE_SEARCH_ALL_PATHS = 1;
437             import Module::Pluggable;
438              
439             or
440              
441             use Module::Pluggable force_search_all_paths => 1;
442              
443             =head1 @INC hooks and App::FatPacker
444              
445             If a module's @INC has a hook and that hook is an object which has a C<files()> method then we will
446             try and require those files too. See C<t/26inc_hook.t> for an example.
447              
448             This has allowed L<App::FatPacker> (as of version 0.10.0) to provide support for Module::Pluggable.
449              
450             This should also, theoretically, allow someone to modify PAR to do the same thing.
451              
452             =head1 Module::Require recommended
453              
454             Up until version 5.2 L<Module::Pluggable> used a string C<eval> to require plugins.
455              
456             This has now been changed to optionally use L<Module::Runtime> and it's C<require_module> method when
457             available and fall back to using a path based C<require> when not.
458              
459             It's recommended, but not required, that you install Module::Runtime.
460              
461             =head1 FUTURE PLANS
462              
463             This does everything I need and I can't really think of any other
464             features I want to add. Famous last words of course (not least
465             because we're up to version 5.0 at the time of writing).
466              
467             However suggestions (and patches) are always welcome.
468              
469             =head1 DEVELOPMENT
470              
471             The master repo for this module is at
472              
473             https://github.com/simonwistow/Module-Pluggable
474              
475             =head1 AUTHOR
476              
477             Simon Wistow <simon@thegestalt.org>
478              
479             =head1 COPYING
480              
481             Copyright, 2006 Simon Wistow
482              
483             Distributed under the same terms as Perl itself.
484              
485             =head1 BUGS
486              
487             None known.
488              
489             =head1 SEE ALSO
490              
491             L<File::Spec>, L<File::Find>, L<File::Basename>, L<Class::Factory::Util>, L<Module::Pluggable::Ordered>
492              
493             =cut
494              
495