File Coverage

blib/lib/MooX/Role/EventEmitter.pm
Criterion Covered Total %
statement 20 73 27.4
branch 0 8 0.0
condition 0 2 0.0
subroutine 7 16 43.7
pod 6 6 100.0
total 33 105 31.4


line stmt bran cond sub pod time code
1             package MooX::Role::EventEmitter;
2 1     1   962 use Moo::Role 2;
  1         14529  
  1         6  
3 1     1   343 use 5.020; # signatures
  1         3  
4 1     1   5 use feature 'signatures';
  1         2  
  1         89  
5 1     1   6 no warnings 'experimental::signatures';
  1         2  
  1         38  
6 1     1   465 use Try::Tiny;
  1         1103  
  1         59  
7 1     1   7 use Carp 'croak';
  1         3  
  1         32  
8              
9 1     1   5 use Scalar::Util 'weaken';
  1         1  
  1         612  
10             # Basically modeled after Mojo::EventEmitter
11              
12             our $VERSION = '0.03';
13              
14             =head1 NAME
15              
16             MooX::Role::EventEmitter - Event emitter role
17              
18             =head1 SYNOPSIS
19              
20             package My::Thing;
21             use 5.020;
22             use feature 'signatures';
23             no warnings 'experimental::signatures';
24             use Moo 2;
25             with 'MooX::Role::EventEmitter';
26              
27             sub event_received( $self, $ev ) {
28             $self->emit( myevent => $ev );
29             }
30              
31             # ... later, in your client
32              
33             package main;
34             my $foo = My::Thing->new();
35             $foo->on( myevent => sub( $ev ) {
36             say "I receivend an event";
37             });
38              
39             =cut
40              
41             has 'events' => (
42             is => 'lazy',
43             default => sub { +{} },
44             );
45              
46             =head1 METHODS
47              
48             =head2 C<< $obj->emit $name, @args >>
49              
50             Emit an event
51              
52             =cut
53              
54 0     0 1   sub emit($self, $name, @args) {
  0            
  0            
  0            
  0            
55 0 0         if (my $s = $self->events->{$name}) {
56             #warn "-- Emit $name in @{[blessed $self]} (@{[scalar @$s]})\n" if DEBUG;
57 0           for my $cb (@$s) {
58              
59 0     0     try { $self->$cb(@args) }
60 0     0     catch { warn "on $name callback died: $_" }
61 0           }
62             }
63             #else {
64             # warn "-- Emit $name in @{[blessed $self]} (0)\n" if DEBUG;
65             # die "@{[blessed $self]}: $_[0]" if $name eq 'error';
66             #}
67 0           return $self;
68             }
69              
70             =head2 C<< $obj->has_subscribers $name >>
71              
72             Check if an event has subscribers.
73              
74             =cut
75              
76 0     0 1   sub has_subscribers( $self, $name ) {
  0            
  0            
  0            
77 0           !!$self->events->{$name}
78             }
79              
80             =head2 C<< $obj->on $name, @args >>
81              
82             my $cb = $obj->on( myevent => sub { ... });
83              
84             Subscribe to an event.
85              
86             =cut
87              
88 0     0 1   sub on($self, $name, $cb) {
  0            
  0            
  0            
  0            
89 0 0         push @{$self->events->{$name}}, $cb and return $cb
  0            
90             }
91              
92             =head2 C<< $obj->once $name, @args >>
93              
94             my $cb = $obj->once( myevent => sub { ... });
95              
96             Subscribe to an event for just one event.
97              
98             =cut
99              
100 0     0 1   sub once($self, $name, $cb) {
  0            
  0            
  0            
  0            
101 0           weaken $self;
102             my $wrapper = sub {
103 0     0     $self->unsubscribe($name => __SUB__);
104 0           goto &$cb;
105 0           };
106 0           $self->on($name => $wrapper);
107              
108 0           return $wrapper;
109             }
110              
111             =head2 C<< $obj->subscribers( $name ) >>
112              
113             my $s = $obj->subscribers( 'myevent' );
114              
115             Return an arrayref of the subscribers for an event.
116              
117             =cut
118              
119 0     0 1   sub subscribers($self,$name) {
  0            
  0            
  0            
120 0   0       $self->events->{ $name } //= []
121             }
122              
123             =head2 C<< $obj->unsubscribe( $name => $cb ) >>
124              
125             $obj->unsubscribe('myevent', $cb); # a specific callback
126             $obj->unsubscribe('myevent'); # all callbacks
127              
128             Unsubscribe from event.
129              
130             =cut
131              
132 0     0 1   sub unsubscribe($self, $name, $cb=undef) {
  0            
  0            
  0            
  0            
133             # One
134 0 0         if ($cb) {
135 0           @{$self->events->{$name}} = grep { $cb ne $_ } @{$self->events->{$name}};
  0            
  0            
  0            
136 0 0         delete $self->events->{$name} unless @{$self->events->{$name}};
  0            
137             } else {
138 0           delete $self->events->{$name}
139             }
140              
141 0           return $self;
142             }
143              
144             1;
145              
146             =head1 SEE ALSO
147              
148             L - the module this API is based on
149              
150             =cut