File Coverage

blib/lib/Config/Context/ConfigScoped.pm
Criterion Covered Total %
statement 13 50 26.0
branch 0 22 0.0
condition 0 9 0.0
subroutine 5 8 62.5
pod 4 4 100.0
total 22 93 23.6


line stmt bran cond sub pod time code
1             package Config::Context::ConfigScoped;
2              
3 15     15   52669 use warnings;
  15         34  
  15         1411  
4 15     15   81 use strict;
  15         199  
  15         1030  
5              
6 15     15   238 use Carp;
  15         27  
  15         1986  
7 15     15   80 use Cwd;
  15         25  
  15         13978  
8              
9             =head1 NAME
10              
11             Config::Context::ConfigScoped - Use Config::Scoped config files with Config::Context
12              
13             =head1 SYNOPSIS
14              
15             use Config::Context;
16              
17             my $config_text = '
18             Location /users {
19             user_area = 1
20             }
21              
22             LocationMatch '\.*(jpg|gif|png)$' {
23             image_file = 1
24             }
25             ';
26              
27             my $conf = Config::Context->new(
28             string => $config_text,
29             driver => 'ConfigScoped',
30             match_sections => [
31             {
32             name => 'Location',
33             match_type => 'path',
34             },
35             {
36             name => 'LocationMatch',
37             match_type => 'regex',
38             },
39             ],
40             );
41              
42             my %config = $conf->context('/users/~mary/index.html');
43              
44             use Data::Dumper;
45             print Dumper(\%config);
46             --------
47             $VAR1 = {
48             'title' => 'User Area',
49             'image_file' => undef,
50             };
51              
52             my %config = $conf->context('/users/~biff/images/flaming_logo.gif');
53             print Dumper(\%config);
54             --------
55             $VAR1 = {
56             'title' => 'User Area',
57             'image_file' => 1,
58             };
59              
60              
61             =head1 DESCRIPTION
62              
63             This module uses C to parse config files for
64             C.
65              
66             =head1 DEFAULT OPTIONS
67              
68             In addition to the options normally enabled by Config::Scoped, the
69             following options are turned on by default:
70              
71             warnings => {
72             parameter => 'off',
73             declaration => 'off',
74             }
75              
76             You can change this behaviour by passing a different value to
77             C to C:
78              
79             my $conf = Config::Context->new(
80             driver => 'ConfigScoped',
81             driver_options => {
82             ConfigScoped = > {
83             warnings => {
84             parameter => 'on',
85             }
86             },
87             },
88             );
89              
90             =head1 CONSTRUCTOR
91              
92             =head2 new(...)
93              
94             my $driver = Config::Context::ConfigScoped->new(
95             file => $config_file,
96             lower_case_names => 1, # optional
97             options => {
98             # ...
99             }
100             );
101              
102             or:
103              
104             my $driver = Config::Context::ConfigScoped->new(
105             string => $config_string,
106             lower_case_names => 1, # optional
107             options => {
108             # ...
109             }
110             );
111              
112             Returns a new driver object, using the provided options.
113              
114             =cut
115              
116             sub new {
117 0     0 1 0 my $proto = shift;
118 0   0     0 my $class = ref $proto || $proto;
119 0         0 my %args = @_;
120              
121 0         0 Config::Context->_require_prerequisite_modules($class);
122              
123             # Copy driver opts
124 0 0       0 my %driver_opts = %{ $args{'options'}{'ConfigScoped'} || {} };
  0         0  
125 0 0       0 my %warnings = %{ $driver_opts{'warnings'} || {} };
  0         0  
126              
127 0         0 $driver_opts{'warnings'} = \%warnings;
128              
129 0 0       0 $warnings{'parameter'} = 'off'
130             unless exists $driver_opts{'parameter'};
131              
132 0 0       0 $warnings{'declaration'} = 'off'
133             unless exists $driver_opts{'declaration'};
134              
135 0 0 0     0 if (exists $args{'lower_case_names'} and not exists $driver_opts{'lc'}) {
136 0         0 $driver_opts{'lc'} = $args{'lower_case_names'};
137             }
138              
139 0         0 my $self = {};
140              
141 0 0       0 if ($args{'string'}) {
    0          
142 0         0 $self->{'text'} = $args{'string'};
143 0         0 $self->{'conf'} = Config::Scoped->new(
144             %driver_opts,
145             );
146             }
147             elsif($args{'file'}) {
148 0         0 $self->{'conf'} = Config::Scoped->new(
149             %driver_opts,
150             file => $args{'file'},
151             );
152             }
153             else {
154 0         0 croak __PACKAGE__ . "->new(): one of 'file' or 'string' is required";
155             }
156              
157 0         0 bless $self, $class;
158 0         0 return $self;
159             }
160              
161             =head1 METHODS
162              
163             =head2 parse()
164              
165             Returns the data structure for the parsed config.
166              
167             =cut
168              
169             sub parse {
170 0     0 1 0 my $self = shift;
171 0         0 my $config;
172 0 0       0 if ($self->{'text'}) {
173 0         0 $config = $self->{'conf'}->parse('text' => $self->{'text'});
174             }
175             else {
176 0         0 $config = $self->{'conf'}->parse;
177             }
178              
179 0 0 0     0 if ((keys %$config) == 1 and exists $config->{'_GLOBAL'}) {
180 0         0 $config = $config->{'_GLOBAL'};
181             }
182              
183 0 0       0 return %$config if wantarray;
184 0         0 return $config;
185             }
186              
187             =head2 files()
188              
189             Returns a list of all the config files read, including any config files
190             included in the main file.
191              
192             =cut
193              
194             sub files {
195 0     0 1 0 my $self = shift;
196              
197 0         0 my @files = values %{$self->{'conf'}{'local'}{'includes'}};
  0         0  
198              
199 0         0 @files = map { Cwd::abs_path($_) } @files;
  0         0  
200              
201 0 0       0 return @files if wantarray;
202 0         0 return \@files;
203             }
204              
205             =head2 config_modules
206              
207             Returns the modules used to parse the config. In this case: C
208              
209             =cut
210              
211             sub config_modules {
212 15     15 1 999 'Config::Scoped';
213             }
214              
215              
216             =head1 CAVEATS
217              
218             =head2 Limitations of hash merging with included files
219              
220             When one C file includes another, and they both contain
221             declarations, the declarations are merged. For instance:
222              
223             # config1.conf
224             %include config2.conf
225             section /users {
226             title = 'Members Area';
227             }
228              
229             # config2.conf
230             section /users {
231             user_area = 1;
232             title = 'users area';
233             }
234              
235             This will result in:
236              
237             {
238             'section' => {
239             '/users' => {
240             'user_area' => '1',
241             'title' => 'Members Area',
242             },
243             },
244             }
245              
246             However, if you use hashes instead of declarations, then the second hash
247             with the same name will completely overwrite the first one. For instance:
248              
249             # config1.conf
250             %include config2.conf
251             section = {
252             '/users' = {
253             title = 'Members Area';
254             }
255             }
256              
257             # config2.conf
258             section = {
259             '/users' = {
260             user_area = 1;
261             title = 'users area';
262             }
263             }
264              
265             This will result in:
266              
267             {
268             'section' => {
269             '/users' => {
270             'title' => 'Members Area',
271             },
272             },
273             }
274              
275              
276             This is important to keep in mind because C does not
277             allow nested declarations.
278              
279              
280             =head2 Avoid using the Default Section
281              
282             When using the C driver, you must be
283             careful with the use of the default section, since C
284             does its own inheritance from the global scope into named sections. See
285             the documentation for C for more
286             information.
287              
288             So for instance, the following will not work as expected.
289              
290             private_area = 0
291             image_file = 0
292              
293             LocationMatch admin {
294             private_area = 1
295             }
296              
297             LocationMatch '\.(gif)|(jpg)|(png)$' {
298             image_file = 1
299             }
300              
301             Since this is equivalent to:
302              
303             LocationMatch admin {
304             image_file = 0
305             private_area = 1
306             }
307              
308             LocationMatch '\.(gif)|(jpg)|(png)$' {
309             private_area = 0
310             image_file = 1
311             }
312              
313             Values set in the default section are inherited into sections before
314             those sections are matched.
315              
316             One solution is to use hashes, rather than declarations:
317              
318             private_area = 0
319             image_file = 0
320              
321             LocationMatch = {
322              
323             admin = {
324             private_area = 1
325             }
326              
327             '\.(gif)|(jpg)|(png)$' = {
328             image_file = 1
329             }
330             }
331              
332             This works, because in C, hashes do not inherit
333             parameters from their enclosing scope.
334              
335             However, note that when two hashes with the same name collide, their
336             values are not merged together. Instead, one hash replaces the other
337             hash. See above under L.
338              
339             =head2 lower_case_names also affects section names
340              
341             If you use the lower_case_names option, be aware that it also affects
342             the names of declaration blocks. For instance, the following
343             configuration,
344              
345             Location /FOO {
346             Some_Param = 'Some Value'
347             }
348              
349             becomes:
350              
351             {
352             'location' => {
353             '/foo' => {
354             'some param' => 'Some Value';
355             }
356             }
357             }
358              
359             Unless you expect this behaviour (which you probably don't), you should
360             probably avoid using the C option with C.
361              
362             =head2 _GLOBAL Scope automatically merged
363              
364             Normally, if there are no declarations in a C file, all
365             configuration is placed under a key called C<_GLOBAL>.
366             C detects this condition and moves the data
367             under C<_GLOBAL> up a level. Basically, it does the equivalent of:
368              
369             $config = $config->{_GLOBAL};
370              
371             The reason for this is to allow use of hashes instead of declarations to
372             enable default values. See L,
373             above.
374              
375             =head2 Quote block names
376              
377             Instead of:
378              
379             LocationMatch \.*(jpg|gif|png)$ {
380             # some configuration
381             }
382              
383             use:
384              
385             LocationMatch '\.*(jpg|gif|png)$' {
386             # some configuration
387             }
388              
389             Note that regular expression characters don't have to be quoted beyond
390             this.
391              
392             =head1 SEE ALSO
393              
394             Config::Context
395             CGI::Application::Plugin::Config::Context
396             Config::Scoped
397              
398             =head1 COPYRIGHT & LICENSE
399              
400             Copyright 2004-2005 Michael Graham, All Rights Reserved.
401              
402             This program is free software; you can redistribute it and/or modify it
403             under the same terms as Perl itself.
404              
405             =cut
406              
407             1;
408              
409              
410              
411