File Coverage

blib/lib/Dotiac/DTL/Addon/html_template/Replace.pm
Criterion Covered Total %
statement 148 232 63.7
branch 53 122 43.4
condition 13 32 40.6
subroutine 17 23 73.9
pod 0 4 0.0
total 231 413 55.9


line stmt bran cond sub pod time code
1             ###############################################################################
2             #Replace.pm
3             #Last Change: 2009-01-21
4             #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch
5             #Version 0.4
6             ####################
7             #This file is an addon to the Dotiac::DTL project.
8             #http://search.cpan.org/perldoc?Dotiac::DTL
9             #
10             #Replace.pm is published under the terms of the MIT license, which
11             #basically means "Do with it whatever you want". For more information, see the
12             #license.txt file that should be enclosed with this distribution. A copy of
13             #the license is (at the time of writing) also available at
14             #http://www.opensource.org/licenses/mit-license.php .
15             ###############################################################################
16            
17             package Dotiac::DTL::Addon::html_template::Replace;
18 2     2   45545 use warnings;
  2         5  
  2         56  
19 2     2   10 use strict;
  2         4  
  2         53  
20 2     2   2216 use Dotiac::DTL;
  2         73588  
  2         94  
21             require Dotiac::DTL::Addon::case_insensitive;
22             #use base qw/Dotiac::DTL::Template/;
23 2     2   18 use Carp;
  2         6  
  2         129  
24 2     2   11 use File::Spec;
  2         7  
  2         58  
25 2     2   10 use Scalar::Util qw/blessed reftype/;
  2         5  
  2         142  
26 2     2   12 use Carp qw/croak/;
  2         3  
  2         2285  
27             require File::Basename;
28            
29             our $VERSION = 0.4;
30            
31             our $COMBINE=0;
32            
33             sub import {
34 2     2   23 my $class=shift;
35 2 50 33     10020 if (@_ and (lc($_[0]) eq "combine" or lc($_[0]) eq ":combine")) {
      66        
36 1         2566 $COMBINE=1;
37             }
38             }
39            
40             sub _new {
41 38     38   52 my $class=shift;
42 38         37 my $parser=shift;
43 38         35 my $template=shift;
44 38         69 my $cs=shift;
45 38         46 my $ci=!$cs;
46 38         55 my $global=shift;
47 38         46 my $context=shift;
48 38         48 my $default=shift;
49 38         232 return bless [$template,$parser,$ci,$global,$context,$default],$class;
50            
51             }
52            
53             sub param {
54 42     42 0 212 my $self=shift;
55 42         126 return $self->[0]->param(@_);
56             }
57             sub output {
58 38     38 0 970 my $self=shift;
59 38         47 my $p=$Dotiac::DTL::PARSER;
60 38         73 $Dotiac::DTL::PARSER=$self->[1];
61 38         100 my @save=($Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars},$Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars},$Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape});
62 38         60 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars}=$self->[3];
63 38         63 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars}=$self->[4];
64 38         56 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape}=$self->[5];
65 38 100       127 Dotiac::DTL::Addon::case_insensitive->import() if $self->[2];
66 38         158 my $r;
67 38         47 $r="";
68 38 50       48 eval {
69 38 50 33     106 if (@_ and $_[0] eq "print_to") {
70 0         0 my $fh=select $_[1];
71 0         0 $self->[0]->print();
72 0         0 select $fh;
73             }
74             else {
75 38         106 $r=$self->[0]->string();
76             }
77 38         13355 1;
78             } or croak "Something went wrong in the output: $@";
79 38         153 $Dotiac::DTL::PARSER=$p;
80 38 100       149 Dotiac::DTL::Addon::case_insensitive->unimport() if $self->[2];
81 38         126 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars}=$save[0];
82 38         46 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars}=$save[1];
83 38         38 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape}=$save[2];
84 38         191 return $r;
85             }
86            
87             sub isa {
88 1     1 0 40 my $class=shift;
89 1         2 my $name=shift;
90 1 50       10 return 1 if $name eq "Dotiac::DTL::Template"; #Just lie about it.
91 0 0       0 return 1 if $name eq "HTML::Template"; #Just lie about it.
92 0         0 return $class->isa($name);
93             }
94            
95             sub query {
96 0     0 0 0 my $self=shift;
97 0         0 my @a=$self->[0]->param();
98 0 0 0     0 if (@_ and $_ eq "name") {
99 0         0 my $l=$_[0];
100 0 0       0 $l=$l->[-1] if ref $l;
101 0         0 $l=lc($l);
102 0 0       0 return "VAR" if grep { lc($_) eq $l } @a;
  0         0  
103             }
104 0 0 0     0 if (@_ and $_ eq "loop") {
105 0         0 my $l=$_[0];
106 0 0       0 $l=$l->[-1] if ref $l;
107 0         0 $l=lc($l);
108 0 0       0 return () if grep { lc($_) eq $l } @a;
  0         0  
109             }
110 0         0 return $self->[0]->param();
111             }
112            
113            
114             sub _filter {
115 2     2   4 my $data=shift;
116 2         4 my $filter=shift;
117 2 100       10 $filter=[$filter] unless ref $filter eq 'ARRAY';
118 2         3 foreach my $f (@{$filter}) {
  2         5  
119 2 100 66     22 if (ref ($f) eq "HASH" and $f->{"sub"} and ref $f->{"sub"} eq "CODE") {
    50 66        
120 1 50 33     14 if ($f->{format} and not ref $f->{format} and lc($f->{format}) eq "array") {
      33        
121 0         0 my @data=split /\n/,$data;
122 0         0 $f->{'sub'}->(\@data);
123 0         0 $data=join("\n",@data);
124             }
125             else {
126 1         6 $f->{'sub'}->(\$data);
127             }
128             }
129             elsif (ref ($f) eq "CODE") {
130 1         4 $f->(\$data);
131             }
132             }
133 2         47 return $data;
134             }
135            
136             sub _associate {
137 0     0   0 my $template=shift;
138 0         0 my $a=shift;
139 0         0 my @a=();
140 0 0       0 if (Scalar::Util::blessed($a)) {
141 0         0 @a=($a)
142             }
143             else {
144 0 0       0 @a=@{$a} if ref $a eq "ARRAY";
  0         0  
145             }
146 0         0 foreach my $obj (@a) {
147 0 0       0 next unless Scalar::Util::blessed($obj);
148 0 0       0 next unless $obj->can("param");
149 0         0 my @params=$obj->param();
150 0         0 foreach my $p (@params) {
151 0         0 $template->param($p,$obj->param($p));
152             }
153             }
154             }
155            
156             #package HTML::Template;
157            
158             #our
159             $HTML::Template::VERSION=2.9;
160            
161 2     2   17 no warnings qw/redefine/;
  2         5  
  2         1083  
162            
163             sub HTML::Template::_find_file { #like HTML::Template
164 2     2   3 my $o=shift;
165 2         5 my $file=$o->{filename};
166 2 50 33     30 return File::Spec->canonpath($file) if (File::Spec->file_name_is_absolute($file) and (-e $file));
167 2         6 foreach my $p (@_) {
168 0         0 my $path = File::Spec->catfile($p, $file);
169 0 0       0 return File::Spec->canonpath($path) if -e $path;
170             }
171 2 50       12 if (defined($ENV{HTML_TEMPLATE_ROOT})) {
172 0         0 my $path = File::Spec->catfile($ENV{HTML_TEMPLATE_ROOT}, $file);
173 0 0       0 return File::Spec->canonpath($path) if -e $path;
174             }
175 2 50       8 if ($o->{path}) {
176 0         0 foreach my $path (@{$o->{path}}) {
  0         0  
177 0         0 $path = File::Spec->catfile($path, $file);
178 0 0       0 return File::Spec->canonpath($path) if -e $path;
179             }
180             }
181 2 50       62 return File::Spec->canonpath($file) if -e $file;
182 0 0       0 if ($o->{path}) {
183 0 0       0 if (defined($ENV{HTML_TEMPLATE_ROOT})) {
184 0         0 foreach my $path (@{$o->{path}}) {
  0         0  
185 0         0 $path = File::Spec->catfile($ENV{HTML_TEMPLATE_ROOT},$path, $file);
186 0 0       0 return File::Spec->canonpath($path) if -e $path;
187             }
188             }
189             }
190 0         0 return undef;
191             }
192            
193            
194            
195             my %escapeflags = (
196             url=>"u",
197             js=>"j"
198             );
199            
200             sub HTML::Template::new_file {
201 0     0   0 my $class = shift;
202 0         0 return $class->HTML::Template::new('filename', @_);
203             }
204             sub HTML::Template::new_filehandle {
205 0     0   0 my $class = shift;
206 0         0 return $class->HTML::Template::new('filehandle', @_);
207             }
208             sub HTML::Template::new_array_ref {
209 0     0   0 my $class = shift;
210 0         0 return $class->HTML::Template::new('arrayref', @_);
211             }
212             sub HTML::Template::new_scalar_ref {
213 0     0   0 my $class = shift;
214 0         0 return $class->HTML::Template::new('scalarref', @_);
215             }
216            
217 2     2   13 use Carp qw/croak/;
  2         5  
  2         2527  
218            
219             sub HTML::Template::new {
220 38     38   27633 %Dotiac::DTL::Addon::html_template::Replace::include=();
221 38         66 my $class=shift;
222 38         94 my %opts=@_;
223 38         112 my @save=($Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars},$Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars},$Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape});
224 38         68 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars}=$opts{global_vars};
225 38         47 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars}=$opts{loop_context_vars};
226 38         48 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape}=$opts{default_escape};
227 38 100       163 Dotiac::DTL::Addon::case_insensitive->import() unless $opts{case_sensitive};
228 38         171 my $flags="";
229 38 100       81 $flags.=($opts{global_vars}?"g":"n");
230 38 100       69 $flags.=($opts{case_sensitive}?"s":"i");
231 38 100       61 $flags.=($opts{loop_context_vars}?"l":"c");
232 38 100 100     101 $flags.=($opts{default_escape}?($escapeflags{lc($opts{default_escape})}||"h"):"o");
233 38         45 my $parser="Dotiac::DTL::Addon::html_template";
234 38 100       87 $parser="Dotiac::DTL::Addon::html_template_pure" unless $Dotiac::DTL::Addon::html_template::Replace::COMBINE;
235 38         47 my $r = eval {
236 38 100       84 if ($opts{filename}) {
237 2 50       9 $flags=($Dotiac::DTL::Addon::html_template::Replace::COMBINE?"+":"-").$flags;
238 2         5 my @compile=();
239 2 50       9 push @compile,$opts{compile} if exists ($opts{compile});
240 2         10 my $file=HTML::Template::_find_file(\%opts);
241 2 50       8 croak "Can't find file: $opts{filename}" unless $file;
242 2 50       23 if (-e "$file$flags.html") { #If there is already a converted version, use it.
243 0 0       0 if ((stat("$file$flags.html"))[9] >= (stat("$file"))[9]) {
244             #if (-M "$file$flags.html" < -M $file) {
245 0         0 my $template=Dotiac::DTL->new("$file$flags.html",@compile);
246 0 0       0 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
247 0         0 return $template;
248             }
249             }
250 2 50       19 if (-e "$file$flags.htm") { #If there is already a filtered version, use it.
251 0 0       0 if ((stat("$file$flags.htm"))[9] >= (stat("$file"))[9]) {
252 0         0 my $p=$Dotiac::DTL::PARSER;
253 0         0 $Dotiac::DTL::PARSER=$parser;
254 0         0 my $template=Dotiac::DTL->new("$file$flags.htm",@compile);
255 0 0       0 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
256 0         0 $Dotiac::DTL::PARSER=$p;
257 0         0 return Dotiac::DTL::Addon::html_template::Replace->_new($parser,$template,$opts{case_sensitive},$opts{global_vars},$opts{loop_context_vars},$opts{default_escape});
258            
259             }
260             }
261 2 100       7 if ($opts{filter}) {
262             #Not good!
263 1 50       55 open my $fh, "<",$file or croak "Can't open $file: $!";
264 1         2 my $data=do {local $/;<$fh>};
  1         5  
  1         49  
265 1         43 close $fh;
266 1         5 $data=Dotiac::DTL::Addon::html_template::Replace::_filter($data,$opts{filter});
267 1         36 my @f = File::Basename::fileparse($file);
268 1 50       106 if (open my $fh,">","$file$flags.htm") {
269 1         24 print $fh $data;
270 1         78 close $fh;
271 1         2 my $p=$Dotiac::DTL::PARSER;
272 1         2 $Dotiac::DTL::PARSER=$parser;
273 1         10 my $template=Dotiac::DTL->new("$file$flags.htm",@compile);
274 1 50       61 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
275 1         4 $Dotiac::DTL::PARSER=$p;
276 1         11 return Dotiac::DTL::Addon::html_template::Replace->_new($parser,$template,$opts{case_sensitive},$opts{global_vars},$opts{loop_context_vars},$opts{default_escape});
277             }
278             else {
279 0         0 my $p=$Dotiac::DTL::PARSER;
280 0         0 $Dotiac::DTL::PARSER=$parser;
281 0         0 $Dotiac::DTL::CURRENTDIR=$f[1];
282 0         0 my $template=Dotiac::DTL->new(\$data);
283 0 0       0 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
284 0         0 $Dotiac::DTL::PARSER=$p;
285 0         0 return Dotiac::DTL::Addon::html_template::Replace->_new($parser,$template,$opts{case_sensitive},$opts{global_vars},$opts{loop_context_vars},$opts{default_escape});
286             }
287             }
288 1         4 my $p=$Dotiac::DTL::PARSER;
289 1         4 $Dotiac::DTL::PARSER=$parser;
290 1         10 my $template=Dotiac::DTL->new($file,@compile); #Flags are ignored, unstable, but fast.
291 1 50       67 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
292 1         2 $Dotiac::DTL::PARSER=$p;
293 1         12 return Dotiac::DTL::Addon::html_template::Replace->_new($parser,$template,$opts{case_sensitive},$opts{global_vars},$opts{loop_context_vars},$opts{default_escape});
294             }
295 36 100       62 if ($Dotiac::DTL::Addon::html_template::Replace::COMBINE) { #We have to put the flags in here to confuse the Dotiac::DTL::Caching stuff if they change.
296 3         7 $flags="{# $flags #}";
297             }
298             else {
299 33         51 $flags="";
300             }
301 36         34 my $data;
302 36 50       98 if ($opts{filehandle}) {
    50          
    0          
303 0         0 my $fh=$opts{filehandle};
304 0         0 $data=do {local $/;<$fh>};
  0         0  
  0         0  
305             }
306             elsif ($opts{scalarref}) {
307 36         57 $data=${$opts{scalarref}}; #Have to deref here for conversion
  36         84  
308             }
309             elsif ($opts{arrayref}) {
310 0         0 $data=join("",@{$opts{arrayref}});
  0         0  
311             }
312 36 100       82 $data=Dotiac::DTL::Addon::html_template::Replace::_filter($data,$opts{filter}) if $opts{filter};
313 36         57 $data=$data.$flags;
314 36         42 my $p=$Dotiac::DTL::PARSER;
315 36         40 $Dotiac::DTL::PARSER=$parser;
316 36         130 my $template=Dotiac::DTL->new(\$data);
317 36         1728 $Dotiac::DTL::PARSER=$p;
318 36 50       80 Dotiac::DTL::Addon::html_template::Replace::_associate($template,$opts{associate}) if $opts{associate};
319 36         197 return Dotiac::DTL::Addon::html_template::Replace->_new($parser,$template,$opts{case_sensitive},$opts{global_vars},$opts{loop_context_vars},$opts{default_escape});
320             };
321 38         108 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{global_vars}=$save[0];
322 38         47 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{loop_context_vars}=$save[1];
323 38         50 $Dotiac::DTL::Addon::html_template_pure::OPTIONS{default_escape}=$save[2];
324 38 100       152 Dotiac::DTL::Addon::case_insensitive->unimport() unless $opts{case_sensitive};
325 38 50       278 return $r if $r;
326 0           croak "Something went wrong while generating the template: $@";
327             }
328            
329            
330            
331             1;
332            
333             __END__