File Coverage

blib/lib/Plugin/Tiny.pm
Criterion Covered Total %
statement 70 81 86.4
branch 26 40 65.0
condition 9 12 75.0
subroutine 14 15 93.3
pod 6 6 100.0
total 125 154 81.1


line stmt bran cond sub pod time code
1             #ABSTRACT: A tiny plugin system for perl
2             package Plugin::Tiny;
3             $Plugin::Tiny::VERSION = '0.012';
4 1     1   25208 use strict;
  1         2  
  1         44  
5 1     1   4 use warnings;
  1         2  
  1         27  
6 1     1   4 use Carp 'confess';
  1         2  
  1         70  
7 1     1   928 use Module::Runtime 'use_package_optimistically';
  1         1869  
  1         7  
8 1     1   54 use Scalar::Util 'blessed';
  1         2  
  1         110  
9 1     1   2038941 use Moo;
  1         1649906  
  1         9  
10 1     1   3795 use MooX::Types::MooseLike::Base qw(Bool Str HashRef ArrayRef Object);
  1         11037  
  1         224  
11 1     1   1118 use namespace::clean;
  1         18719  
  1         9  
12              
13             #use Data::Dumper;
14              
15              
16             has '_registry' => ( #href with phases and plugin objects
17             is => 'ro',
18             isa => HashRef[Object],
19             default => sub { {} },
20             init_arg => undef,
21             );
22              
23              
24             has 'debug' => (is => 'ro', isa => Bool, default => sub {0});
25              
26              
27             has 'prefix' => (is => 'ro', isa => Str);
28              
29              
30             has 'role' => (is => 'ro', isa => ArrayRef[Str]);
31              
32              
33             #
34             # METHODS
35             #
36              
37              
38             #Re-write init argument 'role' as arrayref if not yet arrayref.
39             around BUILDARGS => sub {
40             my $orig = shift;
41             my $class = shift;
42             my %args = @_;
43              
44             if ($args{role} && ref ($args{role}) ne 'ARRAY'){
45             $args{role}=[$args{role}];
46             }
47             return $class->$orig(%args);
48             };
49              
50              
51              
52             sub register {
53 10     10 1 3997 my $self = shift;
54 10         37 my %args = @_;
55 10 50       35 my $plugin = delete $args{plugin} or confess "Need plugin";
56              
57 10 50       34 if ($self->prefix) {
58 0         0 $plugin = $self->prefix . $plugin;
59             }
60 10 100       30 my $phase =
61             $args{phase}
62             ? delete $args{phase}
63             : $self->default_phase($plugin);
64              
65 10 100 100     49 if (defined $self->{_registry}{$phase} && !$args{force}) {
66 3         481 confess <
67             There is already a plugin registered under this phase. If you really want to
68             overwrite the current plugin with a new one, use 'force=>1'.
69             END
70             }
71              
72 7 100       24 use_package_optimistically($plugin)->can('new') or confess "Can't load '$plugin'";
73              
74 6 50       12784 my $roles = $self->role if $self->role; #default role
75 6 100       19 $roles = delete $args{role} if exists $args{role};
76              
77             #rewrite scalar as arrayref
78 6 100 100     24 $roles = [$roles] if ($roles && !ref $roles);
79              
80 6 100 66     21 if ($roles && ref $roles eq 'ARRAY') {
81 2         4 foreach my $role (@{$roles}) {
  2         3  
82 3 50       39 if ($plugin->DOES($role)) {
83 3         45 $self->_debug("Plugin '$plugin' does role '$role'");
84             }
85             else {
86 0         0 confess qq(Plugin '$plugin' doesn't do role '$role');
87             }
88             }
89             }
90              
91 6   33     105 $self->{_registry}{$phase} = $plugin->new(%args)
92             || confess "Can't make $plugin";
93 6         1659 $self->_debug("register $plugin [$phase]");
94 6         31 return $self->{_registry}{$phase};
95             }
96              
97              
98              
99             sub register_bundle {
100 0     0 1 0 my $self = shift;
101 0 0       0 my $bundle = shift or return;
102 0         0 foreach my $plugin (keys %{$bundle}) {
  0         0  
103 0         0 my %args = %{$bundle->{$plugin}};
  0         0  
104 0         0 $args{plugin} = $plugin;
105 0 0       0 $self->register(%args) or confess "Registering $plugin failed";
106             }
107 0         0 return $bundle;
108             }
109              
110              
111              
112             sub get_plugin {
113 2     2 1 10 my $self = shift;
114 2 50       8 my $phase = shift or return;
115 2 50       7 return if (!$self->{_registry}{$phase});
116 2         13 return $self->{_registry}{$phase};
117             }
118              
119              
120              
121             sub default_phase {
122 5     5 1 114 my $self = shift;
123 5 50       12 my $plugin = shift or return; #a class name
124              
125 5 100       17 if ($self->prefix) {
126 1         3 my $phase = $plugin;
127 1         3 my $prefix = $self->prefix;
128 1         23 $phase =~ s/$prefix//;
129 1         3 $phase =~ s/:://g;
130 1         7 return $phase;
131             }
132             else {
133 4         17 my @parts = split('::', $plugin);
134 4         13 return $parts[-1];
135             }
136             }
137              
138              
139             #Todo: Not sure what it returns on error.
140              
141              
142             sub get_class {
143 3     3 1 5 my $self = shift;
144 3 50       11 my $plugin = shift or return;
145 3         13 blessed($plugin);
146             }
147              
148              
149              
150             sub get_phase {
151 2     2 1 385 my $self = shift;
152 2 50       7 my $plugin = shift or return;
153 2         6 blessed($plugin);
154 2         4 my $current_class = $self->get_class($plugin);
155              
156             #print 'z:['.join(' ', keys %{$self->{_registry}})."]\n";
157 2         3 foreach my $phase (keys %{$self->{_registry}}) {
  2         6  
158 3         12 my $registered_class = blessed($self->{_registry}{$phase});
159 3         484 print "[$phase] $registered_class === $current_class\n";
160 3 100       25 return $phase if ("$registered_class" eq "$current_class");
161             }
162              
163             }
164              
165              
166             #
167             # PRIVATE
168             #
169              
170             sub _debug {
171 9 50   9   32 print $_[1] . "\n" if $_[0]->debug;
172             }
173              
174             1;
175              
176             __END__