File Coverage

blib/lib/MooX/ConfigFromFile/Role.pm
Criterion Covered Total %
statement 82 82 100.0
branch 30 30 100.0
condition n/a
subroutine 17 17 100.0
pod n/a
total 129 129 100.0


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