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.3520';
5 170     170   204812 use strict;
  170         1385  
  170         5297  
6 170     170   912 use warnings;
  170         343  
  170         4303  
7 170     170   858 use Carp;
  170         399  
  170         9437  
8 170     170   2811 use base 'Dancer::Object';
  170         2096  
  170         81108  
9              
10 170     170   81322 use Dancer::Config;
  170         576  
  170         9805  
11 170     170   1228 use Dancer::ModuleLoader;
  170         455  
  170         3990  
12 170     170   79465 use Dancer::Route::Registry;
  170         644  
  170         7088  
13 170     170   1227 use Dancer::Logger;
  170         416  
  170         4053  
14 170     170   956 use Dancer::Exception qw(:all);
  170         1313  
  170         20074  
15 170     170   1321 use Dancer::Deprecation;
  170         451  
  170         45886  
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 8060 sub applications { values %$_apps }
22              
23             sub app_exists {
24 1440     1440 0 2792 my ( $self, $name ) = @_;
25 1440         2995 grep { $_ eq $name } keys %$_apps;
  1518         6662  
26             }
27              
28             sub set_running_app {
29 16     16 0 53 my ($self, $name) = @_;
30 16         47 my $app = Dancer::App->get($name);
31 16 100       103 $app = Dancer::App->new(name => $name) unless defined $app;
32 16         61 Dancer::App->current($app);
33             }
34              
35             sub set_app_prefix {
36 1     1 0 6 my ($self, $prefix) = @_;
37 1         8 $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   1446 no warnings; # for undefined
  170         475  
  170         235869  
48 15     15 0 48 $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix + 1 );
49             }
50              
51             sub dec_lexical_prefix {
52 15     15 0 44 $_[0]->on_lexical_prefix( $_[0]->on_lexical_prefix - 1 );
53             }
54              
55             sub set_prefix {
56 29     29 0 69 my ($self, $prefix, $cb) = @_;
57              
58 29 100 100     136 undef $prefix if defined($prefix) and $prefix eq "/";
59              
60 29 100 100     190 raise core_app => "not a valid prefix: `$prefix', must start with a /"
61             if defined($prefix) && $prefix !~ /^\//;
62              
63 28 100       89 my $app_prefix = defined $self->app_prefix ? $self->app_prefix : "";
64 28         105 my $previous = Dancer::App->current->prefix;
65              
66 28   100     103 $prefix ||= "";
67              
68 28 100       73 if (Dancer::App->current->on_lexical_prefix) {
69 10         39 Dancer::App->current->prefix($previous.$prefix);
70             } else {
71 18         50 Dancer::App->current->prefix($app_prefix.$prefix);
72             }
73              
74 28 100       103 if (ref($cb) eq 'CODE') {
75 15         54 Dancer::App->current->incr_lexical_prefix;
76 15         25 eval { $cb->() };
  15         54  
77 15         31 my $e = $@;
78 15         38 Dancer::App->current->dec_lexical_prefix;
79 15         36 Dancer::App->current->prefix($previous);
80 15 50       40 die $e if $e;
81             }
82 28         65 return 1; # prefix may have been set to undef
83             }
84              
85             sub routes {
86 2     2 0 11 my ($self, $method) = @_;
87 2         3 map { $_->pattern } @{$self->registry->{'routes'}{$method}};
  1         4  
  2         7  
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 1228 my ($class, $request) = @_;
128 583         1389 for my $app (Dancer::App->current, Dancer::App->applications) {
129 620         1490 my $route = $app->find_route($request);
130 620 100       1530 if ($route) {
131 556         1418 Dancer::App->current($route->app);
132 556         1746 return $route;
133             }
134 64 50       153 return $route if $route;
135             }
136 27         85 return;
137             }
138              
139             # instance
140              
141             sub find_route {
142 620     620 0 1149 my ($self, $request) = @_;
143 620         1342 my $method = lc($request->method);
144              
145             # if route cache is enabled, we check if we handled this path before
146 620 100       2037 if (Dancer::Config::setting('route_cache')) {
147 84         247 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       211 if ($route) {
152 36         125 $route->match($request);
153 36         111 return $route;
154             }
155             }
156              
157 584         1004 my @routes = @{$self->registry->routes($method)};
  584         1481  
158              
159 584         1362 for my $r (@routes) {
160 1548         3844 my $match = $r->match($request);
161              
162 1548 100       3603 if ($match) {
163 534 100 100     1412 next if $r->has_options && (not $r->validate_options($request));
164              
165             # if we have a route cache, store the result
166 520 100       1635 if (Dancer::Config::setting('route_cache')) {
167 48         136 Dancer::Route::Cache->get->store_path($method,
168             $request->path_info => $r, $self->name);
169             }
170              
171 520         1528 return $r;
172             }
173             }
174 64         137 return;
175             }
176              
177             sub init {
178 115     115 1 460 my ($self) = @_;
179 115 100       690 $self->name('main') unless defined $self->name;
180              
181             raise core_app => "an app named '" . $self->name . "' already exists"
182 115 100       699 if exists $_apps->{$self->name};
183              
184             # default values for properties
185 114         696 $self->settings({});
186 114         577 $self->init_registry();
187              
188 114         586 $_apps->{$self->name} = $self;
189             }
190              
191             sub init_registry {
192 114     114 0 411 my ($self, $reg) = @_;
193 114   33     1743 $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 16169 my ($class, $app) = @_;
202 8187 100       16450 return $_current = $app if defined $app;
203              
204 7135 100       14453 if (not defined $_current) {
205 98   66     478 $_current = Dancer::App->get('main') || Dancer::App->new();
206             }
207              
208 7135         17110 return $_current;
209             }
210              
211             sub get {
212 769     769 0 4145 my ($class, $name) = @_;
213 769         2817 $_apps->{$name};
214             }
215              
216             sub setting {
217 2389     2389 0 3623 my $self = shift;
218              
219 2389 100       5016 if ($self->name eq 'main') {
220 2247 100       7184 return (@_ > 1)
221             ? Dancer::Config::setting( @_ )
222             : Dancer::Config::setting( $_[0] );
223             }
224              
225 142 100       336 if (@_ > 1) {
226 38         85 $self->_set_settings(@_)
227             } else {
228 104         188 my $name = shift;
229 104 100       224 exists($self->settings->{$name}) ? $self->settings->{$name}
230             : Dancer::Config::setting($name);
231             }
232             }
233              
234             sub _set_settings {
235 38     38   58 my $self = shift;
236 38 50       93 die "Odd number of elements in set" unless @_ % 2 == 0;
237 38         93 while (@_) {
238 38         62 my $name = shift;
239 38         60 my $value = shift;
240 38         128 $self->settings->{$name} =
241             Dancer::Config->normalize_setting($name => $value);
242             }
243             }
244              
245              
246             1;
247              
248             __END__