File Coverage

blib/lib/Evented/Object/EventFire.pm
Criterion Covered Total %
statement 42 63 66.6
branch 9 24 37.5
condition 4 13 30.7
subroutine 15 23 65.2
pod 16 17 94.1
total 86 140 61.4


line stmt bran cond sub pod time code
1             # Copyright (c) 2011-17, Mitchell Cooper
2             #
3             # Evented::Object: a simple yet featureful base class event framework.
4             # https://github.com/cooper/evented-object
5             #
6             package Evented::Object::EventFire; # leave this package name the same FOREVER.
7              
8 13     13   89 use warnings;
  13         26  
  13         424  
9 13     13   68 use strict;
  13         19  
  13         230  
10 13     13   54 use utf8;
  13         24  
  13         82  
11 13     13   462 use 5.010;
  13         48  
12              
13             ##########################
14             ### EVENT FIRE OBJECTS ###
15             ##########################
16              
17             our $VERSION = '5.67';
18             our $events = $Evented::Object::events;
19             our $props = $Evented::Object::props;
20              
21             # create a new fire object.
22             sub new {
23 13     13 0 85 my ($class, %opts) = @_;
24 13   50     215 $opts{callback_i} ||= 0;
25 13         191 return bless { $props => \%opts }, $class;
26             }
27              
28             # cancel all future callbacks once.
29             # if stopped already, returns the reason.
30             sub stop {
31 1     1 1 8 my ($fire, $reason) = @_;
32 1   50     19 $fire->{$props}{stop} ||= $reason || 'unspecified';
      33        
33             }
34              
35             # returns a true value if the given callback has been called.
36             # with no argument, returns number of callbacks called so far.
37             sub called {
38 0     0 1 0 my ($fire, $cb_name) = @_;
39              
40             # return the number of callbacks called.
41             # this includes the current callback.
42 0 0       0 if (!length $cb_name) {
43 0         0 my $called = scalar keys %{ $fire->{$props}{called} };
  0         0  
44 0 0       0 $called++ unless $fire->{$props}{complete};
45 0         0 return $called;
46             }
47              
48             # return whether the specified callback was called.
49 0 0       0 my $cb_id = $fire->_cb_id($cb_name) or return;
50 0         0 return $fire->{$props}{called}{$cb_id};
51             }
52              
53             # returns a true value if the given callback will be called soon.
54             # with no argument, returns number of callbacks pending.
55             sub pending {
56 2     2 1 14 my ($fire, $cb_name) = @_;
57 2         4 my $pending = $fire->{$props}{collection}{pending};
58              
59             # return number of callbacks remaining.
60 2 50       6 if (!length $cb_name) {
61 0         0 return scalar keys %$pending;
62             }
63              
64             # return whether the specified callback is pending.
65 2 50       5 my $cb_id = $fire->_cb_id($cb_name) or return;
66 2         6 return $pending->{$cb_id};
67             }
68              
69             # cancels a future callback once.
70             sub cancel {
71 1     1 1 17 my ($fire, $cb_name) = @_;
72              
73             # if there is no argument given, we will just
74             # treat this like a ->stop on the event.
75 1 50       5 length $cb_name or return $fire->stop;
76              
77             # cancel the callback.
78 1 50       5 my $cb_id = $fire->_cb_id($cb_name) or return;
79 1         4 delete $fire->{$props}{collection}{pending}{$cb_id};
80              
81 1         12 return 1;
82             }
83              
84             # returns the return value of the given callback.
85             # if it has not yet been called, this will return undef.
86             # if the return value has a possibility of being undef,
87             # the only way to be sure is to first test ->callback_called.
88             sub return_of {
89 0     0 1 0 my ($fire, $cb_name) = @_;
90 0 0       0 my $cb_id = $fire->_cb_id($cb_name) or return;
91 0         0 return $fire->{$props}{return}{$cb_id};
92             }
93              
94             # returns the callback that was last called.
95             sub last {
96 0     0 1 0 shift->{$props}{last_callback};
97             }
98              
99             # returns the return value of the last-called callback.
100             sub last_return {
101 0     0 1 0 shift->{$props}{last_return};
102             }
103              
104             # returns the callback that stopped the event.
105             sub stopper {
106 0     0 1 0 shift->{$props}{stopper};
107             }
108              
109             # returns the name of the event being fired.
110             # this isn't reliable afterward because it can differ within one fire.
111             sub event_name {
112 2     2 1 20 shift->{$props}{name};
113             }
114              
115             # returns the name of the callback being called.
116             sub callback_name {
117 6     6 1 34 shift->{$props}{callback_name};
118             }
119              
120             # returns the caller(1) value of ->fire_event().
121             sub caller {
122 0     0 1 0 @{ shift->{$props}{caller} };
  0         0  
123             }
124              
125             # returns the priority of the callback being called.
126             sub callback_priority {
127 0     0 1 0 shift->{$props}{callback_priority};
128             }
129              
130             # returns the value of the 'data' option when the callback was registered.
131             # if an argument is provided, it is used as the key to the data hash.
132             sub callback_data {
133 1     1 1 7 my $data = shift->{$props}{callback_data};
134 1         2 my $key_maybe = shift;
135 1 50       4 if (ref $data eq 'HASH') {
136 0 0       0 return $data->{$key_maybe} if defined $key_maybe;
137 0   0     0 return $data->{data} // $data;
138             }
139 1         4 return $data;
140             }
141              
142             # returns the value of the 'data' option on the ->fire().
143             # if an argument is provided, it is used as the key to the data hash.
144             sub data {
145 3     3 1 24 my $data = shift->{$props}{data};
146 3         7 my $key_maybe = shift;
147 3 100       10 if (ref $data eq 'HASH') {
148 2 100       8 return $data->{$key_maybe} if defined $key_maybe;
149 1   33     8 return $data->{data} // $data;
150             }
151 1         6 return $data;
152             }
153              
154             # returns the evented object.
155             sub object {
156 2     2 1 11 shift->{$props}{object};
157             }
158              
159             # returns the exception from 'safe' option, if any.
160             sub exception {
161 0     0 1 0 shift->{$props}{exception};
162             }
163              
164             # find a callback ID from a callback name.
165             sub _cb_id {
166 3     3   6 my ($fire, $cb_name) = @_;
167 3         13 return $fire->{$props}{callback_ids}{$cb_name};
168             }
169              
170             ###############
171             ### ALIASES ###
172             ###############
173              
174             sub object;
175              
176             BEGIN {
177 13     13   945 *eo = *object;
178             }
179              
180             1;
181              
182             =head1 NAME
183              
184             B - represents an L event fire.
185              
186             =head1 DESCRIPTION
187              
188             The fire object provides methods for fetching information related to the current
189             event fire. It also provides an interface for modifying the behavior of the
190             remaining callbacks.
191              
192             Fire objects are specific to the particular event fire, not the event itself.
193             If you fire the same event twice in a row, the fire object used the first time
194             will not be the same as the second time. Therefore, all modifications made by
195             the fire object's methods apply only to the callbacks remaining in this
196             particular fire. For example, C<< $fire->cancel($callback) >> will only cancel
197             the supplied callback once.
198              
199             =head1 METHODS
200              
201             =head2 $fire->object
202              
203             Returns the evented object.
204              
205             $fire->object->delete_event('myEvent');
206              
207             =head2 $fire->caller
208              
209             Returns the value of C from within the C<< ->fire() >> method.
210             This allows you to determine from where the event was fired.
211              
212             my $name = $fire->event_name;
213             my @caller = $fire->caller;
214             say "Package $caller[0] line $caller[2] called event $name";
215              
216             =head2 $fire->stop($reason)
217              
218             Cancels all remaining callbacks. This stops the rest of the event firing. After
219             a callback calls $fire->stop, the name of that callback is stored as
220             C<< $fire->stopper >>.
221              
222             If the event has already been stopped, this method returns the reason for which
223             the fire was stopped or "unspecified" if no reason was given.
224              
225             # ignore messages from trolls
226             if ($user eq 'noah') {
227             # user is a troll.
228             # stop further callbacks.
229             return $fire->stop;
230             }
231              
232             =over
233              
234             =item *
235              
236             B<$reason> - I, the reason for stopping the event fire.
237              
238             =back
239              
240             =head2 $fire->stopper
241              
242             Returns the callback which called C<< $fire->stop >>.
243              
244             if ($fire->stopper) {
245             say 'Fire was stopped by '.$fire->stopper;
246             }
247              
248             =head2 $fire->exception
249              
250             If the event was fired with the C<< safe >> option, it is possible that an
251             exception occurred in one (or more if C<< fail_continue >> enabled) callbacks.
252             This method returns the last exception that occurred or C<< undef >> if none
253             did.
254              
255             if (my $e = $fire->exception) {
256             say "Exception! $e";
257             }
258              
259             =head2 $fire->called($callback)
260              
261             If no argument is supplied, returns the number of callbacks called so far,
262             including the current one. If a callback argument is supplied, returns whether
263             that particular callback has been called.
264              
265             say $fire->called, 'callbacks have been called so far.';
266              
267             if ($fire->called('some.callback')) {
268             say 'some.callback has been called already.';
269             }
270              
271             B
272              
273             =over
274              
275             =item *
276              
277             B<$callback> - I, the callback being checked.
278              
279             =back
280              
281             =head2 $fire->pending($callback)
282              
283             If no argument is supplied, returns the number of callbacks pending to be
284             called, excluding the current one. If a callback argument is supplied, returns
285             whether that particular callback is pending for being called.
286              
287             say $fire->pending, ' callbacks are left.';
288              
289             if ($fire->pending('some.callback')) {
290             say 'some.callback will be called soon (unless it gets canceled)';
291             }
292              
293             B
294              
295             =over
296              
297             =item *
298              
299             B<$callback> - I, the callback being checked.
300              
301             =back
302              
303             =head2 $fire->cancel($callback)
304              
305             Cancels the supplied callback once.
306              
307             if ($user eq 'noah') {
308             # we don't love noah!
309             $fire->cancel('send.hearts');
310             }
311              
312             B
313              
314             =over
315              
316             =item *
317              
318             B<$callback> - callback to be cancelled.
319              
320             =back
321              
322             =head2 $fire->return_of($callback)
323              
324             Returns the return value of the supplied callback.
325              
326             if ($fire->return_of('my.callback')) {
327             say 'my.callback returned a true value';
328             }
329              
330             B
331              
332             =over
333              
334             =item *
335              
336             B<$callback> - desired callback.
337              
338             =back
339              
340             =head2 $fire->last
341              
342             Returns the most recent previous callback called.
343             This is also useful for determining which callback was the last to be called.
344              
345             say $fire->last, ' was called before this one.';
346              
347             my $fire = $eo->fire_event('myEvent');
348             say $fire->last, ' was the last callback called.';
349              
350             =head2 $fire->last_return
351              
352             Returns the last callback's return value.
353              
354             if ($fire->last_return) {
355             say 'the callback before this one returned a true value.';
356             }
357             else {
358             die 'the last callback returned a false value.';
359             }
360              
361             =head2 $fire->event_name
362              
363             Returns the name of the event.
364              
365             say 'the event being fired is ', $fire->event_name;
366              
367             =head2 $fire->callback_name
368              
369             Returns the name of the current callback.
370              
371             say 'the current callback being called is ', $fire->callback_name;
372              
373             =head2 $fire->callback_priority
374              
375             Returns the priority of the current callback.
376              
377             say 'the priority of the current callback is ', $fire->callback_priority;
378              
379             =head2 $fire->callback_data($key)
380              
381             Returns the data supplied to the callback when it was registered, if any. If the
382             data is a hash reference, an optional key parameter can specify a which value to
383             fetch.
384              
385             say 'my data is ', $fire->callback_data;
386             say 'my name is ', $fire->callback_data('name');
387              
388             B
389              
390             =over
391              
392             =item *
393              
394             B<$key> - I, a key to fetch a value if the data registered was a hash.
395              
396             =back
397              
398             =head2 $fire->data($key)
399              
400             Returns the data supplied to the collection when it was fired, if any. If the
401             data is a hash reference, an optional key parameter can specify a which value to
402             fetch.
403              
404             say 'fire data is ', $fire->data;
405             say 'fire time was ', $fire->data('time');
406              
407             B
408              
409             =over
410              
411             =item *
412              
413             B<$key> - I, a key to fetch a value if the data registered was a hash.
414              
415             =back
416              
417             =head1 AUTHOR
418              
419             L
420              
421             Copyright E 2011-2017. Released under New BSD license.
422              
423             Comments, complaints, and recommendations are accepted. Bugs may be reported on
424             L.