1 package Module::Pluggable;
5 use Module::Pluggable::Object;
8 # Bob Porter: Looks like you've been missing a lot of work lately.
9 # Peter Gibbons: I wouldn't say I've been missing it, Bob!
18 my ($pkg, $file) = caller;
19 # the default name for the method is 'plugins'
20 my $sub = $opts{'sub_name'} || 'plugins';
22 my ($package) = $opts{'package'} || $pkg;
23 $opts{filename} = $file;
24 $opts{package} = $package;
27 my $finder = Module::Pluggable::Object->new(%opts);
28 my $subroutine = sub { my $self = shift; return $finder->plugins(@_) };
32 my ($action,@paths) = @_;
34 $finder->{'search_path'} = ["${package}::Plugin"] if ($action eq 'add' and not $finder->{'search_path'} );
35 push @{$finder->{'search_path'}}, @paths if ($action eq 'add');
36 $finder->{'search_path'} = \@paths if ($action eq 'new');
37 return $finder->{'search_path'};
42 my ($self, $only) = @_;
45 $finder->{'only'} = $only;
48 return $finder->{'only'};
52 my ($self, $except) = @_;
54 if (defined $except) {
55 $finder->{'except'} = $except;
58 return $finder->{'except'};
63 no warnings 'redefine';
64 *{"$package\::$sub"} = $subroutine;
65 *{"$package\::search_path"} = $searchsub;
66 *{"$package\::only"} = $onlysub;
67 *{"$package\::except"} = $exceptsub;
77 Module::Pluggable - automatically give your module the ability to have plugins
82 Simple use Module::Pluggable -
85 use Module::Pluggable;
91 my $mc = MyClass->new();
92 # returns the names of all plugins installed under MyClass::Plugin::*
93 my @plugins = $mc->plugins();
97 Why would you want to do this? Say you have something that wants to pass an
98 object to a number of different plugins in turn. For example you may
99 want to extract meta-data from every email you get sent and do something
100 with it. Plugins make sense here because then you can keep adding new
101 meta data parsers and all the logic and docs for each one will be
102 self contained and new handlers are easy to add without changing the
103 core code. For that, you might do something like ...
105 package Email::Examiner;
109 use Module::Pluggable require => 1;
115 foreach my $plugin ($self->plugins) {
116 $plugin->examine($email);
124 .. and all the plugins will get a chance in turn to look at it.
126 This can be trivally extended so that plugins could save the email
127 somewhere and then no other plugin should try and do that.
128 Simply have it so that the C<examine> method returns C<1> if
129 it has saved the email somewhere. You might also wnat to be paranoid
130 and check to see if the plugin has an C<examine> method.
132 foreach my $plugin ($self->plugins) {
133 next unless $plugin->can('examine');
134 last if $plugin->examine($email);
138 And so on. The sky's the limit.
143 Provides a simple but, hopefully, extensible way of having 'plugins' for
144 your module. Obviously this isn't going to be the be all and end all of
145 solutions but it works for me.
147 Essentially all it does is export a method into your namespace that
148 looks through a search path for .pm files and turn those into class names.
150 Optionally it instantiates those classes for you.
152 =head1 ADVANCED USAGE
155 Alternatively, if you don't want to use 'plugins' as the method ...
158 use Module::Pluggable sub_name => 'foo';
163 my @plugins = $mc->foo();
166 Or if you want to look in another namespace
169 use Module::Pluggable search_path => ['Acme::MyClass::Plugin', 'MyClass::Extend'];
173 use Module::Pluggable search_dirs => ['mylibs/Foo'];
176 Or if you want to instantiate each plugin rather than just return the name
179 use Module::Pluggable instantiate => 'new';
183 # whatever is passed to 'plugins' will be passed
184 # to 'new' for each plugin
185 my @plugins = $mc->plugins(@options);
188 alternatively you can just require the module without instantiating it
191 use Module::Pluggable require => 1;
193 since requiring automatically searches inner packages, which may not be desirable, you can turn this off
197 use Module::Pluggable require => 1, inner => 0;
200 You can limit the plugins loaded using the except option, either as a string,
204 use Module::Pluggable except => 'MyClass::Plugin::Foo';
209 use Module::Pluggable except => ['MyClass::Plugin::Foo', 'MyClass::Plugin::Bar'];
214 use Module::Pluggable except => qr/^MyClass::Plugin::(Foo|Bar)$/;
217 and similarly for only which will only load plugins which match.
219 Remember you can use the module more than once
222 use Module::Pluggable search_path => 'MyClass::Filters' sub_name => 'filters';
223 use Module::Pluggable search_path => 'MyClass::Plugins' sub_name => 'plugins';
227 my @filters = $self->filters;
228 my @plugins = $self->plugins;
230 =head1 INNER PACKAGES
232 If you have, for example, a file B<lib/Something/Plugin/Foo.pm> that
233 contains package definitions for both C<Something::Plugin::Foo> and
234 C<Something::Plugin::Bar> then as long as you either have either
235 the B<require> or B<instantiate> option set then we'll also find
236 C<Something::Plugin::Bar>. Nifty!
240 You can pass a hash of options when importing this module.
242 The options can be ...
246 The name of the subroutine to create in your namespace.
248 By default this is 'plugins'
252 An array ref of namespaces to look in.
256 An array ref of directorys to look in before @INC.
260 Call this method on the class. In general this will probably be 'new'
261 but it can be whatever you want. Whatever arguments are passed to 'plugins'
262 will be passed to the method.
264 The default is 'undef' i.e just return the class name.
268 Just require the class, don't instantiate (overrides 'instantiate');
272 If set to 0 will B<not> search inner packages.
273 If set to 1 will override C<require>.
277 Takes a string, array ref or regex describing the names of the only plugins to
278 return. Whilst this may seem perverse ... well, it is. But it also
279 makes sense. Trust me.
283 Similar to C<only> it takes a description of plugins to exclude
284 from returning. This is slightly less perverse.
288 This is for use by extension modules which build on C<Module::Pluggable>:
289 passing a C<package> option allows you to place the plugin method in a
290 different package other than your own.
294 By default C<Module::Pluggable> only looks for I<.pm> files.
296 By supplying a new C<file_regex> then you can change this behaviour e.g
298 file_regex => qr/\.plugin$/
306 The method C<search_path> is exported into you namespace as well.
307 You can call that at any time to change or replace the
310 $self->search_path( add => "New::Path" ); # add
311 $self->search_path( new => "New::Path" ); # replace
317 This does everything I need and I can't really think of any other
318 features I want to add. Famous last words of course
320 Recently tried fixed to find inner packages and to make it
321 'just work' with PAR but there are still some issues.
324 However suggestions (and patches) are welcome.
328 Simon Wistow <simon@thegestalt.org>
332 Copyright, 2006 Simon Wistow
334 Distributed under the same terms as Perl itself.
342 L<File::Spec>, L<File::Find>, L<File::Basename>, L<Class::Factory::Util>, L<Module::Pluggable::Ordered>