File Coverage

blib/lib/Dancer/App.pm
Criterion Covered Total %
statement 122 136 89.7
branch 43 52 82.6
condition 16 19 84.2
subroutine 28 29 96.5
pod 1 17 5.8
total 210 253 83.0


line stmt bran cond sub pod time code
1             package Dancer::App;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             # ABSTRACT: Base application class for Dancer.
4             $Dancer::App::VERSION = '1.3521';
5 170     170   202294 use strict;
  170         354  
  170         4735  
6 170     170   859 use warnings;
  170         351  
  170         3914  
7 170     170   865 use Carp;
  170         386  
  170         11023  
8 170     170   2992 use base 'Dancer::Object';
  170         357  
  170         80512  
9              
10 170     170   80749 use Dancer::Config;
  170         574  
  170         9725  
11 170     170   1571 use Dancer::ModuleLoader;
  170         460  
  170         3918  
12 170     170   79353 use Dancer::Route::Registry;
  170         652  
  170         6886  
13 170     170   1209 use Dancer::Logger;
  170         451  
  170         4067  
14 170     170   938 use Dancer::Exception qw(:all);
  170         1293  
  170         19867  
15 170     170   1324 use Dancer::Deprecation;
  170         420  
  170         44324  
16              
17             Dancer::App->attributes(qw(name app_prefix prefix registry settings on_lexical_prefix));
18              
19             # singleton that saves any app created, we want unicity for app names
20             my $_apps = {};
21 1947     1947 0 7731 sub applications { values %$_apps }
22              
23             sub app_exists {
24 1440     1440 0 2794 my ( $self, $name ) = @_;
25 1440         3007 grep { $_ eq $name } keys %$_apps;
  1518         6684  
26             }
27              
28             sub set_running_app {
29 16     16 0 47 my ($self, $name) = @_;
30 16         49 my $app = Dancer::App->get($name);
31 16 100       108 $app = Dancer::App->new(name => $name) unless defined $app;
32 16         59 Dancer::App->current($app);
33             }
34              
35             sub set_app_prefix {
36 1     1 0 3 my ($self, $prefix) = @_;
37 1         5 $self->app_prefix($prefix);
38 1         3 $self->prefix($prefix);
39             }
40              
41             sub get_prefix {
42             # return the current prefix (if undefined, return an empty string)
43 3   100 3 0 7 return Dancer::App->current->prefix || '';
44             }
45              
46             sub incr_lexical_prefix {
47 170     170   1380 no warnings; # for undefined
  170         468  
  170         226949  
48 15     15 0 44 $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix + 1 );
49             }
50              
51             sub dec_lexical_prefix {
52 15     15 0 54 $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix - 1 );
53             }
54              
55             sub set_prefix {
56 29     29 0 68 my ($self, $prefix, $cb) = @_;
57              
58 29 100 100     137 undef $prefix if defined($prefix) and $prefix eq "/";
59              
60 29 100 100     173 raise core_app => "not a valid prefix: `$prefix', must start with a /"
61             if defined($prefix) && $prefix !~ /^\//;
62              
63 28 100       80 my $app_prefix = defined $self->app_prefix ? $self->app_prefix : "";
64 28         98 my $previous = Dancer::App->current->prefix;
65              
66 28   100     92 $prefix ||= "";
67              
68 28 100       69 if (Dancer::App->current->on_lexical_prefix) {
69 10         35 Dancer::App->current->prefix($previous.$prefix);
70             } else {
71 18         50 Dancer::App->current->prefix($app_prefix.$prefix);
72             }
73              
74 28 100       107 if (ref($cb) eq 'CODE') {
75 15         46 Dancer::App->current->incr_lexical_prefix;
76 15         34 eval { $cb->() };
  15         59  
77 15         33 my $e = $@;
78 15         51 Dancer::App->current->dec_lexical_prefix;
79 15         43 Dancer::App->current->prefix($previous);
80 15 50       49 die $e if $e;
81             }
82 28         71 return 1; # prefix may have been set to undef
83             }
84              
85             sub routes {
86 2     2 0 5 my ($self, $method) = @_;
87 2         3 map { $_->pattern } @{$self->registry->{'routes'}{$method}};
  1         3  
  2         5  
88             }
89              
90             sub reload_apps {
91 0     0 0 0 my ($class) = @_;
92              
93 0         0 Dancer::Deprecation->deprecated(
94             feature => 'auto_reload',
95             reason => 'use plackup -r instead',
96             );
97              
98 0         0 my @missing_modules = grep { not Dancer::ModuleLoader->load($_) }
  0         0  
99             qw(Module::Refresh Clone);
100              
101 0 0       0 if (not @missing_modules) {
102              
103             # saving apps & purging app registries
104 0         0 my $orig_apps = {};
105 0         0 while (my ($name, $app) = each %$_apps) {
106 0         0 $orig_apps->{$name} = $app->clone;
107 0         0 $app->registry->init();
108             }
109              
110             # reloading changed modules, getting apps reloaded
111 0         0 Module::Refresh->refresh;
112              
113             # make sure old apps that didn't get reloaded are kept
114 0         0 while (my ($name, $app) = each %$orig_apps) {
115 0 0       0 $_apps->{$name} = $app unless defined $_apps->{$name};
116 0 0       0 $_apps->{$name} = $app if $_apps->{$name}->registry->is_empty;
117             }
118              
119             }
120             else {
121 0         0 carp "Modules required for auto_reload are missing. Install modules"
122             . " [@missing_modules] or unset 'auto_reload' in your config file.";
123             }
124             }
125              
126             sub find_route_through_apps {
127 583     583 0 1201 my ($class, $request) = @_;
128 583         1382 for my $app (Dancer::App->current, Dancer::App->applications) {
129 621         1453 my $route = $app->find_route($request);
130 621 100       1413 if ($route) {
131 556         1476 Dancer::App->current($route->app);
132 556         1710 return $route;
133             }
134 65 50       160 return $route if $route;
135             }
136 27         92 return;
137             }
138              
139             # instance
140              
141             sub find_route {
142 621     621 0 1202 my ($self, $request) = @_;
143 621         1451 my $method = lc($request->method);
144              
145             # if route cache is enabled, we check if we handled this path before
146 621 100       2002 if (Dancer::Config::setting('route_cache')) {
147 84         270 my $route = Dancer::Route::Cache->get->route_from_path($method,
148             $request->path_info, $self->name);
149              
150             # NOTE maybe we should cache the match data as well
151 84 100       203 if ($route) {
152 36         128 $route->match($request);
153 36         94 return $route;
154             }
155             }
156              
157 585         970 my @routes = @{$self->registry->routes($method)};
  585         1425  
158              
159 585         1273 for my $r (@routes) {
160 1570         3839 my $match = $r->match($request);
161              
162 1570 100       3614 if ($match) {
163 534 100 100     1472 next if $r->has_options && (not $r->validate_options($request));
164              
165             # if we have a route cache, store the result
166 520 100       1462 if (Dancer::Config::setting('route_cache')) {
167 48         146 Dancer::Route::Cache->get->store_path($method,
168             $request->path_info => $r, $self->name);
169             }
170              
171 520         1552 return $r;
172             }
173             }
174 65         133 return;
175             }
176              
177             sub init {
178 115     115 1 421 my ($self) = @_;
179 115 100       692 $self->name('main') unless defined $self->name;
180              
181             raise core_app => "an app named '" . $self->name . "' already exists"
182 115 100       711 if exists $_apps->{$self->name};
183              
184             # default values for properties
185 114         676 $self->settings({});
186 114         585 $self->init_registry();
187              
188 114         511 $_apps->{$self->name} = $self;
189             }
190              
191             sub init_registry {
192 114     114 0 420 my ($self, $reg) = @_;
193 114   33     1616 $self->registry($reg || Dancer::Route::Registry->new);
194              
195             }
196              
197             # singleton that saves the current active Dancer::App object
198             my $_current;
199              
200             sub current {
201 8187     8187 0 15371 my ($class, $app) = @_;
202 8187 100       16127 return $_current = $app if defined $app;
203              
204 7135 100       14204 if (not defined $_current) {
205 98   66     456 $_current = Dancer::App->get('main') || Dancer::App->new();
206             }
207              
208 7135         17168 return $_current;
209             }
210              
211             sub get {
212 769     769 0 4067 my ($class, $name) = @_;
213 769         2720 $_apps->{$name};
214             }
215              
216             sub setting {
217 2389     2389 0 3578 my $self = shift;
218              
219 2389 100       4923 if ($self->name eq 'main') {
220 2247 100       6941 return (@_ > 1)
221             ? Dancer::Config::setting( @_ )
222             : Dancer::Config::setting( $_[0] );
223             }
224              
225 142 100       291 if (@_ > 1) {
226 38         93 $self->_set_settings(@_)
227             } else {
228 104         167 my $name = shift;
229 104 100       201 exists($self->settings->{$name}) ? $self->settings->{$name}
230             : Dancer::Config::setting($name);
231             }
232             }
233              
234             sub _set_settings {
235 38     38   53 my $self = shift;
236 38 50       100 die "Odd number of elements in set" unless @_ % 2 == 0;
237 38         87 while (@_) {
238 38         62 my $name = shift;
239 38         51 my $value = shift;
240 38         140 $self->settings->{$name} =
241             Dancer::Config->normalize_setting($name => $value);
242             }
243             }
244              
245              
246             1;
247              
248             __END__