File Coverage

blib/lib/Config/TT2.pm
Criterion Covered Total %
statement 49 52 94.2
branch 14 16 87.5
condition 8 9 88.8
subroutine 11 11 100.0
pod 3 3 100.0
total 85 91 93.4


line stmt bran cond sub pod time code
1 8     8   141105 use strict;
  8         20  
  8         307  
2 8     8   43 use warnings;
  8         15  
  8         324  
3              
4             package Config::TT2;
5              
6 8     8   8327 use Template;
  8         229967  
  8         246  
7 8     8   5553 use Try::Tiny;
  8         9226  
  8         487  
8 8     8   50 use Carp qw(croak);
  8         17  
  8         5510  
9              
10             our $VERSION = '0.53';
11              
12             =head1 NAME
13              
14             Config::TT2 - Reading configuration files with the Template-Toolkit parser.
15              
16             =head1 ABSTRACT
17              
18             Define configuration files in the powerful, flexible and extensible Template-Toolkit syntax.
19              
20             =cut
21              
22             sub new {
23 31     31 1 34376 my $class = shift;
24              
25             # params as HASH or HASHREF?
26 31 100 100     255 my $params = defined( $_[0] ) && ref( $_[0] ) eq 'HASH' ? shift : {@_};
27              
28             #
29             # Warn for unsupported Template and Template::Service params.
30             # Our entry level is Template::Context, see Template::Manual::Internals
31             #
32 31         167 my @unsupported = qw(
33             PRE_PROCESS
34             PROCESS
35             POST_PROCESS
36             WRAPPER
37             AUTO_RESET
38             DEFAULT
39             OUTPUT
40             OUTPUT_PATH
41             ERROR
42             ERRORS
43             );
44              
45 31         75 foreach my $unsupported (@unsupported) {
46 265 100       2239 croak "Option '$unsupported' not supported\n"
47             if exists $params->{$unsupported};
48             }
49              
50             #
51             # DEFAULTS, see Template::Manual::Config
52             #
53 21         120 my $defaults = {
54             STRICT => 1,
55             ABSOLUTE => 1,
56             RELATIVE => 1,
57             CACHE_SIZE => 0,
58             };
59              
60             # override defaults by params
61 21         165 my $self = bless { _PARAMS => { %$defaults, %$params } }, $class;
62              
63 21   66     371 my $tt = Template->new( $self->{_PARAMS} ) || croak "$Template::ERROR\n";
64              
65             # our entry level into TT2 is Template::Context to get the stash back
66 20         258377 $self->context( $tt->service->context );
67              
68 20         269 return $self;
69             }
70              
71             sub context {
72 57     57 1 295 my ( $self, $ctx ) = @_;
73 57 100       187 $self->{_CONTEXT} = $ctx if defined $ctx;
74 57         173 return $self->{_CONTEXT};
75             }
76              
77             sub process {
78 19     19 1 444 my ( $self, $template, $vars ) = @_;
79              
80 19         48 my $ctx = $self->context;
81 19         73 my $stash = $ctx->stash;
82              
83             #
84             # processing template from Template::Context level and NOT
85             # from Template::Service level to get the stash back
86             #
87 19         81 my ( $output, $error );
88             try {
89 19     19   782 my $comp_template = $ctx->template($template);
90              
91             # play Template::Service, preset template slot
92 17         297753 $vars->{template} = $comp_template;
93              
94             # ok, process at Template::Context level
95 17         106 $output = $ctx->process( $comp_template, $vars );
96             }
97 19     2   200 catch { $error = $_ };
  2         155  
98 19 100       9353 croak "$error" if $error;
99              
100             # remove initial stash keys like _STRICT, _DEBUG, inc, ...
101 17         75 $self->_purge_stash;
102              
103 17 100       107 return wantarray ? ( $ctx->stash, $output ) : $ctx->stash;
104             }
105              
106             sub _purge_stash {
107 17     17   40 my $self = shift;
108              
109 17         72 my @purge_keys = qw(
110             template
111             component
112             inc
113             dec
114             _PARENT
115             _STRICT
116             _DEBUG
117             );
118              
119 17         66 my $stash = $self->context->stash;
120              
121 17 50       197 if ( $stash->{_DEBUG} ) {
122 0         0 my $pkg = __PACKAGE__;
123              
124 0         0 warn "[${pkg}::_purge_stash] purging keys:\n";
125 0         0 warn join( ', ', @purge_keys ) . "\n";
126             }
127              
128 17         51 foreach my $key (@purge_keys) {
129              
130             #
131             # initial root VMethods inc, dec
132             #
133 119 100 100     694 if ( $key eq 'inc' || $key eq 'dec' ) {
134 34 50       143 delete $stash->{$key} if ref $stash->{$key} eq 'CODE';
135 34         60 next;
136             }
137              
138 85         234 delete $stash->{$key};
139             }
140             }
141              
142             =head1 SYNOPSIS
143              
144             use Config::TT2;
145              
146             my $ctt2 = Config::TT2->new;
147             my $cfg_stash = $ctt2->process($file);
148              
149             =head1 DESCRIPTION
150              
151             C<< Config::TT2 >> extends the C<< Template-Toolkit >> aka C<< TT2 >> in a very special way:
152              
153             It returns the B<< VARIABLES STASH >> instead of the template text!
154              
155             The TT2 syntax is very powerful, flexible and extensible. One of the key features of TT2 is the ability to bind template variables to any kind of Perl data: scalars, lists, hash arrays, sub-routines and objects.
156              
157             See L<< Template::Manual::Variables >> for a reference.
158              
159             E.g. this Template-Toolkit config
160              
161             [% # tt2 directive start-tag
162             scalar = 'string' # strings in single or double quotes
163              
164             array = [ 10 20 30 ] # commas are optional
165             rev = array.reverse # powerful virtual methods
166             item = array.0 # interpolate previous value
167              
168             hash = { foo = 'bar' # hashes to any depth
169             moo = array # points to above arrayref
170             }
171             %] # tt2 directive end-tag
172              
173             is returned as a perl datastructure:
174              
175             'scalar' => 'string'
176             'array' => ARRAY(0x8ad2708)
177             0 10
178             1 20
179             2 30
180             'rev' => ARRAY(0x8afe740)
181             0 30
182             1 20
183             2 10
184             'item' => 10
185             'hash' => HASH(0x8afe160)
186             'foo' => 'bar'
187             'moo' => ARRAY(0x8ad2708)
188             -> REUSED_ADDRESS
189              
190             =head1 METHODS
191              
192             =head2 new(%config)
193              
194             The C<< new() >> constructor method instantiates a new C object. This method croaks on error.
195              
196             Configuration items may be passed as a list of items or a hash array:
197              
198             my $ctt2 = Config::TT2->new(
199             ABSOLUTE => 0,
200             DEBUG => 'all',
201             );
202              
203             The supported configuration options are the same as for C<< Template >>, please see the L<< Template::Manual::Config >> as a reference and the LIMITATIONS section below.
204              
205             The preset default options which differ from the Template default options are:
206              
207             STRICT = 1 # undefined vars or values cause exceptions
208             ABSOLUTE = 1 # files with absolute filenames allowed
209             RELATIVE = 1 # files with relative filenames allowed
210             CACHE_SIZE = 0 # don't cache compiled config files
211              
212             =head2 process($config, $variables)
213              
214             The C<< process() >> method is called to process a config file or string. The first parameter indicates the input as one of: a filename; a reference to a text string containing the config text; or a file handle reference, from which the config can be read.
215              
216             A reference to a hash array may be passed as the second parameter, containing definitions of input variables.
217              
218             $stash = $ctt2->process( '.app.cfg', {foo => $ENV{APP_FOO}} );
219              
220             The returned datastructure is a C<< Template::Stash >> object. You may access the key and values through normal perl dereferencing:
221              
222             $item = $stash->{hash}{moo}[0];
223              
224             or via the C<< Template::Stash->get >> method like:
225              
226             $item = $stash->get('hash.moo.0');
227              
228             For debugging purposes you can even request the template output from the process method:
229              
230             ($stash, $output) = $ctt2->process( $config );
231              
232             The method croaks on error.
233              
234             =head1 LIMITATIONS
235              
236             The Template-Toolkit processor uses the toplevel variables C<< template >> und C<< component >> for meta information during template file processing. You B<< MUST NOT >> define or redefine these toplevel variables at object creation, processing or within the config files.
237              
238             See the section L<< Template::Manual::Variables/Special Variables >>.
239              
240             The C<< process >> method purges these toplevel variables unconditionally after processing but before returning the stash.
241              
242             See also the special meaning of the C<< global >> toplevel variable.
243              
244             Successive calls to C<< process >> with the same Config::TT2 instance B<< MUST >> be avoided. The Template CONTEXT and STASH have states belonging to the processed config text. Create new instances for successive C<< process >> calls.
245              
246             $stash1 = Config::TT2->new->process($file1);
247             $stash2 = Config::TT2->new->process($file2);
248              
249             The following Template options are not supported with Config::TT2:
250              
251             PRE_PROCESS
252             PROCESS
253             POST_PROCESS
254             WRAPPER
255             AUTO_RESET
256             DEFAULT
257             OUTPUT
258             OUTPUT_PATH
259             ERROR
260             ERRORS
261              
262             =head1 EXTENSIONS AND VIRTUAL METHODS
263              
264             With the C<< context >> method you can get/set the underlying Template::Context object.
265              
266             =head2 context()
267              
268             Getter/setter method for the underlying Template::Context object.
269              
270             With the context you can also access the stash and define new virtual methods BEFORE processing.
271              
272             $ctt2 = Config::TT2->new;
273             $ctt2->context->stash->define_vmethod( $type, $name, $code_ref );
274             $cfg_stash = $ctt2->process($cfg_file);
275              
276             See the manuals L<< Template::Stash >>, L<< Template::Context >> and L<< Template::Manual::Internals >>.
277              
278             =head1 SEE ALSO
279              
280             L<< Config::Any::TT2 >>, the corresponding L<< Config::Any >> plugin.
281              
282             L<< Template::Manual::Intro >>, L<< Template::Manual::Syntax >>, L<< Template::Manual::Config >>, L<< Template::Manual::Variables >>, L<< Template::Manual::VMethods >>
283              
284             =head1 AUTHOR
285              
286             Karl Gaissmaier, C<< >>
287              
288             =head1 BUGS
289              
290             Please report any bugs or feature requests to C, or through
291             the web interface at L. I will be notified, and then you'll
292             automatically be notified of progress on your bug as I make changes.
293              
294             =head1 SUPPORT
295              
296             You can find documentation for this module with the perldoc command.
297              
298             perldoc Config::TT2
299              
300              
301             You can also look for information at:
302              
303             =over 4
304              
305             =item * RT: CPAN's request tracker (report bugs here)
306              
307             L
308              
309             =item * AnnoCPAN: Annotated CPAN documentation
310              
311             L
312              
313             =item * CPAN Ratings
314              
315             L
316              
317             =item * Search CPAN
318              
319             L
320              
321             =back
322              
323             =head1 LICENSE AND COPYRIGHT
324              
325             Copyright 2012 Karl Gaissmaier.
326              
327             This program is free software; you can redistribute it and/or modify it
328             under the terms of either: the GNU General Public License as published
329             by the Free Software Foundation; or the Artistic License.
330              
331             See http://dev.perl.org/licenses/ for more information.
332              
333             =cut
334              
335             1; # End of Config::TT2
336              
337             # vim: sw=4