File Coverage

blib/lib/Dancer/Route/Registry.pm
Criterion Covered Total %
statement 79 83 95.1
branch 20 24 83.3
condition 7 8 87.5
subroutine 14 15 93.3
pod 1 8 12.5
total 121 138 87.6


line stmt bran cond sub pod time code
1             package Dancer::Route::Registry;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             # ABSTRACT: Route registry for Dancer
4             $Dancer::Route::Registry::VERSION = '1.3514_04'; # TRIAL
5             $Dancer::Route::Registry::VERSION = '1.351404';
6 171     171   1437 use strict;
  171         311  
  171         4337  
7 171     171   758 use warnings;
  171         287  
  171         3679  
8 171     171   698 use Carp;
  171         1321  
  171         8091  
9 171     171   61475 use Dancer::Route;
  171         507  
  171         5690  
10 171     171   1131 use base 'Dancer::Object';
  171         358  
  171         17467  
11 171     171   1247 use Dancer::Logger;
  171         527  
  171         4837  
12 171     171   845 use Dancer::Exception qw(:all);
  171         386  
  171         133870  
13              
14             Dancer::Route::Registry->attributes(qw( id ));
15              
16             my $id = 1;
17              
18             sub init {
19 115     115 1 314 my ($self) = @_;
20              
21 115 50       1962 unless (defined $self->{id}) {
22 115         506 $self->id($id++);
23             }
24              
25             # Routes are stored here. Keys are route methods, and values are
26             # arrays of routes. Routes with options are stored in the
27             # beginning of the array while routes without options are stored
28             # at the end.
29 115         335 $self->{routes} = {};
30              
31             # Keep track of the border between routes with and without
32             # options, so that routes with options can be easily inserted into
33             # its routes array.
34 115         283 $self->{routes_border} = {};
35              
36 115         244 return $self;
37             }
38              
39             sub is_empty {
40 2     2 0 4 my ($self) = @_;
41 2         2 for my $method ( keys %{ $self->routes } ) {
  2         5  
42 1 50       2 return 0 if $self->routes($method);
43             }
44 1         4 return 1;
45             }
46              
47             # replace any ':foo' by '(.+)' and stores all the named
48             # matches defined in $REG->{route_params}{$route}
49             sub routes {
50 3476     3476 0 5179 my ($self, $method) = @_;
51              
52 3476 100       5306 if ($method) {
53 3474         4812 my $route = $self->{routes}{$method};
54 3474 100       9223 return $route ? $route : [];
55             }
56             else {
57 2         7 return $self->{routes};
58             }
59             }
60              
61             sub add_route {
62 1442     1442 0 2194 my ($self, $route) = @_;
63 1442   100     2721 $self->{routes}{$route->method} ||= [];
64 1442         1978 my @registered = @{$self->routes($route->method)};
  1442         2732  
65 1442         2256 my $last = $registered[-1];
66 1442 100       4018 $route->set_previous($last) if defined $last;
67              
68             # Routes are stored in the order they are declared. However,
69             # routes with options (such as ajax routes) are stored before
70             # routes without options. This way, we can have the following
71             # routes:
72             #
73             # get '/' => sub {};
74             # get qr{.*} => sub {};
75             # ajax '/' => sub {};
76             # ajax qr{.*} => sub {};
77             #
78             # And the user won't have to declare the ajax routes before the
79             # get routes.
80 1442 100       1668 if (keys %{$route->{options}}) {
  1442         3344  
81 11         24 splice @{$self->routes($route->method)},
82 11         14 $self->{routes_border}{$route->method}++,
83             0,
84             $route;
85             }
86             else {
87 1431         1767 push @{$self->routes($route->method)}, $route;
  1431         2565  
88             }
89              
90 1442         6331 return $route;
91             }
92              
93             # sugar for add_route
94              
95             sub register_route {
96 1443     1443 0 3130 my ($self, %args) = @_;
97              
98             # look if the caller (where the route is declared) exists as a Dancer::App
99             # object
100 1443         6803 my ($package) = caller(2);
101 1443 100 100     4964 if ($package && Dancer::App->app_exists($package)) {
102 651         1356 my $app = Dancer::App->get($package);
103 651         1432 my $route = Dancer::Route->new(prefix => $app->prefix, %args);
104 650         1444 return $app->registry->add_route($route);
105             }
106             else {
107              
108             # FIXME maybe this code is useless, drop it later if so
109 792         2238 my $route = Dancer::Route->new(%args);
110 792         1525 return $self->add_route($route);
111             }
112             }
113              
114             # sugar for Dancer.pm
115             # class, any, ARRAY(0x9864818), '/path', CODE(0x990ac88)
116             # or
117             # class, any, '/path', CODE(0x990ac88)
118             sub any_add {
119 24     24 0 90 my ($self, $pattern, @rest) = @_;
120              
121 24         107 my @methods = qw(get post put patch delete options head);
122              
123 24 100       96 if (ref($pattern) eq 'ARRAY') {
124 19         63 @methods = @$pattern;
125             # 'get' defaults to 'get' and 'head'
126 38         140 push @methods, 'head' if ((grep { $_ eq 'get' } @methods) and
127 19 100 66     49 not (grep { $_ eq 'head' } @methods));
  4         12  
128 19         68 $pattern = shift @rest;
129             }
130              
131             raise core_route => "Syntax error, methods should be provided as an ARRAY ref"
132 24 100       63 if grep {$_ eq $pattern} @methods;
  75         196  
133              
134 23         111 $self->universal_add($_, $pattern, @rest) for @methods;
135 23         86 return scalar(@methods);
136             }
137              
138             sub universal_add {
139 1443     1443 0 2734 my ($self, $method, $pattern, @rest) = @_;
140              
141 1443         1932 my %options;
142             my $code;
143              
144 1443 100       2488 if (@rest == 1) {
145 1431         1836 $code = $rest[0];
146             }
147             else {
148 12         15 %options = %{$rest[0]};
  12         34  
149 12         17 $code = $rest[1];
150             }
151              
152 1443         4020 my %route_args = (
153             method => $method,
154             code => $code,
155             options => \%options,
156             pattern => $pattern,
157             );
158              
159 1443         3712 return $self->register_route(%route_args);
160             }
161              
162             # look for a route in the given array
163             sub find_route {
164 0     0 0   my ($self, $r, $reg) = @_;
165 0           foreach my $route (@$reg) {
166 0 0         return $route if $r->equals($route);
167             }
168 0           return;
169             }
170              
171             1;
172              
173             __END__