File Coverage

blib/lib/MooX/ConfigFromFile/Role.pm
Criterion Covered Total %
statement 71 77 92.2
branch 13 26 50.0
condition n/a
subroutine 15 16 93.7
pod n/a
total 99 119 83.1


line stmt bran cond sub pod time code
1             package MooX::ConfigFromFile::Role;
2              
3 2     2   11014 use strict;
  2         3  
  2         81  
4 2     2   12 use warnings;
  2         4  
  2         101  
5              
6             our $VERSION = '0.007';
7              
8 2     2   584 use FindBin qw/$Script/;
  2         1181  
  2         322  
9              
10 2     2   1244 use Config::Any;
  2         19563  
  2         79  
11 2     2   1443 use File::Find::Rule;
  2         17195  
  2         21  
12              
13 2     2   137 use Moo::Role;
  2         4  
  2         17  
14              
15             with "MooX::File::ConfigDir";
16              
17             around BUILDARGS => sub {
18             my $next = shift;
19             my $class = shift;
20             my $params = $class->$next(@_);
21             $class->_initialize_from_config($params);
22             return $params;
23             };
24              
25             sub _initialize_from_config
26             {
27 1     1   3 my ( $class, $params ) = @_;
28 1 50       9 defined $params->{loaded_config} or $params->{loaded_config} = $class->_build_loaded_config($params);
29              
30             # This copies stuff from loaded_config into the object's parameters
31 1         2 foreach my $cfg_key ( keys %{ $params->{loaded_config} } )
  1         3  
32             {
33 2 50       4 exists $params->{$cfg_key} and next;
34 2         4 $params->{$cfg_key} = $params->{loaded_config}->{$cfg_key};
35             }
36              
37 1         3 return $params;
38             }
39              
40             has 'config_prefix' => ( is => 'lazy' );
41              
42 0     0   0 sub _build_config_prefix { $Script; }
43              
44             has 'config_prefixes' => ( is => 'lazy' );
45              
46             sub _build_config_prefixes
47             {
48 1     1   2 my ( $class, $params ) = @_;
49 1 50       3 defined $params->{config_prefix} or $params->{config_prefix} = $class->_build_config_prefix($params);
50 1         3 [ $params->{config_prefix} ];
51             }
52              
53             has 'config_prefix_map_separator' => ( is => 'lazy' );
54              
55 1     1   2 sub _build_config_prefix_map_separator { "-" }
56              
57             has 'config_prefix_map' => ( is => 'lazy' );
58              
59             sub _build_config_prefix_map
60             {
61 1     1   2 my ( $class, $params ) = @_;
62              
63 1 50       7 defined $params->{config_prefix_map_separator}
64             or $params->{config_prefix_map_separator} = $class->_build_config_prefix_map_separator($params);
65 1 50       6 defined $params->{config_prefixes} or $params->{config_prefixes} = $class->_build_config_prefixes($params);
66              
67 1         3 my ( $sep, $i, @prefix_map ) = ( $params->{config_prefix_map_separator} );
68 1         2 for ( $i = 0; $i < scalar @{ $params->{config_prefixes} }; ++$i )
  2         6  
69             {
70 1         2 push @prefix_map, join( $sep, @{ $params->{config_prefixes} }[ 0 .. $i ] );
  1         5  
71             }
72              
73 1         3 \@prefix_map;
74             }
75              
76             has 'config_extensions' => ( is => 'lazy' );
77              
78 1     1   9 sub _build_config_extensions { [ Config::Any->extensions() ] }
79              
80             has 'config_files_pattern' => ( is => 'lazy' );
81              
82             sub _build_config_files_pattern
83             {
84 1     1   3 my ( $class, $params ) = @_;
85              
86 1 50       7 defined $params->{config_prefix_map} or $params->{config_prefix_map} = $class->_build_config_prefix_map($params);
87 1 50       5 defined $params->{config_extensions} or $params->{config_extensions} = $class->_build_config_extensions($params);
88             # my @cfg_pattern = map { $params->{config_prefix} . "." . $_ } @{ $params->{config_extensions} };
89 10         6 my @cfg_pattern = map {
90 1         3 my $ext = $_;
91 10         6 map { $_ . "." . $ext } @{ $params->{config_prefix_map} }
  10         16  
  10         10  
92 1         8294 } @{ $params->{config_extensions} };
93              
94 1         5 \@cfg_pattern;
95             }
96              
97             has 'config_files' => ( is => 'lazy' );
98              
99             sub _build_config_files
100             {
101 1     1   2 my ( $class, $params ) = @_;
102              
103 1 50       7 defined $params->{config_files_pattern} or $params->{config_files_pattern} = $class->_build_config_files_pattern($params);
104 1 50       13 defined $params->{config_dirs} or $params->{config_dirs} = $class->_build_config_dirs($params);
105 1 50       4501 ref $params->{config_dirs} eq "ARRAY" or $params->{config_dirs} = ["."];
106              
107 1         62 my @cfg_files =
108 1         43 File::Find::Rule->file()->name( @{ $params->{config_files_pattern} } )->maxdepth(1)->in( @{ $params->{config_dirs} } );
  1         1730  
109              
110 1         7334 return \@cfg_files;
111             }
112              
113             has raw_loaded_config => (
114             is => 'lazy',
115             clearer => 1
116             );
117              
118             sub _build_raw_loaded_config
119             {
120 1     1   2 my ( $class, $params ) = @_;
121              
122 1 50       8 defined $params->{config_files} or $params->{config_files} = $class->_build_config_files($params);
123 1 50       1 return [] if !@{ $params->{config_files} };
  1         10  
124              
125             [
126 1         2 sort { my @a = %{$a}; my @b = %{$b}; $a[0] cmp $b[0]; } @{ Config::Any->load_files(
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  1         15  
127             {
128             files => $params->{config_files},
129             use_ext => 1
130             }
131             )
132             }
133             ];
134             }
135              
136             has 'loaded_config' => (
137             is => 'lazy',
138             clearer => 1
139             );
140              
141             sub _build_loaded_config
142             {
143 1     1   2 my ( $class, $params ) = @_;
144              
145 1 50       8 defined $params->{raw_loaded_config} or $params->{raw_loaded_config} = $class->_build_raw_loaded_config($params);
146              
147 1         4071 my $config_merged = {};
148 1         2 for my $c ( map { values %$_ } @{ $params->{raw_loaded_config} } )
  1         4  
  1         3  
149             {
150 1         5 %$config_merged = ( %$config_merged, %$c );
151             }
152              
153 1         3 $config_merged;
154             }
155              
156             =head1 NAME
157              
158             MooX::ConfigFromFile::Role - Moo eXtension for initializing objects from config file
159              
160             =head1 DESCRIPTION
161              
162             This role adds a initializing sub around L
163             and puts all what could read from config files into the hash which will be
164             used to construct the final object.
165              
166             While it does that, it internally calls it's own _build_* methods (I<_build_config_prefix>,
167             I<_build_config_files> and I<_build_loaded_config>) unless the appropriate attributes are
168             already in C<$params>.
169              
170             =head1 ATTRIBUTES
171              
172             This role uses following attributes which might be suitable customized by
173             overloading the appropriate builder or pass defaults in construction arguments.
174              
175             Be sure to read L, especially
176             L to understand how the L
177             are build.
178              
179             When you miss a directory - see L and
180             L.
181              
182             =head2 config_prefix
183              
184             This attribute is a string and defaults to L's C<$Script>. It's
185             interpreted as the basename of the config file name to use.
186              
187             =head2 config_prefixes
188              
189             This attribute is an array of strings and defaults to C<<[ config_prefix ]>>.
190              
191             =head2 config_prefix_map_separator
192              
193             This attribute is a string and contains the character which is used building
194             I from I.
195              
196             =head2 config_prefix_map
197              
198             This attribute is an array of strings containing all config-prefixes joint
199             together C<($0, $0.$1, $0.$1.$2, ...)> using I.
200              
201             =head2 config_files_pattern
202              
203             This attribute contains a cross-product of I and
204             I. Both are concatenated using the shell wildcard '*'.
205              
206             =head2 config_dirs
207              
208             This attribute is consumed from L.
209             It might not be smart to override - but possible. Use with caution.
210              
211             =head2 config_extensions
212              
213             This attribute defaults to list of extensions from L.
214              
215             =head2 config_files
216              
217             This attribute contains the list of existing files in I matching
218             I . I. Search is operated by L.
219              
220             =head2 raw_loaded_config
221              
222             This attribute contains the config as loaded from file system in an array of
223             C<< filename => \%content >>. The result from L is sorted by
224             filename (C<< '-' < '.' >>).
225              
226             =head2 loaded_config
227              
228             This attribute contains the config loaded and transformed while constructing
229             the instance. Construction is done from I, ignoring the
230             filename part.
231              
232             For classes set up using
233              
234             use MooX::ConfigFromFile config_singleton = 1;
235              
236             this attribute is cached from the very first construction and fed by overwritten
237             I. The content of this attribute is passed to lower I.
238              
239             =head1 AUTHOR
240              
241             Jens Rehsack, C<< >>
242              
243             =head1 ACKNOWLEDGEMENTS
244              
245             Toby Inkster suggested to rely on BUILDARGS instead of intercepting object
246             creation with nasty hacks. He also taught me a bit more how Moo(se) works.
247              
248             =head1 LICENSE AND COPYRIGHT
249              
250             Copyright 2013-2015 Jens Rehsack.
251              
252             This program is free software; you can redistribute it and/or modify it
253             under the terms of either: the GNU General Public License as published
254             by the Free Software Foundation; or the Artistic License.
255              
256             See L for more information.
257              
258             =cut
259              
260             1;