File Coverage

blib/lib/Banal/Config/General.pm
Criterion Covered Total %
statement 24 100 24.0
branch 0 14 0.0
condition 0 18 0.0
subroutine 8 17 47.0
pod 7 7 100.0
total 39 156 25.0


line stmt bran cond sub pod time code
1             #===============================================
2             package Banal::Config::General;
3              
4 1     1   1101 use utf8;
  1         11  
  1         5  
5 1     1   38 use strict;
  1         2  
  1         31  
6 1     1   6 use warnings;
  1         2  
  1         34  
7 1     1   6 no warnings qw(uninitialized);
  1         1  
  1         33  
8              
9 1     1   1411 use Config::General;
  1         64200  
  1         105  
10             our @ISA = qw(Config::General);
11              
12             # Apparently, on debian with perl > 5.8.4 croak() doesn't work anymore without this.
13             # There seems to be some require statement which apparently dies 'cause it can't find Carp::Heavy,
14 1     1   14 use Carp::Heavy;
  1         1  
  1         28  
15 1     1   6 use Carp;
  1         2  
  1         74  
16              
17 1     1   4143 use Banal::DateTime;
  1         242023  
  1         1244  
18              
19              
20             our $STASH;
21              
22             #-----------------------------------------------
23             sub new {
24 0     0 1   my $proto = shift;
25 0   0       my $class = ref($proto) || $proto;
26 0           my $opts = $class->determine_options(@_);
27            
28            
29 0           print STDERR "\n========= " . __PACKAGE__ . " : New ...\n" if 0; # For debugging.
30            
31 0           my $self = $class->SUPER::new(%$opts);
32            
33 0           $class->_bless_into_appropriate_class($self, $opts);
34            
35 0           return $self;
36             }
37              
38              
39             #-----------------------------------------------
40             # Class method.
41             # -- may be overridden.
42             #-----------------------------------------------
43             sub extended_config_class {
44 0     0 1   return __PACKAGE__ ."::Extended";
45             }
46              
47              
48             #-----------------------------------------------
49             # Class method.
50             # -- may be overridden.
51             #-----------------------------------------------
52             sub default_options {
53             return {
54 0     0 1   -InterPolateVars => 1,
55             -InterPolateEnv => 1,
56             -ExtendedAccess => 1,
57             -StrictObjects => 0,
58             -UseApacheInclude => 1,
59             -IncludeRelative => 1,
60             -IncludeDirectories => 1,
61             -IncludeGlob => 1,
62             -UTF8 => 1,
63             -SaveSorted => 1,
64             -AutoTrue => 1,
65             -MergeDuplicateBlocks => 1,
66             -MergeDuplicateOptions => 1,
67             -LowerCaseNames => 1,
68            
69             # 'Banal' options
70             -Banal_UsePredefinedVars => 1,
71             -Banal_StashKind => 'normal', # Could have also been 'global'
72             };
73             }
74              
75              
76             #-----------------------------------------------
77             # Class method.
78             # -- may be overridden, but you better know what you are doing!
79             #-----------------------------------------------
80             sub forced_default_options {
81             return {
82 0     0 1   -StrictObjects => 0,
83             # -Plug => { pre_read => *_debug_hook_pre_read }
84             };
85             }
86              
87              
88             #-----------------------------------------------
89             # Class method.
90             # -- may be overridden, but you should not need to do that normally.
91             #-----------------------------------------------
92             sub determine_options {
93 0     0 1   my $proto = shift;
94 0   0       my $class = ref($proto) || $proto;
95 0           my $stash = $class->build_stash();
96              
97             # Preserve a global copy of the very first stash we ever build, hopefully when the process first starts.
98 0   0       $STASH ||= $stash;
99            
100 0           my $default_opts = $class->default_options(@_);
101 0           my $forced_default_opts = $class->forced_default_options(@_);
102            
103             # Make sure the options passed by the user (i.e. caller) override the defaults.
104             # In between, force a few defaults on options. They can still be overriden by user passed options.
105             # In the end, make sure we have ExtendedAccess.
106 0           my $opts = {
107             %$default_opts,
108             %$forced_default_opts,
109             @_,
110             -ExtendedAccess => 1,
111             };
112            
113             # Do the right thing, if we are told to use predefined variables (like NOW, TODAY, ...)
114 0 0         if ($opts->{-Banal_UsePredefinedVars}) {
115 0 0         $stash = $STASH if ($opts->{-Banal_StashKind} =~ /global/i);
116            
117             # Yes, a copy is needed. Don't just assign the reference. Otherwise, the global STASH will be polluted.
118 0           my $dc = {%$stash};
119            
120             # If there is already a default config, merge it with the stash.
121 0 0         if ($opts->{-DefaultConfig}) {
122 0           my $odc = $opts->{-DefaultConfig};
123            
124 0 0         if (ref($odc) eq 'HASH') {
125 0           $dc = {%$dc, %$odc};
126             } else {
127 0           croak "Banal::Config::General: Error: Currently, '-DefaultConfig' can only be a reference to a HASH when used in conjunction with '-Banal_UsePredefinedVars'. Let go of one or the other, or both.\n";
128             }
129             }
130            
131 0           $opts->{-DefaultConfig} = $dc;
132             }
133            
134 0           return $opts;
135             }
136            
137            
138             #================================
139             # class method
140             #================================
141             sub build_stash {
142 0     0 1   my $class = shift;
143 0           my $stash = {};
144            
145 0           my $now = $stash->{'BNL.NOW.OBJ'} = Banal::DateTime->now();
146 0           my $today = $stash->{'BNL.TODAY.OBJ'} = $now->clone()->truncate( to => 'day' );
147 0           my $yesterday = $stash->{'BNL.YESTERDAY.OBJ'} = $today->clone()->subtract( days => 1 );
148 0           my $day_before_yesterday = $stash->{'BNL.DAY_BEFORE_YESTERDAY.OBJ'} = $yesterday->clone()->subtract( days => 1 );
149            
150 0           my $tomorrow = $stash->{'BNL.TOMORROW.OBJ'} = $today->clone()->add( days => 1 );
151 0           my $day_after_tomorrow = $stash->{'BNL.DAY_AFTER_TOMORROW.OBJ'} = $tomorrow->clone()->add( days => 1 );
152            
153 0           $stash->{'BNL.NOW.STR.ISO'} = $now->iso8601();
154 0           $stash->{'BNL.TODAY.STR.ISO'} = $today->ymd('-');
155 0           $stash->{'BNL.YESTERDAY.STR.ISO'} = $yesterday->ymd('-');
156 0           $stash->{'BNL.DAY_BEFORE_YESTERDAY.STR.ISO'} = $day_before_yesterday->ymd('-');
157 0           $stash->{'BNL.TOMORROW.STR.ISO'} = $tomorrow->ymd('-');
158 0           $stash->{'BNL.DAY_AFTER_TOMORROW.STR.ISO'} = $day_after_tomorrow->ymd('-');
159            
160 0           $stash->{'BNL.NOW.STR'} = $now->ymd('') . 'T' . $now->hms('');
161 0           $stash->{'BNL.TODAY.STR'} = $today->ymd('');
162 0           $stash->{'BNL.YESTERDAY.STR'} = $yesterday->ymd('');
163 0           $stash->{'BNL.DAY_BEFORE_YESTERDAY.STR'} = $day_before_yesterday->ymd('');
164 0           $stash->{'BNL.TOMORROW.STR'} = $tomorrow->ymd('');
165 0           $stash->{'BNL.DAY_AFTER_TOMORROW.STR'} = $day_after_tomorrow->ymd('');
166            
167 0           $stash->{'BNL.THIS_YEAR'} = $now->year();
168 0           $stash->{'BNL.THIS_YEAR.STD'} = $now->year_std();
169              
170 0           $stash->{'BNL.THIS_MONTH'} = $now->month();
171 0           $stash->{'BNL.THIS_MONTH.STD'} = $now->month_std();
172            
173 0           $stash->{'BNL.THIS_DAY_OF_MONTH'} = $now->day();
174 0           $stash->{'BNL.THIS_DAY_OF_MONTH.STD'} = $now->day_std();
175            
176 0           my $extra_vars = $class->extra_predefined_vars(@_);
177 0           $stash = {%$stash, %$extra_vars};
178            
179 0           return $stash;
180             }
181              
182              
183             #================================
184             # class method
185             # -- Feel free to override
186             # Should return a hashable list.
187             #================================
188             sub extra_predefined_vars {
189 0     0 1   return;
190             }
191              
192              
193              
194              
195              
196             #*************************************************************************
197             # Private stuff.
198             #*************************************************************************
199              
200             # Note that this is a class method!
201             # Note also that "class" parameter comes before "object".
202             sub _bless_into_appropriate_class {
203             #
204             # bless into ::Extended if necessary
205 0     0     my $class = shift;
206 0           my $object = shift;
207 0           my $opts = shift;
208            
209 0 0 0       if ($object->{ExtendedAccess} || $opts->{-ExtendedAccess} || UNIVERSAL::isa($object, "Config::General::Extended")) {
      0        
210             # we are blessing here again, to get into the ::Extended namespace
211             # for inheriting the methods available over there, which we don't necessarily have.
212            
213 0   0       my $extended_class = $class->extended_config_class(@_) || $class . "::Extended";
214            
215 0 0         unless (UNVERSAL::isa($object, $extended_class)) {
216 0           bless $object, $extended_class;
217 0           eval { require $extended_class; };
  0            
218 0 0         if ($@) {
219 0           croak "Banal::Config::General: " . $@;
220             }
221             }
222             }else {
223 0           bless $object, $class;
224             }
225            
226 0           return $object;
227             }
228            
229            
230            
231             #================================
232             # A pre-read hook for debugging purposes.
233             #================================
234             sub _debug_hook_pre_read {
235 0     0     my $fh = shift;
236 0           my $text = join ('', @_);
237 0           my $retval = 1;
238            
239 0           print STDERR "\n========= ". __PACKAGE__ . " : Reading a config file ...\n";
240            
241 0           my @lines = split ("\n", $text);
242            
243 0           return ($retval, $fh, @lines);
244            
245             }
246              
247             1;
248              
249              
250             __END__
251              
252              
253             =head1 NAME
254              
255             Banal::Config::General - A wrapper around Config::General that provides semsible defaults as well as a stash.
256              
257              
258             =head1 SYNOPSIS
259              
260             Here's a snippet.
261              
262             use Banal::Config::General;
263              
264             my $foo = Banal::Config::General->new(-ConfigFile=>"path/to/config/file");
265            
266             # The resulting object is blessed into "Banal::Config::General::Extended".
267            
268             my $v = $foo->value('the-key');
269            
270             ...
271              
272             =head1 EXPORT
273              
274             None.
275              
276             =head1 EXPORT_OK
277              
278             None.
279              
280             =head1 CONSTRUCTORS
281              
282             =head2 new()
283              
284             The new() constructor is overriden in order to take into account the default options for this particular class. Other than that, it's essentially a call to SUPER::new.
285              
286              
287             =head1 CLASS METHODS
288              
289             =head2 extended_config_class()
290              
291             =head2 default_options()
292              
293             =head2 forced_default_options()
294              
295             =head2 extra_predefined_vars()
296              
297             =head2 build_stash()
298              
299             =head1 METHODS
300              
301             =head2 determine_options()
302              
303              
304              
305             =head1 AUTHOR
306              
307             "aulusoy", C<< <"dev (at) ulusoy.name"> >>
308              
309             =head1 BUGS
310              
311             Please report any bugs or feature requests to C<bug-banal-config at rt.cpan.org>, or through
312             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Banal-Config>. I will be notified, and then you'll
313             automatically be notified of progress on your bug as I make changes.
314              
315              
316              
317             =head1 SUPPORT
318              
319             You can find documentation for this module with the perldoc command.
320              
321             perldoc Banal::Config::General
322              
323              
324             You can also look for information at:
325              
326             =over 4
327              
328             =item * RT: CPAN's request tracker (report bugs here)
329              
330             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Banal-Config>
331              
332             =item * AnnoCPAN: Annotated CPAN documentation
333              
334             L<http://annocpan.org/dist/Banal-Config>
335              
336             =item * CPAN Ratings
337              
338             L<http://cpanratings.perl.org/d/Banal-Config>
339              
340             =item * Search CPAN
341              
342             L<http://search.cpan.org/dist/Banal-Config/>
343              
344             =back
345              
346              
347             =head1 ACKNOWLEDGEMENTS
348              
349              
350             =head1 LICENSE AND COPYRIGHT
351              
352             Copyright 2014 "aulusoy".
353              
354             This program is free software; you can redistribute it and/or modify it
355             under the terms of the the Artistic License (2.0). You may obtain a
356             copy of the full license at:
357              
358             L<http://www.perlfoundation.org/artistic_license_2_0>
359              
360             Any use, modification, and distribution of the Standard or Modified
361             Versions is governed by this Artistic License. By using, modifying or
362             distributing the Package, you accept this license. Do not use, modify,
363             or distribute the Package, if you do not accept this license.
364              
365             If your Modified Version has been derived from a Modified Version made
366             by someone other than you, you are nevertheless required to ensure that
367             your Modified Version complies with the requirements of this license.
368              
369             This license does not grant you the right to use any trademark, service
370             mark, tradename, or logo of the Copyright Holder.
371              
372             This license includes the non-exclusive, worldwide, free-of-charge
373             patent license to make, have made, use, offer to sell, sell, import and
374             otherwise transfer the Package with respect to any patent claims
375             licensable by the Copyright Holder that are necessarily infringed by the
376             Package. If you institute patent litigation (including a cross-claim or
377             counterclaim) against any party alleging that the Package constitutes
378             direct or contributory patent infringement, then this Artistic License
379             to you shall terminate on the date that such litigation is filed.
380              
381             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
382             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
383             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
384             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
385             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
386             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
387             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
388             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
389              
390              
391             =cut
392              
393             1; # End of Banal::Config::General
394              
395