line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Cake::Dispatcher;
|
2
|
8
|
|
|
8
|
|
45
|
use strict;
|
|
8
|
|
|
|
|
15
|
|
|
8
|
|
|
|
|
245
|
|
3
|
8
|
|
|
8
|
|
40
|
use warnings;
|
|
8
|
|
|
|
|
13
|
|
|
8
|
|
|
|
|
171
|
|
4
|
8
|
|
|
8
|
|
44
|
use Carp;
|
|
8
|
|
|
|
|
12
|
|
|
8
|
|
|
|
|
17839
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#============================================================================
|
7
|
|
|
|
|
|
|
# setup
|
8
|
|
|
|
|
|
|
#============================================================================
|
9
|
|
|
|
|
|
|
sub setup {
|
10
|
3
|
|
|
3
|
0
|
1918
|
my $self = shift;
|
11
|
|
|
|
|
|
|
#match current route
|
12
|
3
|
|
|
|
|
27
|
$self->match();
|
13
|
3
|
50
|
33
|
|
|
16
|
if (defined $self->controller and $self->controller->can('begin')){
|
14
|
0
|
|
|
|
|
0
|
$self->controller->begin($self);
|
15
|
|
|
|
|
|
|
}
|
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
##dispatch & excute
|
18
|
3
|
|
|
|
|
34
|
$self->dispatch();
|
19
|
3
|
50
|
33
|
|
|
16
|
if (defined $self->controller and $self->controller->can('end')){
|
20
|
0
|
|
|
|
|
0
|
$self->controller->end($self);
|
21
|
|
|
|
|
|
|
}
|
22
|
|
|
|
|
|
|
}
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#============================================================================
|
25
|
|
|
|
|
|
|
# dispatch: sending to the match route and execute
|
26
|
|
|
|
|
|
|
#============================================================================
|
27
|
|
|
|
|
|
|
sub dispatch {
|
28
|
3
|
|
|
3
|
0
|
8
|
my $self = shift;
|
29
|
3
|
|
|
|
|
5
|
my $args = shift;
|
30
|
|
|
|
|
|
|
|
31
|
3
|
|
|
|
|
22
|
my $actionclass = $self->ActionClass;
|
32
|
3
|
|
|
|
|
12
|
my $controller = $self->controller;
|
33
|
3
|
|
|
|
|
20
|
my $code = $self->code;
|
34
|
3
|
|
33
|
|
|
20
|
$args ||= $self->action->{args};
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
##running actions
|
37
|
3
|
50
|
|
|
|
11
|
if ($actionclass){
|
38
|
0
|
|
|
|
|
0
|
$actionclass->execute($controller,$self,$code,$args);
|
39
|
|
|
|
|
|
|
}
|
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
##running auto blocks
|
42
|
3
|
50
|
|
|
|
16
|
if (my $auto = $self->auto_chain->{ref $controller}){
|
43
|
0
|
|
|
|
|
0
|
my $line = $self->action->{line};
|
44
|
0
|
0
|
|
|
|
0
|
map { __PACKAGE__->execute($controller,$self,$_->{code},$args) if $_->{line} < $line } @{$auto};
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
45
|
|
|
|
|
|
|
}
|
46
|
|
|
|
|
|
|
|
47
|
3
|
|
|
|
|
21
|
__PACKAGE__->execute($controller,$self,$code,$args);
|
48
|
|
|
|
|
|
|
}
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
#============================================================================
|
52
|
|
|
|
|
|
|
# match : match current request path with routes
|
53
|
|
|
|
|
|
|
#============================================================================
|
54
|
|
|
|
|
|
|
##match sequence
|
55
|
|
|
|
|
|
|
## 1) direct paths - 2) paths with defined arguments - 3) chained - 4) regex
|
56
|
|
|
|
|
|
|
sub match {
|
57
|
3
|
|
|
3
|
0
|
13
|
my $self = shift;
|
58
|
3
|
|
33
|
|
|
37
|
my $path = shift || $self->path;
|
59
|
|
|
|
|
|
|
|
60
|
3
|
|
|
|
|
25
|
$self->log("Start Searching For $path path");
|
61
|
3
|
|
|
|
|
46
|
my $method = $self->method;
|
62
|
3
|
|
|
|
|
84
|
my $dispatch = $self->dispatcher;
|
63
|
3
|
|
|
|
|
6
|
my $match;
|
64
|
|
|
|
|
|
|
my @captures;
|
65
|
|
|
|
|
|
|
|
66
|
3
|
|
|
|
|
13
|
$self->log("1- Trying Direct Path Match");
|
67
|
|
|
|
|
|
|
|
68
|
3
|
0
|
33
|
|
|
31
|
if ($dispatch->{$path} && ($match = $dispatch->{$path}->{$method}) && !$dispatch->{$path}->{$method}->{chain}){
|
|
|
|
33
|
|
|
|
|
69
|
0
|
|
|
|
|
0
|
$self->addAction($match,"Direct Match");
|
70
|
0
|
|
|
|
|
0
|
return;
|
71
|
|
|
|
|
|
|
}
|
72
|
|
|
|
|
|
|
|
73
|
3
|
|
|
|
|
12
|
$self->log("2- Trying PAths With Arguments");
|
74
|
|
|
|
|
|
|
## nothing found in direct paths, lets try with args
|
75
|
3
|
|
|
|
|
16
|
(my $tpath = $path) =~ s/^\///;
|
76
|
3
|
|
|
|
|
14
|
my @args = split(/\//,$tpath);
|
77
|
3
|
|
|
|
|
84
|
my $i = $#args+1;
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
####get sequence of path - arg ... /first/second(1) /first(2) /(3)
|
80
|
3
|
|
|
|
|
6
|
my $t;
|
81
|
3
|
|
|
|
|
7
|
my @t = reverse (map { --$i; $t .= '/'.$_; $t.'('.$i.')' } @args);
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
82
|
3
|
|
|
|
|
13
|
push(@t,'/'.'('.($#args+1).')');
|
83
|
3
|
|
|
|
|
7
|
foreach my $this (@t){
|
84
|
3
|
0
|
33
|
|
|
15
|
if ($dispatch->{$this} && ($match = $dispatch->{$this}->{$method}) && !$dispatch->{$this}->{$method}->{chain}){
|
|
|
|
33
|
|
|
|
|
85
|
|
|
|
|
|
|
##capture
|
86
|
0
|
|
|
|
|
0
|
@captures = splice(@args,-$i,$i);
|
87
|
0
|
|
|
|
|
0
|
$self->addAction($match,"Path with arguments Match", @captures);
|
88
|
|
|
|
|
|
|
|
89
|
0
|
|
|
|
|
0
|
return;
|
90
|
|
|
|
|
|
|
}
|
91
|
3
|
|
|
|
|
8
|
$i++;
|
92
|
|
|
|
|
|
|
}
|
93
|
|
|
|
|
|
|
|
94
|
3
|
|
|
|
|
11
|
$self->log("3- Trying Chained Actions");
|
95
|
|
|
|
|
|
|
##lets try chains
|
96
|
|
|
|
|
|
|
####start with chain indexes and search for best match
|
97
|
3
|
50
|
|
|
|
21
|
if ( my $indexes = $dispatch->{chains_index} ){
|
98
|
|
|
|
|
|
|
|
99
|
0
|
|
|
|
|
0
|
local $self->{chain_action};
|
100
|
0
|
|
|
|
|
0
|
local $self->{chain_sequence};
|
101
|
|
|
|
|
|
|
|
102
|
0
|
|
|
|
|
0
|
for my $index (@{$indexes}){
|
|
0
|
|
|
|
|
0
|
|
103
|
|
|
|
|
|
|
#die Dumper $chain->{$index_path};
|
104
|
0
|
|
|
|
|
0
|
my $return = $self->_loop_chains($path,$index,1);
|
105
|
0
|
0
|
0
|
|
|
0
|
$return && $return == 1 ? next : last;
|
106
|
|
|
|
|
|
|
}
|
107
|
|
|
|
|
|
|
|
108
|
0
|
0
|
|
|
|
0
|
if ($self->{chain_action}){
|
109
|
0
|
|
|
|
|
0
|
my @chain = @{$self->{chain_action}};
|
|
0
|
|
|
|
|
0
|
|
110
|
0
|
|
|
|
|
0
|
my $lastaction = pop @chain;
|
111
|
|
|
|
|
|
|
|
112
|
0
|
|
|
|
|
0
|
for my $action (@chain){
|
113
|
0
|
|
|
|
|
0
|
$self->addAction($action,"Chained Match");
|
114
|
0
|
|
|
|
|
0
|
$self->dispatch();
|
115
|
|
|
|
|
|
|
}
|
116
|
|
|
|
|
|
|
|
117
|
0
|
|
|
|
|
0
|
$self->addAction($lastaction,"Last Chained Match");
|
118
|
0
|
|
|
|
|
0
|
return;
|
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
}
|
121
|
|
|
|
|
|
|
}
|
122
|
|
|
|
|
|
|
|
123
|
3
|
|
|
|
|
14
|
$self->log("4- Trying Regex Match");
|
124
|
3
|
100
|
|
|
|
13
|
if ($dispatch->{regex}){
|
125
|
1
|
|
|
|
|
3
|
my $oldstrength = '';
|
126
|
1
|
|
|
|
|
3
|
my $match;
|
127
|
|
|
|
|
|
|
|
128
|
1
|
|
|
|
|
2
|
foreach my $this (@{$dispatch->{regex}}){
|
|
1
|
|
|
|
|
3
|
|
129
|
1
|
50
|
|
|
|
8
|
if ($path =~ m/$this->{regex}/){
|
130
|
0
|
0
|
|
|
|
0
|
next if (!grep(/$method/,@{$this->{methods}}));
|
|
0
|
|
|
|
|
0
|
|
131
|
|
|
|
|
|
|
###select the strongest
|
132
|
0
|
|
|
|
|
0
|
my $localpath = $path; $localpath =~ s/$this->{regex}//;
|
|
0
|
|
|
|
|
0
|
|
133
|
0
|
|
|
|
|
0
|
my $strength = length $localpath;
|
134
|
|
|
|
|
|
|
|
135
|
0
|
0
|
0
|
|
|
0
|
if ($oldstrength eq '' || $strength < $oldstrength){
|
136
|
0
|
|
|
|
|
0
|
$match = $this;
|
137
|
|
|
|
|
|
|
}
|
138
|
|
|
|
|
|
|
|
139
|
0
|
|
|
|
|
0
|
$oldstrength = $strength;
|
140
|
|
|
|
|
|
|
#return;
|
141
|
|
|
|
|
|
|
}
|
142
|
|
|
|
|
|
|
}
|
143
|
|
|
|
|
|
|
|
144
|
1
|
50
|
|
|
|
4
|
if ($match){
|
145
|
|
|
|
|
|
|
##capture it
|
146
|
0
|
|
|
|
|
0
|
@captures = ($path =~ m/$match->{regex}$/);
|
147
|
0
|
|
|
|
|
0
|
@{$self->{capture}} = map { split('/',$_) } @captures;
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
148
|
0
|
|
|
|
|
0
|
$self->addAction($match->{action},"Regex Match",@{$self->{capture}});
|
|
0
|
|
|
|
|
0
|
|
149
|
0
|
|
|
|
|
0
|
return;
|
150
|
|
|
|
|
|
|
}
|
151
|
|
|
|
|
|
|
}
|
152
|
|
|
|
|
|
|
|
153
|
3
|
|
|
|
|
27
|
$self->log("There is no matching route for $path");
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
##does the app defined a sub to process not found locations?
|
156
|
3
|
50
|
|
|
|
10
|
if ($self->app->can('notfound')){
|
157
|
0
|
|
|
|
|
0
|
$self->app->notfound($self);
|
158
|
|
|
|
|
|
|
} else {
|
159
|
3
|
|
|
|
|
24
|
$self->status_code('404');
|
160
|
3
|
|
|
|
|
16
|
$self->body('Not Found');
|
161
|
|
|
|
|
|
|
}
|
162
|
|
|
|
|
|
|
}
|
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub _loop_chains {
|
165
|
0
|
|
|
0
|
|
0
|
my $self = shift;
|
166
|
0
|
|
|
|
|
0
|
my $path = shift;
|
167
|
0
|
|
|
|
|
0
|
my $dir = shift;
|
168
|
0
|
|
|
|
|
0
|
my $add_namespace = shift;
|
169
|
0
|
|
|
|
|
0
|
my $regex;
|
170
|
0
|
|
|
|
|
0
|
my $dispatch = $self->dispatcher;
|
171
|
0
|
|
|
|
|
0
|
my $chain = $dispatch->{chains};
|
172
|
0
|
|
|
|
|
0
|
my $thisChain = $chain->{$dir};
|
173
|
|
|
|
|
|
|
|
174
|
0
|
0
|
|
|
|
0
|
my $route = $add_namespace ?
|
175
|
|
|
|
|
|
|
$dir :
|
176
|
|
|
|
|
|
|
$thisChain->{dir};
|
177
|
|
|
|
|
|
|
|
178
|
0
|
|
|
|
|
0
|
my $args = $thisChain->{args};
|
179
|
|
|
|
|
|
|
|
180
|
0
|
0
|
|
|
|
0
|
if ($args){
|
181
|
0
|
|
|
|
|
0
|
$regex = qr{^$route/(.*?)$};
|
182
|
|
|
|
|
|
|
} else {
|
183
|
0
|
|
|
|
|
0
|
$regex = qr{^$route(.*?)$};
|
184
|
|
|
|
|
|
|
}
|
185
|
|
|
|
|
|
|
|
186
|
0
|
0
|
|
|
|
0
|
if (my ($newpath) = $path =~ m#$regex#){
|
187
|
0
|
0
|
|
|
|
0
|
my $match = $dispatch->{$thisChain->{path}}->{$self->method}
|
188
|
|
|
|
|
|
|
or return 1;
|
189
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
0
|
my @captures;
|
191
|
0
|
0
|
|
|
|
0
|
if ($args){
|
192
|
0
|
|
|
|
|
0
|
@captures = split '/',$newpath;
|
193
|
0
|
|
|
|
|
0
|
my @args = splice @captures,0,$args;
|
194
|
|
|
|
|
|
|
##re construct path
|
195
|
0
|
|
|
|
|
0
|
$newpath = '/'.join '/',@captures;
|
196
|
0
|
|
|
|
|
0
|
$match->{captures} = \@args;
|
197
|
|
|
|
|
|
|
}
|
198
|
|
|
|
|
|
|
|
199
|
0
|
|
|
|
|
0
|
my $next_chain = $thisChain->{chained_by};
|
200
|
0
|
0
|
0
|
|
|
0
|
return 1 if !$next_chain && $newpath && (!$args || $args && @captures);
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
201
|
0
|
|
|
|
|
0
|
push @{$self->{action_sequence}},$match;
|
|
0
|
|
|
|
|
0
|
|
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
###last action in the chain
|
204
|
0
|
0
|
0
|
|
|
0
|
$self->{chain_action} = $self->{action_sequence} and return
|
205
|
|
|
|
|
|
|
if !$next_chain;
|
206
|
|
|
|
|
|
|
|
207
|
0
|
|
|
|
|
0
|
for my $next (@{$next_chain}){
|
|
0
|
|
|
|
|
0
|
|
208
|
0
|
|
|
|
|
0
|
my $nextnamespace = $chain->{$next}->{namespace};
|
209
|
0
|
0
|
|
|
|
0
|
my $return = $self->_loop_chains($newpath,$next,$nextnamespace ne $thisChain->{namespace} ? 1 : 0);
|
210
|
|
|
|
|
|
|
|
211
|
0
|
0
|
0
|
|
|
0
|
if ($return && $return == 1){
|
212
|
0
|
|
|
|
|
0
|
next;
|
213
|
|
|
|
|
|
|
}
|
214
|
0
|
|
|
|
|
0
|
return;
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
|
217
|
0
|
|
|
|
|
0
|
@{$self->{action_sequence}} = splice @{$self->{action_sequence}},0,-1;
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
218
|
|
|
|
|
|
|
}
|
219
|
|
|
|
|
|
|
|
220
|
0
|
|
|
|
|
0
|
return 1;
|
221
|
|
|
|
|
|
|
}
|
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub addAction {
|
226
|
0
|
|
|
0
|
0
|
0
|
my $self = shift;
|
227
|
0
|
|
|
|
|
0
|
my $match = shift;
|
228
|
0
|
|
|
|
|
0
|
my $type = shift;
|
229
|
|
|
|
|
|
|
|
230
|
0
|
|
|
|
|
0
|
$self->log("PINGO: $type Found in " . $match->{class} . " at line " . $match->{line} );
|
231
|
|
|
|
|
|
|
|
232
|
0
|
|
|
|
|
0
|
my @captures;
|
233
|
|
|
|
|
|
|
|
234
|
0
|
0
|
|
|
|
0
|
if (@_) {
|
|
|
0
|
|
|
|
|
|
235
|
0
|
|
|
|
|
0
|
@captures = @_;
|
236
|
|
|
|
|
|
|
} elsif ($match->{captures}){
|
237
|
0
|
|
|
|
|
0
|
@captures = @{$match->{captures}};
|
|
0
|
|
|
|
|
0
|
|
238
|
|
|
|
|
|
|
}
|
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
$self->action({
|
241
|
0
|
|
0
|
|
|
0
|
ActionClass => $match->{ActionClass},
|
242
|
|
|
|
|
|
|
controller => bless($self->config->{$match->{class}} || {},$match->{class}),
|
243
|
|
|
|
|
|
|
code => _get_code($match->{class},$match->{code}),
|
244
|
|
|
|
|
|
|
line => $match->{line},
|
245
|
|
|
|
|
|
|
namespace => $match->{namespace},
|
246
|
|
|
|
|
|
|
args => \@captures
|
247
|
|
|
|
|
|
|
});
|
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
##log captures
|
250
|
0
|
0
|
0
|
|
|
0
|
if ($self->debug && @captures){
|
251
|
|
|
|
|
|
|
$self->log(sub {
|
252
|
0
|
|
|
0
|
|
0
|
my $msg = '';
|
253
|
0
|
|
|
|
|
0
|
$msg .= "=================\n";
|
254
|
0
|
|
|
|
|
0
|
$msg .= " Captured Args \n";
|
255
|
0
|
|
|
|
|
0
|
$msg .= "=================\n";
|
256
|
0
|
|
|
|
|
0
|
foreach my $arg (@captures){
|
257
|
0
|
|
|
|
|
0
|
$msg .= $arg."\n";
|
258
|
|
|
|
|
|
|
}
|
259
|
0
|
|
|
|
|
0
|
return $msg;
|
260
|
0
|
|
|
|
|
0
|
});
|
261
|
|
|
|
|
|
|
}
|
262
|
|
|
|
|
|
|
|
263
|
0
|
0
|
0
|
|
|
0
|
if (@captures && ref $match->{args} eq 'ARRAY'){
|
264
|
0
|
|
|
|
|
0
|
my $count = -1;
|
265
|
0
|
|
|
|
|
0
|
my %capture = map { ++$count; $_ => $captures[$count] } @{$match->{args}};
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
|
0
|
|
|
|
|
0
|
|
266
|
0
|
|
|
|
|
0
|
$self->action->{args} = \%capture;
|
267
|
|
|
|
|
|
|
}
|
268
|
|
|
|
|
|
|
|
269
|
0
|
|
|
|
|
0
|
return;
|
270
|
|
|
|
|
|
|
}
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
#============================================================================
|
273
|
|
|
|
|
|
|
# excute : execute current action
|
274
|
|
|
|
|
|
|
#============================================================================
|
275
|
|
|
|
|
|
|
sub execute {
|
276
|
3
|
|
|
3
|
0
|
10
|
shift;
|
277
|
3
|
|
|
|
|
8
|
my ($controller,$c,$method,$args) = @_;
|
278
|
3
|
50
|
|
|
|
15
|
if (ref $method eq 'CODE'){
|
279
|
0
|
0
|
|
|
|
|
my @args = ref $args eq 'HASH' ? values %{$args} : @{$args};
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
280
|
0
|
|
|
|
|
|
return $method->($controller,$c,@args);
|
281
|
|
|
|
|
|
|
}
|
282
|
|
|
|
|
|
|
}
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
#============================================================================
|
286
|
|
|
|
|
|
|
# private method
|
287
|
|
|
|
|
|
|
#============================================================================
|
288
|
|
|
|
|
|
|
sub _get_code {
|
289
|
0
|
|
|
0
|
|
|
my $controller = shift;
|
290
|
0
|
|
|
|
|
|
my $method = shift;
|
291
|
|
|
|
|
|
|
###convert method to CODE ref
|
292
|
0
|
0
|
|
|
|
|
if (ref $method ne 'CODE'){
|
293
|
0
|
|
|
|
|
|
$method = $controller.'::'.$method;
|
294
|
0
|
|
|
|
|
|
$method = \&$method;
|
295
|
|
|
|
|
|
|
}
|
296
|
0
|
|
|
|
|
|
return $method;
|
297
|
|
|
|
|
|
|
}
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
1;
|
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
__END__
|