File Coverage

blib/lib/Sprocket/Session.pm
Criterion Covered Total %
statement 46 53 86.7
branch 16 24 66.6
condition 3 9 33.3
subroutine 6 6 100.0
pod n/a
total 71 92 77.1


line stmt bran cond sub pod time code
1             package Sprocket::Session;
2              
3 5     5   29 use warnings;
  5         9  
  5         190  
4 5     5   26 use strict;
  5         8  
  5         160  
5              
6              
7 5     5   25 use POE;
  5         8  
  5         38  
8 5     5   1533 use base qw(POE::Session);
  5         11  
  5         426  
9 5     5   33 use Errno qw(ENOSYS);
  5         26  
  5         3732  
10              
11             our $VERSION = '0.01';
12              
13             sub _invoke_state {
14 140     140   19303 my ($self, $source_session, $state, $etc, $file, $line, $fromstate) = @_;
15              
16             # Trace the state invocation if tracing is enabled.
17              
18 140 50       377 if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_TRACE}) {
19 0         0 POE::Kernel::_warn(
20             $POE::Kernel::poe_kernel->ID_session_to_id($self),
21             " -> $state (from $file at $line)\n"
22             );
23             }
24              
25             # The desired destination state doesn't exist in this session.
26             # Attempt to redirect the state transition to _default.
27              
28 140 100       384 unless (exists $self->[POE::Session::SE_STATES]->{$state}) {
29              
30             # There's no _default either; redirection's not happening today.
31             # Drop the state transition event on the floor, and optionally
32             # make some noise about it.
33              
34 44 50       114 unless (exists $self->[POE::Session::SE_STATES]->{+POE::Session::EN_DEFAULT}) {
35 0         0 $! = ENOSYS;
36 0 0 0     0 if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_DEFAULT} and $state ne POE::Session::EN_SIGNAL) {
37 0         0 my $loggable_self =
38             $POE::Kernel::poe_kernel->_data_alias_loggable($self);
39 0         0 POE::Kernel::_warn(
40             "a '$state' event was sent from $file at $line to $loggable_self ",
41             "but $loggable_self has neither a handler for it ",
42             "nor one for _default\n"
43             );
44             }
45 0         0 return undef;
46             }
47              
48             # If we get this far, then there's a _default state to redirect
49             # the transition to. Trace the redirection.
50              
51 44 50       90 if ($self->[POE::Session::SE_OPTIONS]->{+POE::Session::OPT_TRACE}) {
52 0         0 POE::Kernel::_warn(
53             $POE::Kernel::poe_kernel->ID_session_to_id($self),
54             " -> $state redirected to _default\n"
55             );
56             }
57              
58             # Transmogrify the original state transition into a corresponding
59             # _default invocation. ARG1 is copied from $etc so it can't be
60             # altered from a distance.
61              
62 44         128 $etc = [ $state, [@$etc] ];
63 44         72 $state = POE::Session::EN_DEFAULT;
64             }
65              
66             # If we get this far, then the state can be invoked. So invoke it
67             # already!
68              
69             # Package and object states are invoked this way.
70             SWITCH: {
71 140 100 66     129 if ( $state eq POE::Session::EN_DEFAULT
  140         617  
72             && ( $etc->[0] =~ m/^([^\|]+)\/(.*)/ ) ) {
73 44 50 33     201 last SWITCH unless ( $1 && $2 );
74            
75 44         84 my ( $heap, $nstate ) = ( $1, $2 );
76            
77             # does this state exist in this session?
78 44         89 my $om = $self->[POE::Session::SE_STATES]->{ $nstate };
79 44 100       89 unless( $om ) {
80 3         5 $om = $self->[POE::Session::SE_STATES]->{ POE::Session::EN_DEFAULT };
81             }
82 44 50       92 last SWITCH unless( $om );
83            
84             # does this object have this method?
85 44         74 my ( $object, $method ) = @$om;
86             #last SWITCH unless ( $object->can( $method ) );
87 44 50       274 if ( $object->{heap} = $object->{heaps}->{ $heap } ) {
88 44         57 my $ret;
89 44 100       74 if ( $method eq POE::Session::EN_DEFAULT ) {
90 3         4 $method = POE::Session::EN_DEFAULT;
91 3         15 $ret =
92             $object->$method( # package/object (implied)
93             $self, # session
94             $POE::Kernel::poe_kernel, # kernel
95             $object->{heap}, # heap
96             $nstate, # state
97             $source_session, # sender
98             undef, # unused #6
99             $file, # caller file name
100             $line, # caller file line
101             $fromstate, # caller state
102             $nstate, # original event
103 3         6 @{$etc->[1]} # args
104             );
105             } else {
106 41         246 $ret =
107             $object->$method( # package/object (implied)
108             $self, # session
109             $POE::Kernel::poe_kernel, # kernel
110             $object->{heap}, # heap
111             $nstate, # state
112             $source_session, # sender
113             undef, # unused #6
114             $file, # caller file name
115             $line, # caller file line
116             $fromstate, # caller state
117 41         74 @{$etc->[1]} # args
118             );
119             }
120 44         89 $object->{heap} = undef;
121            
122 44         169 return $ret;
123             }
124             }
125             }
126            
127             # Inline states are invoked this way.
128              
129 96 100       284 if (ref($self->[POE::Session::SE_STATES]->{$state}) eq 'CODE') {
130 33         142 return $self->[POE::Session::SE_STATES]->{$state}->
131             ( undef, # object
132             $self, # session
133             $POE::Kernel::poe_kernel, # kernel
134             $self->[POE::Session::SE_NAMESPACE], # heap
135             $state, # state
136             $source_session, # sender
137             undef, # unused #6
138             $file, # caller file name
139             $line, # caller file line
140             $fromstate, # caller state
141             @$etc # args
142             );
143             }
144              
145              
146 63         70 my ($object, $method) = @{$self->[POE::Session::SE_STATES]->{$state}};
  63         149  
147             return
148 63         361 $object->$method # package/object (implied)
149             ( $self, # session
150             $POE::Kernel::poe_kernel, # kernel
151             $self->[POE::Session::SE_NAMESPACE], # heap
152             $state, # state
153             $source_session, # sender
154             undef, # unused #6
155             $file, # caller file name
156             $line, # caller file line
157             $fromstate, # caller state
158             @$etc # args
159             );
160             }
161              
162             1;