File Coverage

blib/lib/Template/Provider/FromDATA.pm
Criterion Covered Total %
statement 73 73 100.0
branch 17 18 94.4
condition 2 2 100.0
subroutine 10 10 100.0
pod 2 2 100.0
total 104 105 99.0


line stmt bran cond sub pod time code
1             package Template::Provider::FromDATA;
2              
3 9     9   367107 use base qw( Template::Provider Class::Accessor::Fast );
  9         27  
  9         11734  
4              
5 9     9   80451 use strict;
  9         23  
  9         265  
6 9     9   50 use warnings;
  9         27  
  9         554  
7              
8 9     9   51 use Template::Constants;
  9         22  
  9         7025  
9              
10             =head1 NAME
11              
12             Template::Provider::FromDATA - Load templates from your __DATA__ section
13              
14             =head1 SYNOPSIS
15              
16             use Template;
17             use Template::Provider::FromDATA;
18            
19             # Create the provider
20             my $provider = Template::Provider::FromDATA->new( {
21             CLASSES => __PACKAGE__
22             } );
23            
24             # Add the provider to the config
25             my $template = Template->new( {
26             # ...
27             LOAD_TEMPLATES => [ $provider ]
28             } );
29              
30             # Render a template
31             $template->process( 'mytemplate', { bar => 'Bar' } );
32              
33             # ...and now the templates
34            
35             __DATA__
36            
37             __mytemplate__
38             Foo [% bar %]
39            
40             __myothertemplate__
41             Baz, [% qux %]?
42              
43             =head1 DESCRIPTION
44              
45             This module allows you to store your templates inline with your
46             code in the C<__DATA__> section. It will search any number of classes
47             specified.
48              
49             =head1 CAVEAT
50              
51             If you have two templates with the same name, this module will not understand
52             the difference, it will simply return the first one found. If you wish, you
53             can specify a fully qualified template name by prefixing the template with the
54             module name (using C<-> instead of C<::> as a namespace separator), adding
55             a C to separate the module name from the template name.
56              
57             $template->process( 'My-Templates/mytemplate', { bar => 'Bar' } );
58              
59             =head1 INSTALLATION
60              
61             perl Makefile.PL
62             make
63             make test
64             make install
65              
66             =cut
67              
68             __PACKAGE__->mk_accessors( qw( cache classes ) );
69              
70             our $VERSION = '0.13';
71              
72             =head1 METHODS
73              
74             =head2 new( \%OPTIONS )
75              
76             Create a new instance of the provider. You can specify a list of classes to
77             be searched for templates via the C option. By omitting this option
78             it will search C
.
79              
80             # defaults to 'main'
81             $provider = Template::Provider::FromDATA->new;
82            
83             # look for templates in 'Foo'
84             $provider = Template::Provider::FromDATA->new( {
85             CLASSES => 'Foo'
86             } );
87              
88             # look for templates in 'Foo::Bar' and 'Foo::Baz'
89             $provider = Template::Provider::FromDATA->new( {
90             CLASSES => [ 'Foo::Bar', 'Foo::Baz' ]
91             } );
92              
93             By default, template data is lazy-loaded as they it is requested. If you
94             wish to load up all template data upon initializtion, you can use the
95             C option.
96              
97             $provider = Template::Provider::FromDATA->new( {
98             PRELOAD => 1
99             } );
100              
101             =head2 _init( \%OPTIONS )
102              
103             A subclassed method to handle the options passed to C.
104              
105             =cut
106              
107             sub _init {
108 9     9   6092 my( $self, $args ) = @_;
109 9         24 my $classes = delete $args->{ CLASSES };
110 9   100     104 $classes ||= [ 'main' ];
111 9 100       47 $classes = [ $classes ] if not ref $classes;
112            
113 9         20 for( @$classes ) {
114 10         737 eval "require $_";
115             }
116              
117 9         77 $self->classes( $classes );
118 9         176 $self->cache( { classes => {}, templates => {} } );
119              
120 9 100       101 if( delete $args->{ PRELOAD } ) {
121 1         6 $self->_cache_class( $_ ) for @$classes;
122             }
123              
124 9         84 return $self->SUPER::_init;
125             }
126              
127             =head2 fetch( $name )
128              
129             This is a subclassed method that will load a template via C<_fetch()>
130             if a non-reference argument is passed.
131              
132             =cut
133              
134             sub fetch {
135 16     16 1 258493 my( $self, $name ) = @_;
136              
137 16 100       83 return undef, Template::Constants::STATUS_DECLINED if ref $name;
138              
139 15         140 my( $data, $error ) = $self->_fetch( $name );
140 15         227020 return $data, $error;
141             }
142              
143             =head2 _load( $name )
144              
145             Loads the template via the C sub and sets some cache
146             information.
147              
148             =cut
149              
150             sub _load {
151 10     10   357 my( $self, $name ) = @_;
152 10         30 my $data = {};
153 10         55 my $classes = $self->classes;
154 10         70 my( $content, $error );
155              
156             # handle fully qualified names
157 10 100       50 if( $name =~ m{/} ) {
158 2         11 my( $class, $template ) = split( m{/}, $name, 2 );
159 2         11 $class =~ s{-}{::}g;
160 2         6 $classes = [ $class ];
161 2         7 $name = $template;
162             }
163              
164 10         30 for my $class ( @$classes ) {
165 10         49 $content = $self->get_file( $class, $name );
166 10 100       40 last if $content;
167             }
168              
169 10         61 my $time = time;
170 10         31 $data->{ time } = $time;
171 10         23 $data->{ load } = $time;
172 10         20 $data->{ name } = $name;
173 10         39 $data->{ text } = $content;
174              
175 10 100       38 $error = Template::Constants::STATUS_DECLINED if !$content;
176              
177 10         41 return $data, $error;
178             }
179              
180             =head2 get_file( $class, $template )
181              
182             This method searches through C<$class> for a template
183             named C<$template>. Returns the contents on success, undef
184             on failure.
185              
186             This function was mostly borrowed from L's
187             C function.
188              
189             =cut
190              
191             sub get_file {
192 10     10 1 32 my( $self, $class, $template ) = @_;
193              
194 10         43 my $cache = $self->cache;
195 10         78 my $key = "${class}/${template}";
196              
197 10 100       72 $self->_cache_class( $class ) unless $cache->{ classes }->{ $class };
198              
199 10 100       49 if( exists $cache->{ templates }->{ $key } ) {
200 9         33 return $cache->{ templates }->{ $key };
201             }
202              
203 1         2 return undef;
204             }
205              
206             sub _cache_class {
207 9     9   28 my( $self, $class ) = @_;
208              
209 9         64 my $cache = $self->cache;
210              
211 9 50       92 return if $cache->{ classes }->{ $class };
212              
213 9     9   62 no strict 'refs';
  9         27  
  9         2147  
214 9         18 my $fh = \*{"${class}\::DATA"};
  9         48  
215 9         30 my $pos = tell( $fh );
216 9         15 my $filecache = do { local $/; <$fh>; };
  9         47  
  9         237  
217 9         64 seek( $fh, $pos, 0 );
218 9         36 $cache->{ classes }->{ $class }++;
219              
220 9         123 my @files = split /^__(.+)__\r?\n/m, $filecache;
221 9         27 shift @files;
222 9         44 while (@files) {
223 11         40 my( $name, $content ) = splice @files, 0, 2;
224 11         145 my $key = "${class}/${name}";
225 11         67 $cache->{ templates }->{ $key } = $content;
226             }
227             }
228              
229             =head1 ACCESSORS
230              
231             =head2 classes
232              
233             An arrayref of the class names containing our templates.
234              
235             =head2 cache
236              
237             A hashref of file and template data.
238              
239             =head1 AUTHOR
240              
241             Brian Cassidy Ebricas@cpan.orgE
242              
243             =head1 COPYRIGHT AND LICENSE
244              
245             Copyright 2005-2012 by Brian Cassidy
246              
247             This library is free software; you can redistribute it and/or modify
248             it under the same terms as Perl itself.
249              
250             =cut
251              
252             1;