File Coverage

blib/lib/Dancer/Config.pm
Criterion Covered Total %
statement 124 124 100.0
branch 29 32 90.6
condition 36 81 44.4
subroutine 28 28 100.0
pod 0 11 0.0
total 217 276 78.6


line stmt bran cond sub pod time code
1             package Dancer::Config;
2             our $AUTHORITY = 'cpan:SUKRIA';
3             #ABSTRACT: how to configure Dancer to suit your needs
4             $Dancer::Config::VERSION = '1.3514_04'; # TRIAL
5             $Dancer::Config::VERSION = '1.351404';
6 194     194   116013 use strict;
  194         343  
  194         4924  
7 194     194   900 use warnings;
  194         327  
  194         4794  
8 194     194   858 use base 'Exporter';
  194         401  
  194         17923  
9 194     194   1200 use vars '@EXPORT_OK';
  194         344  
  194         8945  
10              
11 194     194   73250 use Hash::Merge::Simple;
  194         81116  
  194         8240  
12 194     194   69329 use Dancer::Config::Object 'hashref_to_object';
  194         420  
  194         8853  
13 194     194   72585 use Dancer::Deprecation;
  194         397  
  194         4879  
14 194     194   64595 use Dancer::Template;
  194         450  
  194         4803  
15 194     194   1051 use Dancer::ModuleLoader;
  194         351  
  194         3209  
16 194     194   69024 use Dancer::FileUtils 'path';
  194         476  
  194         9848  
17 194     194   1129 use Carp;
  194         554  
  194         7829  
18 194     194   1001 use Dancer::Exception qw(:all);
  194         353  
  194         16352  
19              
20 194     194   83975 use Encode;
  194         2262544  
  194         243295  
21              
22             @EXPORT_OK = qw(setting);
23              
24             my $SETTINGS = {};
25              
26             # mergeable settings
27             my %MERGEABLE = map { ($_ => 1) } qw( plugins handlers );
28             my %_LOADED;
29              
30 599     599 0 5061 sub settings {$SETTINGS}
31              
32             my $setters = {
33             logger => sub {
34             my ($setting, $value) = @_;
35             require Dancer::Logger;
36             Dancer::Logger->init($value, settings());
37             },
38             log_file => sub {
39             require Dancer::Logger;
40             Dancer::Logger->init(setting("logger"), settings());
41             },
42             session => sub {
43             my ($setting, $value) = @_;
44             require Dancer::Session;
45             Dancer::Session->init($value, settings());
46             },
47             template => sub {
48             my ($setting, $value) = @_;
49             require Dancer::Template;
50             Dancer::Template->init($value, settings());
51             },
52             route_cache => sub {
53             my ($setting, $value) = @_;
54             require Dancer::Route::Cache;
55             Dancer::Route::Cache->reset();
56             },
57             serializer => sub {
58             my ($setting, $value) = @_;
59             require Dancer::Serializer;
60             Dancer::Serializer->init($value);
61             },
62             # This setting has been deprecated in favor of global_warnings.
63             import_warnings => sub {
64             my ($setting, $value) = @_;
65              
66             Dancer::Deprecation->deprecated(
67             message => "import_warnings has been deprecated, please use global_warnings instead."
68             );
69              
70             $^W = $value ? 1 : 0;
71             },
72             global_warnings => sub {
73             my ($setting, $value) = @_;
74             $^W = $value ? 1 : 0;
75             },
76             traces => sub {
77             my ($setting, $traces) = @_;
78             $Dancer::Exception::Verbose = $traces ? 1 : 0;
79             },
80             };
81             $setters->{log_path} = $setters->{log_file};
82              
83             my $normalizers = {
84             charset => sub {
85             my ($setting, $charset) = @_;
86             length($charset || '')
87             or return $charset;
88             my $encoding = Encode::find_encoding($charset);
89             defined $encoding
90             or raise core_config => "Charset defined in configuration is wrong : couldn't identify '$charset'";
91             my $name = $encoding->name;
92             # Perl makes a distinction between the usual perl utf8, and the strict
93             # utf8 charset. But we don't want to make this distinction
94             $name eq 'utf-8-strict'
95             and $name = 'utf-8';
96             return $name;
97             },
98             session_same_site => sub {
99             my ($setting, $same_site_setting) = @_;
100             if ($same_site_setting =~ m{^(strict|lax|none)$}i) {
101             return ucfirst lc $same_site_setting;
102             } else {
103             raise core_config => "Invalid session_same_site value $same_site_setting";
104             }
105             },
106             };
107              
108             sub normalize_setting {
109 1889     1889 0 3375 my ($class, $setting, $value) = @_;
110              
111             $value = $normalizers->{$setting}->($setting, $value)
112 1889 100       4114 if exists $normalizers->{$setting};
113              
114 1889         3529 return $value;
115             }
116              
117             # public accessor for get/set
118             sub setting {
119 13914 100   13914 0 40564 if (@_ == 1) {
120 12112         19020 return _get_setting(shift @_);
121             }
122             else {
123             # can be useful for debug! Use Logger, instead?
124 1802 50       4545 die "Odd number in 'set' assignment" unless scalar @_ % 2 == 0;
125              
126 1802         2412 my $count = 0;
127 1802         3416 while (@_) {
128 1819         2580 my $setting = shift;
129 1819         2273 my $value = shift;
130              
131 1819         4601 _set_setting ($setting, $value);
132              
133             # At the moment, with any kind of hierarchical setter,
134             # there is no case where the same trigger will be run more
135             # than once. If/when a hierarchical setter is implemented,
136             # we should create a list of the hooks that should be run,
137             # and run them at the end of this while, only (efficiency
138             # purposes).
139 1819         3756 _trigger_hooks($setting, $value);
140 1814         4082 $count++
141             }
142 1797         5888407 return $count; # just to return anything, the number of items set.
143             }
144             }
145              
146             sub _trigger_hooks {
147 1821     1821   2751 my ($setting, $value) = @_;
148              
149 1821 100       5203 $setters->{$setting}->(@_) if defined $setters->{$setting};
150             }
151              
152             sub _set_setting {
153 1820     1820   3097 my ($setting, $value) = @_;
154              
155 1820 50       3345 return unless @_ == 2;
156              
157             # normalize the value if needed
158 1820         4558 $value = Dancer::Config->normalize_setting($setting, $value);
159 1820         3997 $SETTINGS->{$setting} = $value;
160 1820         2730 return $value;
161             }
162              
163             sub _get_setting {
164 12113     12113   15462 my $setting = shift;
165              
166 12113         41490 return $SETTINGS->{$setting};
167             }
168              
169 225   66 225 0 1007 sub conffile { path(setting('confdir') || setting('appdir'), 'config.yml') }
170              
171             sub environment_file {
172 17     17 0 176 my $env = setting('environment');
173             # XXX for compatibility reason, we duplicate the code from `init_envdir` here
174             # we don't know how if some application don't already do some weird stuff like
175             # the test in `t/15_plugins/02_config.t`.
176 17   66     29 my $envdir = setting('envdir') || path(setting('appdir'), 'environments');
177 17         53 return path($envdir, "$env.yml");
178             }
179              
180             sub init_confdir {
181 201 100   201 0 601 return setting('confdir') if setting('confdir');
182 4   66     26 setting confdir => $ENV{DANCER_CONFDIR} || setting('appdir');
183             }
184              
185             sub init_envdir {
186 201 100   201 0 568 return setting('envdir') if setting('envdir');
187 130 100       466 my $appdirpath = defined setting('appdir') ?
188             path( setting('appdir'), 'environments' ) :
189             path('environments');
190              
191 130   33     1140 setting envdir => $ENV{DANCER_ENVDIR} || $appdirpath;
192             }
193              
194             sub load {
195 201     201 0 1365 init_confdir();
196 201         792 init_envdir();
197              
198             # look for the conffile
199 201 100       772 return 1 unless -f conffile;
200              
201             # load YAML
202 11         76 my $module = load_yaml_module();
203              
204 10 100       24 unless ($_LOADED{conffile()}) {
205 5         16 load_settings_from_yaml(conffile, $module);
206 5         18 $_LOADED{conffile()}++;
207             }
208              
209 10         27 my $env = environment_file;
210              
211             # don't load the same env twice
212 10 50       33 unless( $_LOADED{$env} ) {
213 10 100       187 if (-f $env ) {
    100          
214 4         19 load_settings_from_yaml($env, $module);
215 4         12 $_LOADED{$env}++;
216             }
217             elsif (setting('require_environment')) {
218             # failed to load the env file, and the main config said we needed it.
219 1         204 confess "Could not load environment file '$env', and require_environment is set";
220             }
221             }
222              
223 9         48 foreach my $key (grep { $setters->{$_} } keys %$SETTINGS) {
  203         245  
224 28         80 $setters->{$key}->($key, $SETTINGS->{$key});
225             }
226 9 100       37 if ( $SETTINGS->{strict_config} ) {
227 2         7 $SETTINGS = hashref_to_object($SETTINGS);
228             }
229              
230 9         41 return 1;
231             }
232              
233             sub load_settings_from_yaml {
234 14     14 0 5881 my ($file, $module) = @_;
235              
236 14   66     40 $module ||= load_yaml_module();
237              
238 14         23 my $config;
239             {
240 194     194   1777 no strict 'refs';
  194         603  
  194         85042  
  14         52  
241 14 100       22 $config = eval { &{ $module . '::LoadFile' }($file) }
  14         23  
  14         61  
242             or confess "Unable to parse the configuration file: $file: $@";
243             }
244              
245             $SETTINGS = Hash::Merge::Simple::merge( $SETTINGS, {
246             map {
247 9         13268 $_ => Dancer::Config->normalize_setting( $_, $config->{$_} )
  31         82  
248             } keys %$config
249             } );
250              
251 9         584 return scalar keys %$config;
252             }
253              
254             sub load_yaml_module {
255 12     12 0 29 my ($module) = @_;
256              
257 12   100     91 $module ||= $SETTINGS->{engines}{YAML}{module} || 'YAML';
      33        
258              
259 12         55 my ( $result, $error ) = Dancer::ModuleLoader->load($module);
260 12 100       249 confess "Could not load $module: $error"
261             unless $result;
262              
263 11         26 return $module;
264             }
265              
266             sub load_default_settings {
267 194   50 194 0 2357 $SETTINGS->{server} ||= $ENV{DANCER_SERVER} || '0.0.0.0';
      33        
268 194   50     1413 $SETTINGS->{port} ||= $ENV{DANCER_PORT} || '3000';
      33        
269 194   50     2137 $SETTINGS->{content_type} ||= $ENV{DANCER_CONTENT_TYPE} || 'text/html';
      33        
270 194   50     2170 $SETTINGS->{charset} ||= $ENV{DANCER_CHARSET} || '';
      33        
271 194   33     1097 $SETTINGS->{startup_info} ||= !$ENV{DANCER_NO_STARTUP_INFO};
272 194   50     1668 $SETTINGS->{daemon} ||= $ENV{DANCER_DAEMON} || 0;
      33        
273 194   50     1606 $SETTINGS->{apphandler} ||= $ENV{DANCER_APPHANDLER} || 'Standalone';
      33        
274 194   50     1833 $SETTINGS->{warnings} ||= $ENV{DANCER_WARNINGS} || 0;
      33        
275 194   50     1749 $SETTINGS->{auto_reload} ||= $ENV{DANCER_AUTO_RELOAD} || 0;
      33        
276 194   50     1551 $SETTINGS->{traces} ||= $ENV{DANCER_TRACES} || 0;
      33        
277 194   33     1126 $SETTINGS->{server_tokens} ||= !$ENV{DANCER_NO_SERVER_TOKENS};
278 194   50     1648 $SETTINGS->{logger} ||= $ENV{DANCER_LOGGER} || 'file';
      33        
279             $SETTINGS->{environment} ||=
280             $ENV{DANCER_ENVIRONMENT}
281             || $ENV{PLACK_ENV}
282 194   50     2639 || 'development';
      33        
283              
284 194         988 setting $_ => {} for keys %MERGEABLE;
285 194         667 setting template => 'simple';
286             }
287              
288             load_default_settings();
289              
290             1;
291              
292             __END__