File Coverage

blib/lib/mop/internals/observable.pm
Criterion Covered Total %
statement 52 52 100.0
branch 11 14 78.5
condition 2 3 66.6
subroutine 9 9 100.0
pod 0 4 0.0
total 74 82 90.2


line stmt bran cond sub pod time code
1             package mop::internals::observable;
2              
3 143     143   94614 use v5.16;
  143         483  
  143         7117  
4 143     143   724 use warnings;
  143         395  
  143         11571  
5              
6 143     143   1267 use Scalar::Util qw[ refaddr ];
  143         277  
  143         12308  
7              
8 143     143   1048 use mop::internals::util;
  143         278  
  143         100490  
9              
10             our $VERSION = '0.03';
11             our $AUTHORITY = 'cpan:STEVAN';
12              
13             mop::internals::util::init_attribute_storage(my %callbacks);
14              
15             sub bind {
16 33     33 0 21864 my ($self, $event_name, $callback) = @_;
17 33 100       219 $callbacks{ $self } = \{}
18             unless $callbacks{ $self };
19 28         130 ${$callbacks{ $self }}->{ $event_name } = []
  33         164  
20 33 100       62 unless exists ${$callbacks{ $self }}->{ $event_name };
21 33         54 push @{ ${$callbacks{ $self }}->{ $event_name } } => $callback;
  33         47  
  33         112  
22 33         115 $self;
23             }
24              
25             sub unbind {
26 4     4 0 28 my ($self, $event_name, $callback) = @_;
27 4 50       16 return $self unless $callbacks{ $self };
28 4 50       7 return $self unless ${$callbacks{ $self }}->{ $event_name };
  4         19  
29 4         4 @{ ${$callbacks{ $self }}->{ $event_name } } = grep {
  4         16  
  4         25  
30 4         13 refaddr($_) != refaddr($callback)
31 4         8 } @{ ${$callbacks{ $self }}->{ $event_name } };
  4         5  
32 4         10 $self;
33             }
34              
35             sub fire {
36 19261     19261 0 49812 my ($self, $event_name, @args) = @_;
37 19261 100       70963 return $self unless $callbacks{ $self };
38 178 100       195 return $self unless ${$callbacks{ $self }}->{ $event_name };
  178         821  
39 55         87 $self->$_( @args ) foreach @{ ${$callbacks{ $self }}->{ $event_name } };
  55         71  
  55         381  
40 55         192 return $self;
41             }
42              
43             sub has_events {
44 773     773 0 1174 my $self = shift;
45 773   66     5916 return $callbacks{ $self } && ${ $callbacks{ $self } } && !!%{ ${ $callbacks{ $self } } };
46             }
47              
48             sub __INIT_METACLASS__ {
49 143     143   320 state $METACLASS;
50 143 50       1069 return $METACLASS if defined $METACLASS;
51 143         2492 require mop::role;
52 143         874 $METACLASS = mop::role->new(
53             name => 'mop::observable',
54             version => $VERSION,
55             authority => $AUTHORITY
56             );
57              
58 143         826 $METACLASS->add_attribute(mop::attribute->new(
59             name => '$!callbacks',
60             storage => \%callbacks
61             ));
62              
63 143         811 $METACLASS->add_method( mop::method->new( name => 'bind', body => \&bind ) );
64 143         794 $METACLASS->add_method( mop::method->new( name => 'unbind', body => \&unbind ) );
65 143         836 $METACLASS->add_method( mop::method->new( name => 'fire', body => \&fire ) );
66              
67 143         798 $METACLASS->add_method( mop::method->new( name => 'has_events', body => \&has_events ) );
68              
69 143         1141 $METACLASS;
70             }
71              
72             1;
73              
74             __END__