File Coverage

blib/lib/MooX/ConfigFromFile/Role.pm
Criterion Covered Total %
statement 72 77 93.5
branch 26 26 100.0
condition n/a
subroutine 16 16 100.0
pod n/a
total 114 119 95.8


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