File Coverage

blib/lib/CGI/Application/Plugin/Config/Any.pm
Criterion Covered Total %
statement 99 120 82.5
branch 37 56 66.0
condition 16 31 51.6
subroutine 13 15 86.6
pod 6 6 100.0
total 171 228 75.0


line stmt bran cond sub pod time code
1             ## --------------------------------------------------------------------
2             ## C::A::Plugin to use Config::Any
3             ## --------------------------------------------------------------------
4              
5             package CGI::Application::Plugin::Config::Any;
6 2     2   62972 use strict;
  2         6  
  2         83  
7 2     2   12 use warnings;
  2         4  
  2         64  
8              
9 2     2   10 use base 'Exporter';
  2         7  
  2         204  
10 2     2   11 use vars qw/ @EXPORT @EXPORT_OK %EXPORT_TAGS /;
  2         12  
  2         244  
11              
12             @EXPORT = qw( config );
13             @EXPORT_OK = qw( config_init config_name config_section config_read );
14             %EXPORT_TAGS = (
15             'all' => [
16             qw( config config_init config_name config_section config_read )
17             ]
18             );
19              
20 2     2   2195 use Config::Any;
  2         27343  
  2         2782  
21              
22             my $prefix = '__CONFIG_ANY_';
23              
24             $CGI::Application::Plugin::Config::Any::DEBUG = 0;
25              
26              
27             =head1 NAME
28              
29             CGI::Application::Plugin::Config::Any - Add Config::Any Support to CGI::Application
30              
31             =head1 VERSION
32              
33             Version 0.13
34              
35             =cut
36              
37             $CGI::Application::Plugin::Config::Any::VERSION = '0.14';
38              
39              
40             =head1 SYNOPSIS
41              
42             There are two ways to initialize this module.
43              
44             B
45              
46             my $app = WebApp->new(
47             PARAMS => {
48             config_dir => '/path/to/configfiles',
49             config_files => [ 'app.conf' ],
50             config_name => 'main',
51             config_params => {
52             ## passed to Config::Any->load_files;
53             ## see Config::Any for valid params
54             }
55             }
56             );
57             $app->run();
58            
59             B-based module:>
60              
61             use base 'CGI::Application';
62             use CGI::Application::Plugin::Config::Any;
63              
64             sub cgiapp_init {
65             my $self = shift;
66              
67             # Set config file and other options
68             $self->config_init(
69             config_dir => '/path/to/configfiles',
70             config_files => [ 'app.conf' ],
71             config_name => 'main',
72             config_params => {
73             ## passed to Config::Any->load_files;
74             ## see Config::Any for valid params
75             }
76             );
77             }
78              
79             Later...
80              
81             ## get a complete config section as a hashref
82             my $section = $self->config_section( 'sectionname' );
83            
84             ## get a single config param
85             my $param = $self->config( 'paramname' );
86            
87              
88             =head1 DESCRIPTION
89              
90             This module allows to use L for config files inside a
91             CGI::Application based application.
92              
93             B
94              
95             (L provides a facility for Perl applications and libraries
96             to load configuration data from multiple different file formats. It
97             supports XML, YAML, JSON, Apache-style configuration, Windows INI
98             files, and even Perl code.)
99              
100              
101             =head1 EXPORTS
102              
103             By default, only the L() method is exported.
104              
105             B
106              
107             =over 4
108              
109             =item config_init
110              
111             =item config_name
112              
113             =item config_section
114              
115             =item config_read
116              
117             =back
118              
119             You can import them explicitly, or use ':all':
120              
121             use CGI::Application::Plugin::Config::Any qw( :all );
122              
123              
124             =head1 METHODS
125              
126             =head2 config
127              
128             This method is exported to your C::A based application as an accessor
129             to the configuration params.
130              
131             There are several ways to retrieve a config param:
132              
133             $self->config_section('mysection');
134             $self->config('mysetting');
135             # set section to 'mysection' before retrieving 'mysetting'
136              
137             $self->config('mysetting', section => 'mysection' );
138             # more convenient way to do the same as above
139              
140             $self->config('mysection.mysetting');
141             # another way to do the same as above
142              
143             $self->config('mysetting');
144             # let the module find a param named 'mysetting' without
145             # knowing or bothering the section name
146              
147             See also L!
148              
149             =cut
150              
151             #-------------------------------------------------------------------
152             # METHOD: config
153             # + author: Bianka Martinovic
154             # + reviewed: Bianka Martinovic
155             # + purpose:
156             #-------------------------------------------------------------------
157             sub config {
158 3     3 1 329 my $self = shift;
159 3         6 my $param = shift;
160              
161 3   100     25 my %attrs = (
162             section => $self->{$prefix.'CURRENT_SECTION'},
163             name => $self->{$prefix.'CONFIG_NAME'} || 'default',
164             @_
165             );
166              
167 3         4 my $section = $attrs{'section'};
168              
169 3 50 33     21 if ( $param && $param =~ /^(.*)\.(.*)$/ ) {
170 0         0 $section = $1;
171 0         0 $param = $2;
172             }
173              
174             $CGI::Application::Plugin::Config::Any::DEBUG
175 3 50       8 and __PACKAGE__->_debug(
176             " config name [$attrs{'name'}]\n"
177             . " param [$param]\n"
178             . " section [$section]\n"
179             );
180              
181 3         10 return _load(
182             $self,
183             section => $section,
184             param => $param,
185             name => $attrs{'name'}
186             );
187             } # --- end sub config ---
188              
189              
190             =head2 config_init
191              
192             Initializes the plugin.
193              
194             $self->config_init(
195             config_dir => '/path/to/configfiles',
196             config_files => [ 'app.conf' ],
197             );
198              
199             Valid params:
200              
201             =over 4
202              
203             =item config_dir SCALAR
204              
205             Path where the config files reside in.
206              
207             =item config_files ARRAY
208              
209             A list of files to load.
210              
211             =item config_name SCALAR
212              
213             You can use more than one configuration at the same time by using config
214             names. For example:
215              
216             $self->config_init(
217             config_name => 'database',
218             config_files => [ 'db.conf' ],
219             );
220             $self->config_init(
221             config_name => 'template',
222             config_files => [ 'tpl.conf' ],
223             );
224              
225             ...
226              
227             my $connection_options = $self->config_section('connection', name => 'database' );
228             my $template_file = $self->config( 'file', name => 'template' );
229              
230             =item config_names HASHREF
231              
232              
233              
234             =item config_params HASHREF
235              
236             Options to pass to Config::Any->load_files().
237              
238             B
239              
240             $self->config_init(
241             config_files => [ 'default.yml' ],
242             config_params => {
243             'use_ext' => 1,
244             }
245             );
246              
247             See L for details.
248              
249             =back
250              
251             =cut
252              
253             #-------------------------------------------------------------------
254             # METHOD: config_init
255             # + author: Bianka Martinovic
256             # + reviewed: Bianka Martinovic
257             # + purpose:
258             #-------------------------------------------------------------------
259             sub config_init {
260 1     1 1 2 my $self = shift;
261              
262 1   50     3 my %args = (
      50        
      50        
      50        
      50        
263             'config_names' => $self->param('config_names') || {},
264             'config_dir' => $self->param('config_dir') || undef,
265             'config_files' => $self->param('config_files') || [],
266             'config_params' => $self->param('config_params') || {},
267             'config_name' => $self->param('config_name') || 'default',
268             @_
269             );
270            
271 1         73 foreach ( keys %args ) {
272 8         24 $self->{ $prefix . uc($_) } = delete $args{$_};
273             }
274              
275             $CGI::Application::Plugin::Config::Any::DEBUG
276 0         0 and __PACKAGE__->_debug(
277             "initialized with:\n"
278             . "\tconfig_names: $self->{$prefix.'CONFIG_NAMES'}\n"
279             . "\tconfig_dir : $self->{$prefix.'CONFIG_DIR'}\n"
280             . "\tconfig_files: "
281 1 50       4 . join( ', ', @{ $self->{$prefix.'CONFIG_FILES'} } )
282             );
283              
284 1         2 return 1;
285            
286             } # --- end sub config_init ---
287              
288             =head2 config_name
289              
290             Set the name of the config to use.
291              
292             =cut
293              
294             #-------------------------------------------------------------------
295             # METHOD: config_name
296             # + author: Bianka Martinovic
297             # + reviewed: Bianka Martinovic
298             # + purpose: set the name of the current config
299             #-------------------------------------------------------------------
300             sub config_name {
301 1     1 1 554 my $self = shift;
302 1         2 my $name = shift;
303            
304 1 50       5 return unless $name;
305            
306 1 50       3 $CGI::Application::Plugin::Config::Any::DEBUG
307             and __PACKAGE__->_debug( "setting config name: $name" );
308            
309 1         3 $self->{$prefix.'CONFIG_NAME'} = $name;
310            
311 1         4 return $name;
312              
313             } # --- end sub config_name ---
314              
315              
316             =head2 config_section
317              
318             Retrieve a complete section from your configuration, or set the name
319             of the current "default section" for later use with C.
320              
321             my $hash = $self->config_section('mysection');
322              
323             =cut
324              
325             #-------------------------------------------------------------------
326             # METHOD: config_section
327             # + author: Bianka Martinovic
328             # + reviewed: Bianka Martinovic
329             # + purpose:
330             #-------------------------------------------------------------------
331             sub config_section {
332 1     1 1 2 my $self = shift;
333 1         2 my $section = shift;
334            
335 1         4 $self->{$prefix.'CURRENT_SECTION'} = $section;
336            
337 1 50       4 $CGI::Application::Plugin::Config::Any::DEBUG
338             and __PACKAGE__->_debug(
339             "loading section [$section]"
340             );
341            
342 1 50       5 return _load( $self, section => $section, @_ ) if defined wantarray;
343            
344 0         0 return;
345            
346             } # --- end sub config_section ---
347              
348              
349             =head2 config_read
350              
351             Get complete configuration as a hashref.
352              
353             my $config = $self->config_read();
354              
355             =cut
356              
357             #-------------------------------------------------------------------
358             # METHOD: config_read
359             # + author: Bianka Martinovic
360             # + reviewed: Bianka Martinovic
361             # + purpose:
362             #-------------------------------------------------------------------
363             sub config_read {
364 1     1 1 226 my $self = shift;
365            
366 1         2 return _load( $self, @_ );
367            
368             } # --- end sub config_read ---
369              
370              
371             =head2 std_config
372              
373             For CGI::Application::Standard::Config compatibility. Just returns
374             'TRUE'.
375              
376             =cut
377              
378             #-------------------------------------------------------------------
379             # METHOD: std_config
380             # + author: Bianka Martinovic
381             # + reviewed: Bianka Martinovic
382             # + purpose: CGI::Application::Standard::Config compatibility
383             #-------------------------------------------------------------------
384 0     0 1 0 sub std_config { return 1; }
385              
386              
387             #-------------------------------------------------------------------
388             # + + + + + INTERNAL METHODS + + + + +
389             #-------------------------------------------------------------------
390              
391             #-------------------------------------------------------------------
392             # METHOD: _load
393             # + author: Bianka Martinovic
394             # + reviewed: 07-11-14 Bianka Martinovic
395             # + purpose: load config file(s)
396             #-------------------------------------------------------------------
397             sub _load {
398 5     5   9 my $self = shift;
399              
400 5   100     29 my %args = (
401             section => undef,
402             param => undef,
403             name => $self->{$prefix.'CONFIG_NAME'} || 'default',
404             @_
405             );
406            
407 5         8 my $name = $args{'name'};
408              
409 5 100       14 unless ( $self->{$prefix.'CONFIG_CONFIG'} ) {
410 1         6 $self->config_init( %args );
411             }
412              
413 5         9 my %config = ();
414            
415             ## config already loaded?
416 5 100       15 unless ( $self->{$prefix.'CONFIG_CONFIG'}->{ $name } ) {
417            
418 2 50       5 $CGI::Application::Plugin::Config::Any::DEBUG
419             and __PACKAGE__->_debug(
420             "loading config named [$name]"
421             );
422              
423 2 100       9 if ( exists $self->{$prefix.'CONFIG_NAMES'}->{ $name } ) {
424            
425 1         3 my $this = $self->{$prefix.'CONFIG_NAMES'}->{ $name };
426              
427 1         3 foreach ( qw/ config_dir config_files config_params / ) {
428 3         6 my $key = $prefix.uc($_);
429 3 100       8 if ( exists $this->{ $_ } ) {
430 2         4 $self->{$key} = $this->{$_};
431             }
432 3         12 $self->{$prefix.'CONFIG_FILES'}
433             = $self->{$prefix.'CONFIG_NAMES'}->{ $name }->{'config_files'};
434             }
435             }
436              
437 2 50 33     24 if ( $self->{$prefix.'CONFIG_FILES'}
438             && ref $self->{$prefix.'CONFIG_FILES'} ne 'ARRAY'
439             ) {
440 0         0 $self->{$prefix.'CONFIG_FILES'} = [ $self->{$prefix.'CONFIG_FILES'} ];
441             }
442            
443 2         13 $self->{$prefix.'CONFIG_FILES'}
444             = [
445 2         7 map { $self->{$prefix.'CONFIG_DIR'}.'/'.$self->{$prefix.'CONFIG_FILES'}[$_] }
446 2         4 0 .. $#{ $self->{$prefix.'CONFIG_FILES'} }
447             ];
448              
449 0         0 $CGI::Application::Plugin::Config::Any::DEBUG
450             and __PACKAGE__->_debug(
451             "searching files: "
452 2 50       5 . join( ', ', @{$self->{$prefix.'CONFIG_FILES'}} )
453             );
454              
455             ## load the files using Config::Any
456 2         23 my $cfg = Config::Any->load_files(
457             {
458             files => $self->{$prefix.'CONFIG_FILES'},
459 2         6 %{ $self->{$prefix.'CONFIG_PARAMS'} }
460             }
461             );
462              
463 2 50       19783 $CGI::Application::Plugin::Config::Any::DEBUG
464             and __PACKAGE__->_debug(
465             "found [" . scalar @$cfg . "] config files"
466             );
467            
468             ## import settings
469 2         8 for ( @$cfg ) {
470            
471 2         7 my ( $filename, $thisconfig ) = each %$_;
472            
473 2         8 foreach ( keys %$thisconfig ) {
474 5         38 $config{$_} = $thisconfig->{$_};
475             }
476            
477             }
478            
479 2         19 $self->{$prefix.'CONFIG_CONFIG'}->{ $args{'name'} } = \%config;
480            
481             }
482             else {
483 3         3 %config = %{ $self->{$prefix.'CONFIG_CONFIG'}->{ $args{'name'} } };
  3         15  
484             }
485              
486             ## return a section
487 5 100 100     38 if ( $args{'section'} && ! $args{'param'} ) {
488            
489 1 50       3 $CGI::Application::Plugin::Config::Any::DEBUG
490             and __PACKAGE__->_debug(
491             "returning complete section [$args{'section'}]"
492             );
493            
494 1         6 return $config{ $args{'section'} };
495            
496             }
497              
498 4 100       12 if ( $args{'param'} ) {
499              
500 2     2   25 no strict 'vars';
  2         5  
  2         1266  
501            
502 3         6 my $value;
503            
504 3 100 33     16 if ( exists $config{ $args{'param'} } ) {
    50 33        
505 2         6 $value = $config{ $args{'param'} };
506             }
507             elsif ( $args{'section'}
508             && $config{ $args{'section'} }
509             && $config{ $args{'section'} }->{ $args{'param'} }
510             ) {
511 0         0 $value = $config{ $args{'section'} }->{ $args{'param'} };
512             }
513            
514 3 100       8 unless ( defined $value ) {
515 1 50       2 $CGI::Application::Plugin::Config::Any::DEBUG
516             and __PACKAGE__->_debug(
517             "trying to find key [$args{'param'}]"
518             );
519 1         5 $value = _find_key( $self, $args{'param'}, \%config );
520             }
521              
522 3         36 return $value;
523              
524             }
525              
526 1         4 return \%config;# unless wantarray;
527              
528             } # --- end sub _load ---
529              
530             #-------------------------------------------------------------------
531             # METHOD: _find_key
532             # + author: Bianka Martinovic
533             # + reviewed: Bianka Martinovic
534             # + purpose: find a key in the config data structure
535             #-------------------------------------------------------------------
536             sub _find_key {
537 7     7   7 my $self = shift;
538 7         8 my $key = shift;
539 7         7 my $config = shift;
540              
541 7 100       13 unless ( ref $config eq 'HASH' ) {
542 2         4 return;
543             }
544            
545 5 100       12 if ( exists $config->{ $key } ) {
546 1 50       4 $CGI::Application::Plugin::Config::Any::DEBUG
547             and __PACKAGE__->_debug(
548             "key [$key] found"
549             );
550 1         2 return $config->{ $key };
551             }
552            
553 4         5 foreach my $subkey ( keys %{ $config } ) {
  4         9  
554 6         16 my $value = _find_key( $self, $key, $config->{$subkey} );
555 6 100       15 return $value if $value;
556             }
557            
558 2         4 return;
559              
560             } # --- end sub _find_key ---
561              
562              
563             =pod
564              
565             =head1 DEBUGGING
566              
567             This module provides some internal debugging. Any debug messages go to
568             STDOUT, so beware of enabling debugging when running in a web
569             environment. (This will end up with "Internal Server Error"s in most
570             cases.)
571              
572             There are two ways to enable the debug mode:
573              
574             =over 4
575              
576             =item In the module
577              
578             Find line
579              
580             $CGI::Application::Plugin::Config::Any::DEBUG = 0;
581              
582             and set it to any "true" value. ("1", "TRUE", ... )
583              
584             =item From outside the module
585              
586             Add this line B calling C:
587              
588             $CGI::Application::Plugin::Config::Any::DEBUG = 1;
589              
590             =back
591              
592             =cut
593              
594             #-------------------------------------------------------------------
595             # METHOD: _debug
596             # + author: Bianka Martinovic
597             # + reviewed: 07-11-14 Bianka Martinovic
598             # + purpose: print out formatted _debug messages
599             #-------------------------------------------------------------------
600             sub _debug {
601 0     0     my $self = shift;
602 0           my $msg = shift;
603            
604 0           my $dump;
605 0 0         if ( @_ ) {
606 0 0         if ( scalar ( @_ ) % 2 == 2 ) {
607 0           %{ $dump } = ( @_ );
  0            
608             }
609             else {
610 0           $dump = \@_;
611             }
612             }
613            
614 0           my ( $package, $line, $sub ) = (caller())[0,2,3];
615 0           my ( $callerpackage, $callerline, $callersub )
616             = (caller(1))[0,2,3];
617            
618 0   0       $sub ||= '-';
619            
620 0           print "\n",
621             join( ' | ', $package, $line, $sub ),
622             "\n\tcaller: ",
623             join( ' | ', $callerpackage, $callerline, $callersub ),
624             "\n\t$msg",
625             "\n\n";
626            
627             #if ( $dump ) {
628             # print $self->_dump( $dump );
629             #}
630            
631 0           return;
632             } # --- end sub _debug ---
633              
634             1;
635              
636             __END__