-
-
24 Jan 2014 00:16:48 UTC
- Distribution: Plugin-Tiny
- Module version: 0.012
- Source (raw)
- Browse (raw)
- Changes
- Homepage
- How to Contribute
- Repository
- Issues (1)
- Testers (405 / 179 / 0)
- Kwalitee
Bus factor: 0- 81.17% Coverage
- License: perl_5
- Perl: v5.6.0
- Activity
24 month- Tools
- Download (17.15KB)
- MetaCPAN Explorer
- Permissions
- Subscribe to distribution
- Permalinks
- This version
- Latest version
and 1 contributors-
Maurice Mengel
- NAME
- VERSION
- SYNOPSIS
- DESCRIPTION
- ATTRIBUTES
- METHODS
- Recommendation: First Register Then Do Things
- Recommendation: Require a Plugin Role
- Plugin Bundles
- CONTRIBUTORS
- SEE ALSO
- AUTHOR
- COPYRIGHT AND LICENSE
NAME
Plugin::Tiny - A tiny plugin system for perl
VERSION
version 0.012
SYNOPSIS
#a complete 'Hello World' plugin package My::Plugin; use Moose; #optional; required is an object with new as constructor sub do_something { print "Hello World @_\n" } 1; #in your core use Plugin::Tiny; my $ps=Plugin::Tiny->new(); #plugin system #load My::Plugin: require, import, return My::Plugin->new(@_) my $plugin=$ps->register(plugin=>'My::Plugin'); #elsewhere in core: execute your plugin's methods my $plugin=$ps->get_plugin ($phase); $plugin->do_something(@args);
DESCRIPTION
Plugin::Tiny is minimalistic plugin system for perl. Each plugin is associated with a keyword (referred to as phase). A limitation of Plugin::Tiny is that each phase can have only one plugin.
Plugin::Tiny calls itself tiny because it doesn't attempt to solve all problems plugin systems could solve, because it consists of one smallish package, and it doesn't depend on a whole lot.
ATTRIBUTES
debug
Optional. Expects a boolean. Prints additional info to STDOUT.
prefix
Optional. You can have the prefix added to all plugin classes you register so save some typing and force plugins in your namespace:
#without prefix my $ps=Plugin::Tiny->new $ps->register(plugin='Your::App::Plugin::Example1'); $ps->register(plugin='Your::App::Plugin::Example2'); #with prefix my $ps=Plugin::Tiny->new ( prefix=>'Your::App::Plugin::' ); $ps->register(plugin='Example1'); $ps->register(plugin='Example2');
role
Optional. One or more roles that all plugins have to be able to do. Can be overwritten in
register
.role=>['Role::One', Role::Two] #either as ArrayRef role=>'Role::One' #or a scalar
METHODS
register
Registers a plugin, i.e. loads it and makes a new plugin object. Needs a plugin package name (plugin). Returns the newly created plugin object on success. Confesses on error. Remaining arguments are passed down to the plugin constructor:
$obj=$ps->register( plugin=>$plugin_class, #required args=>$more_args, #optional ); #returns result of $plugin_class->new (args=>$args);
N.B. Your plugin cannot use 'phase', 'plugin', 'role', 'force' as named arguments.
- plugin
-
The package name of the plugin. Required. Internally, the value of
prefix
is prepended to plugin. - phase
-
A phase asociated with the plugin. Optional. If not specified, Plugin::Tiny uses
default_phase
to determine the phase. - role
-
One or more roles that the plugin has to appply. Optional. Specify role=>undef to unset global roles. Currently, you can't mix global roles (defined via new) with local roles (defined via register).
role=>'Single::Role' #or role=>['Role::One','Role:Two'] role=>undef #unset global roles
- force
-
Force re-registration of a previously used phase. Optional.
Normally, Plugin::Tiny confesses if you try to register a phase that has previously been assigned. To overwrite this message make force true.
With force both plugins will be loaded (required, imported) and both return new objects for their respective plugin classes, but after the second plugin is made, the first one cannot be accessed anymore through get_plugin.
register_bundle
Registers a bundle of plugins in no particular order. A bundle is just a hashRef with info needed to issue a series of register calls (see
register
).Confesses if a plugin cannot be registered. Otherwise returns $bundle or undef.
sub bundle{ return { 'Store::One' => { phase => 'Store', role => undef, dbfile => $self->core->config->{main}{dbfile}, }, 'Scan::Monitor'=> { core => $self->core }, }; } $ps->register_bundle(bundle)
If you want to add or remove plugins, use hashref as usual:
undef $bundle->{$plugin}; #remove a plugin using package name $bundle->{'My::Plugin'}={phase=>'foo'}; #add another plugin
To facilitate inheritance of your plugins perhaps you put the hashref in a separate sub, so a child bundle can extend or remove plugins from yours.
get_plugin
Returns the plugin object associated with the phase. Returns undef on failure.
my $plugin=$ps->get_plugin ($phase);
default_phase
Makes a default phase from (the plugin's) class name. Expects a $plugin_class. Returns scalar or undef. If prefix is defined it use tail and removes all '::'. If no prefix is set default_phase returns the last element of the class name:
my $ps=Plugin-Tiny->new; $ps->default_phase(My::Plugin::Long::Example); #returns 'Example' $ps=Plugin-Tiny->new(prefix=>'My::Plugin::'); $ps->default_phase(My::Plugin::Long::Example); #returns 'LongExample'
get_class
Returns the plugin's class (package name). Expects plugin (not its package name). Croaks on error.
my $class=$ps->get_class ($plugin);
get_phase
returns the plugin's phase. Expects plugin (not its package name). Returns undef on failure. (You will not normally need get_phase, because typically your code knows the phases.)
my $phase=$ps->get_phase ($plugin);
Recommendation: First Register Then Do Things
Plugin::Tiny suggests that you first register (load) all your plugins before you actually do something with them. Internal
require
/use
of your packages is deferred until runtime. You can control the order in which plugins are loaded (in the order you callregister
), but if you manage to load all of them before you do anything, you can forget about order.You may know Plugin::Tiny's phases at compile time, but not which plugins will be loaded.
Recommendation: Require a Plugin Role
You may want to do a plugin role for all you plugins, e.g. to standardize the interface for your plugins. Perhaps to make sure that a specific sub is available in the plugin:
package My::Plugin; use Moose; with 'Your::App::Role::Plugin'; #...
Plugin Bundles
You can create bundles of plugins if you pass the plugin system to the (bundling) plugin. That way you can load multiple plugins for one phase. You still need unique phases for each plugin:
package My::Core; use Moose; has 'plugin_system'=>( is=>'ro', isa=>'Plugin::Tiny', default=>sub{Plugin::Tiny->new}, ); sub BUILD { $self->plugins->register( plugin=>'PluginBundle', phase=>'Bundle', plugin_system=>$self->plugins, ); } #elsewhere in core my $b=$self->plugin_system->get_plugin ('Bundle'); $b->start(); package PluginBundle; use Moose; has 'plugin_system'=>(is=>'ro', isa=>'Plugin::Tiny', required=>1); sub bundle { {Plugin::One=>{},Plugin::Two=>{}} } sub BUILD { #phase defaults to 'One' and 'Two': $self->plugins->register_bundle(bundle()); #more or less the same as: #$self->plugins->register (plugin=>'Plugin::One'); #$self->plugins->register (plugin=>'Plugin::Two'); } sub start { my $one=$self->plugins->get('One'); $one->do_something(@args); }
CONTRIBUTORS
Thanks to Toby Inkster for making Plugin::Tiny tinier.
SEE ALSO
Object::Pluggable Module::Pluggable MooX::Role::Pluggable MooseX::Object::Pluggable MooseX::Role::Pluggable
AUTHOR
Maurice Mengel <mauricemengel@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Maurice Mengel.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
Module Install Instructions
To install Plugin::Tiny, copy and paste the appropriate command in to your terminal.
cpanm Plugin::Tiny
perl -MCPAN -e shell install Plugin::Tiny
For more information on module installation, please visit the detailed CPAN module installation guide.