File Coverage

blib/lib/POE/Component/Pluggable.pm
Criterion Covered Total %
statement 15 152 9.8
branch 0 76 0.0
condition 0 30 0.0
subroutine 5 18 27.7
pod 8 8 100.0
total 28 284 9.8


line stmt bran cond sub pod time code
1             package POE::Component::Pluggable;
2              
3 2     2   50803 use strict;
  2         6  
  2         74  
4 2     2   12 use warnings;
  2         4  
  2         66  
5 2     2   21 use Carp;
  2         8  
  2         206  
6 2     2   1409 use POE::Component::Pluggable::Pipeline;
  2         5  
  2         73  
7 2     2   1278 use POE::Component::Pluggable::Constants qw(:ALL);
  2         5  
  2         4435  
8              
9             our $VERSION='1.26';
10              
11             sub _pluggable_init {
12 0     0     my ($self, %opts) = @_;
13            
14 0           $self->{'_pluggable_' . lc $_} = delete $opts{$_} for keys %opts;
15 0 0         $self->{_pluggable_reg_prefix} = 'plugin_' if !$self->{_pluggable_reg_prefix};
16 0 0         $self->{_pluggable_prefix} = 'pluggable_' if !$self->{_pluggable_prefix};
17            
18 0 0         if (ref $self->{_pluggable_types} eq 'ARRAY') {
    0          
19 0           $self->{_pluggable_types} = { map { $_ => $_ } @{ $self->{_pluggable_types} } };
  0            
  0            
20             }
21             elsif (ref $self->{_pluggable_types} ne 'HASH') {
22 0           croak "Argument 'types' must be supplied";
23             }
24            
25 0           return 1;
26             }
27              
28             sub _pluggable_destroy {
29 0     0     my ($self) = @_;
30 0           $self->plugin_del( $_ ) for keys %{ $self->plugin_list() };
  0            
31 0           return;
32             }
33              
34             sub _pluggable_event {
35 0     0     return;
36             }
37              
38             sub _pluggable_process {
39 0     0     my ($self, $type, $event, @args) = @_;
40              
41 0 0 0       if (!defined $type || !defined $event) {
42 0           carp 'Please supply an event type and name!';
43 0           return;
44             }
45              
46 0           $event = lc $event;
47 0           my $pipeline = $self->pipeline;
48 0           my $prefix = $self->{_pluggable_prefix};
49 0           $event =~ s/^\Q$prefix\E//;
50 0           my $sub = join '_', $self->{_pluggable_types}{$type}, $event;
51 0           my $return = PLUGIN_EAT_NONE;
52 0           my $self_ret = $return;
53              
54 0 0         if ($self->can($sub)) {
    0          
55 0           eval { $self_ret = $self->$sub( $self, @args ) };
  0            
56 0           $self->_handle_error($self, $sub, $self_ret);
57             }
58             elsif ( $self->can('_default') ) {
59 0           eval { $self_ret = $self->_default( $self, $sub, @args ) };
  0            
60 0           $self->_handle_error($self, '_default', $self_ret);
61             }
62              
63 0 0         return $return if $self_ret == PLUGIN_EAT_PLUGIN;
64 0 0         $return = PLUGIN_EAT_ALL if $self_ret == PLUGIN_EAT_CLIENT;
65 0 0         return PLUGIN_EAT_ALL if $self_ret == PLUGIN_EAT_ALL;
66              
67 0           for my $plugin (@{ $pipeline->{PIPELINE} }) {
  0            
68 0 0 0       if ($self eq $plugin
      0        
69             || !$pipeline->{HANDLES}{$plugin}{$type}{$event}
70             && !$pipeline->{HANDLES}{$plugin}{$type}{all}) {
71 0           next;
72             }
73              
74 0           my $ret = PLUGIN_EAT_NONE;
75              
76 0           my $alias = ($pipeline->get($plugin))[1];
77 0 0         if ($plugin->can($sub)) {
    0          
78 0           eval { $ret = $plugin->$sub($self,@args) };
  0            
79 0           $self->_handle_error($plugin, $sub, $ret, $alias);
80             }
81             elsif ( $plugin->can('_default') ) {
82 0           eval { $ret = $plugin->_default($self,$sub,@args) };
  0            
83 0           $self->_handle_error($plugin, '_default', $ret, $alias);
84             }
85              
86 0 0         $ret = PLUGIN_EAT_NONE unless defined $ret;
87 0 0         return $return if $ret == PLUGIN_EAT_PLUGIN;
88 0 0         $return = PLUGIN_EAT_ALL if $ret == PLUGIN_EAT_CLIENT;
89 0 0         return PLUGIN_EAT_ALL if $ret == PLUGIN_EAT_ALL;
90             }
91              
92 0           return $return;
93             }
94              
95             sub _handle_error {
96 0     0     my ($self, $object, $sub, $return, $source) = @_;
97 0 0         $source = defined $source ? "plugin '$source'" : 'self';
98              
99 0 0 0       if ($@) {
    0 0        
      0        
      0        
100 0           chomp $@;
101 0           my $error = "$sub call on $source failed: $@";
102 0 0         warn "$error\n" if $self->{_pluggable_debug};
103              
104 0 0         $self->_pluggable_event(
105             "$self->{_pluggable_prefix}plugin_error",
106             $error, ($object == $self ? ($object, $source) : ()),
107             );
108             }
109             elsif ( !defined $return ||
110             ($return != PLUGIN_EAT_NONE
111             && $return != PLUGIN_EAT_PLUGIN
112             && $return != PLUGIN_EAT_CLIENT
113             && $return != PLUGIN_EAT_ALL) ) {
114 0           my $error = "$sub call on $source did not return a valid EAT constant";
115 0 0         warn "$error\n" if $self->{_pluggable_debug};
116              
117 0 0         $self->_pluggable_event(
118             "$self->{_pluggable_prefix}plugin_error",
119             $error, ($object == $self ? ($object, $source) : ()),
120             );
121             }
122              
123 0           return;
124             }
125              
126             # accesses the plugin pipeline
127             sub pipeline {
128 0     0 1   my ($self) = @_;
129 0           eval { $self->{_PLUGINS}->isa('POE::Component::Pluggble::Pipeline') };
  0            
130 0 0         $self->{_PLUGINS} = POE::Component::Pluggable::Pipeline->new($self) if $@;
131 0           return $self->{_PLUGINS};
132             }
133              
134             # Adds a new plugin object
135             sub plugin_add {
136 0     0 1   my ($self, $name, $plugin) = @_;
137              
138 0 0 0       if (!defined $name || !defined $plugin) {
139 0           carp 'Please supply a name and the plugin object to be added!';
140 0           return;
141             }
142              
143 0           return $self->pipeline->push($name, $plugin);
144             }
145              
146             # Removes a plugin object
147             sub plugin_del {
148 0     0 1   my ($self, $name) = @_;
149              
150 0 0         if (!defined $name) {
151 0           carp 'Please supply a name/object for the plugin to be removed!';
152 0           return;
153             }
154              
155 0           my $return = scalar $self->pipeline->remove($name);
156 0           return $return;
157             }
158              
159             # Gets the plugin object
160             sub plugin_get {
161 0     0 1   my ($self, $name) = @_;
162              
163 0 0         if (!defined $name) {
164 0           carp 'Please supply a name/object for the plugin to be removed!';
165 0           return;
166             }
167              
168 0           return scalar $self->pipeline->get($name);
169             }
170              
171             # Lists loaded plugins
172             sub plugin_list {
173 0     0 1   my ($self) = @_;
174 0           my $pipeline = $self->pipeline;
175            
176 0           my %return = map {$pipeline->{PLUGS}{$_} => $_} @{ $pipeline->{PIPELINE} };
  0            
  0            
177 0           return \%return;
178             }
179              
180             # Lists loaded plugins in order!
181             sub plugin_order {
182 0     0 1   my ($self) = @_;
183 0           return $self->pipeline->{PIPELINE};
184             }
185              
186             sub plugin_register {
187 0     0 1   my ($self, $plugin, $type, @events) = @_;
188 0           my $pipeline = $self->pipeline;
189              
190 0 0         if (!grep { $_ eq $type } keys %{ $self->{_pluggable_types} }) {
  0            
  0            
191 0           carp "The event type '$type' is not supported!";
192 0           return;
193             }
194              
195 0 0         if (!defined $plugin) {
196 0           carp 'Please supply the plugin object to register events for!';
197 0           return;
198             }
199              
200 0 0         if (!@events) {
201 0           carp 'Please supply at least one event to register!';
202 0           return;
203             }
204              
205 0           for my $ev (@events) {
206 0 0 0       if (ref $ev and ref $ev eq 'ARRAY') {
207 0           $pipeline->{HANDLES}{$plugin}{$type}{lc $_} = 1 for @$ev;
208             }
209             else {
210 0           $pipeline->{HANDLES}{$plugin}{$type}{lc $ev} = 1;
211             }
212             }
213              
214 0           return 1;
215             }
216              
217             sub plugin_unregister {
218 0     0 1   my ($self, $plugin, $type, @events) = @_;
219 0           my $pipeline = $self->pipeline;
220              
221 0 0         if (!grep { $_ eq $type } keys %{ $self->{_pluggable_types} }) {
  0            
  0            
222 0           carp "The event type '$type' is not supported!";
223 0           return;
224             }
225              
226 0 0         if (!defined $plugin) {
227 0           carp 'Please supply the plugin object to register!';
228 0           return;
229             }
230              
231 0 0         if (!@events) {
232 0           carp 'Please supply at least one event to unregister!';
233 0           return;
234             }
235              
236 0           for my $ev (@events) {
237 0 0 0       if (ref $ev and ref $ev eq "ARRAY") {
238 0           for my $e (map { lc } @$ev) {
  0            
239 0 0         if (!delete $pipeline->{HANDLES}{$plugin}{$type}{$e}) {
240 0           carp "The event '$e' does not exist!";
241 0           next;
242             }
243             }
244             }
245             else {
246 0           $ev = lc $ev;
247 0 0         if (!delete $pipeline->{HANDLES}{$plugin}{$type}{$ev}) {
248 0           carp "The event '$ev' does not exist!";
249 0           next;
250             }
251             }
252             }
253              
254 0           return 1;
255             }
256              
257             1;
258             __END__