File Coverage

lib/Petal.pm
Criterion Covered Total %
statement 298 324 91.9
branch 126 162 77.7
condition 25 53 47.1
subroutine 45 52 86.5
pod 11 14 78.5
total 505 605 83.4


line stmt bran cond sub pod time code
1             # ------------------------------------------------------------------
2             # Petal - Perl Template Attribute Language
3             # ------------------------------------------------------------------
4             # Author: Jean-Michel Hiver
5             # Description: Front-end for all Petal templating functionality
6             # ------------------------------------------------------------------
7             package Petal;
8 77     77   1158997 use Petal::Hash;
  77         107  
  77         3852  
9 77     77   23810 use Petal::Cache::Disk;
  77         751  
  77         4828  
10 77     77   21442 use Petal::Cache::Memory;
  77         782  
  77         3075  
11 77     77   19871 use Petal::Parser;
  77         152  
  77         1962  
12 77     77   335 use Petal::Canonicalizer::XML;
  77         125  
  77         1049  
13 77     77   224 use Petal::Canonicalizer::XHTML;
  77         77  
  77         1083  
14 77     77   19006 use Petal::Functions;
  77         94  
  77         1706  
15 77     77   19160 use Petal::Entities;
  77         128  
  77         2121  
16 77     77   343 use File::Spec;
  77         74  
  77         1162  
17 77     77   208 use Carp;
  77         97  
  77         3667  
18 77     77   40770 use Data::Dumper;
  77         498267  
  77         4208  
19 77     77   384 use Scalar::Util;
  77         83  
  77         2264  
20 77     77   277 use strict;
  77         99  
  77         1264  
21 77     77   221 use warnings;
  77         80  
  77         1507  
22 77     77   259 use MKDoc::XML::Decode;
  77         67  
  77         1124  
23 77     77   19923 use Petal::I18N;
  77         117  
  77         3214  
24              
25              
26             BEGIN
27             {
28 77 50   77   349 ($] > 5.007) and do {
29 77         36451 require Encode;
30             };
31 77 50       519342 $@ and warn $@;
32             }
33              
34              
35              
36             # these are used as local variables when the XML::Parser
37             # is crunching templates...
38 77     77   392 use vars qw /@tokens @nodeStack/;
  77         95  
  77         230261  
39              
40              
41             # HTML errors?
42             our $HTML_ERRORS = undef;
43              
44              
45             # Encode / Decode info...
46             our $DECODE_CHARSET = 'utf8';
47             our $ENCODE_CHARSET = 'utf8'; # deprecated
48              
49              
50             # Prints as much info as possible when this is enabled.
51             our $DEBUG_DUMP = 1;
52              
53              
54             # Warn about uninitialised values in the template?
55             our $WARN_UNINIT = 0;
56              
57              
58             # What do we use to parse input?
59             our $INPUT = 'XML';
60             our $INPUTS = {
61             'XML' => 'Petal::Parser',
62             'HTML' => 'Petal::Parser',
63             'XHTML' => 'Petal::Parser',
64             };
65              
66              
67             # What do we use to format output?
68             our $OUTPUT = 'XML';
69             our $OUTPUTS = {
70             'XML' => 'Petal::Canonicalizer::XML',
71             'HTML' => 'Petal::Canonicalizer::XHTML',
72             'XHTML' => 'Petal::Canonicalizer::XHTML',
73             };
74              
75              
76             # makes taint mode happy if set to 1
77             our $TAINT = undef;
78              
79              
80             # don't confess() errors if we access an undefined template variable
81             our $ERROR_ON_UNDEF_VAR = 1;
82              
83              
84             # where are our templates supposed to be?
85             our @BASE_DIR = ('.');
86             our $BASE_DIR = undef; # for backwards compatibility...
87              
88              
89             # vroom!
90             our $DISK_CACHE = 1;
91              
92              
93             # vroom vroom!
94             our $MEMORY_CACHE = 1;
95              
96              
97             # cache only mode
98             our $CACHE_ONLY = 0;
99              
100              
101             # prevents infinites includes...
102             our $MAX_INCLUDES = 30;
103             our $CURRENT_INCLUDES = 0;
104              
105              
106             # this is for CPAN
107             our $VERSION = '2.24';
108              
109              
110             # The CodeGenerator class backend to use.
111             # Change this only if you know what you're doing.
112             our $CodeGenerator = 'Petal::CodeGenerator';
113             our $CodeGeneratorLoaded = 0;
114              
115             # Default language for multi-language mode.
116             # Change if you feel that English isn't a fair default.
117             our $LANGUAGE = 'en';
118              
119              
120             # this is for XML namespace support. Can't touch this :-)
121             our $NS = 'petal';
122             our $NS_URI = 'http://purl.org/petal/1.0/';
123              
124             our $XI_NS = 'xi';
125             our $XI_NS_URI = 'http://www.w3.org/2001/XInclude';
126              
127             our $MT_NS = 'metal';
128             our $MT_NS_URI = 'http://xml.zope.org/namespaces/metal';
129             our $MT_NAME_CUR = 'main';
130              
131             # translation service, optional
132             our $TranslationService = undef;
133              
134              
135             # Displays the canonical template for template.xml.
136             # You can set $INPUT using by setting the PETAL_INPUT environment variable.
137             # You can set $OUTPUT using by setting the PETAL_OUTPUT environment variable.
138             sub main::canonical
139             {
140 0     0   0 my $file = shift (@ARGV);
141 0         0 local $Petal::DISK_CACHE = 0;
142 0         0 local $Petal::MEMORY_CACHE = 0;
143 0         0 local $Petal::CACHE_ONLY = 0;
144 0   0     0 local $Petal::INPUT = $ENV{PETAL_INPUT} || 'XML';
145 0   0     0 local $Petal::OUTPUT = $ENV{PETAL_OUTPUT} || 'XHTML';
146 0         0 print ${Petal->new ($file)->_canonicalize()};
  0         0  
147             }
148              
149              
150             # Displays the perl code for template.xml.
151             # You can set $INPUT using by setting the PETAL_INPUT environment variable.
152             # You can set $OUTPUT using by setting the PETAL_OUTPUT environment variable.
153             sub main::code
154             {
155 0     0   0 my $file = shift (@ARGV);
156 0         0 local $Petal::DISK_CACHE = 0;
157 0         0 local $Petal::MEMORY_CACHE = 0;
158 0         0 local $Petal::CACHE_ONLY = 0;
159 0         0 print Petal->new ($file)->_code_disk_cached;
160             }
161              
162              
163             # Displays the perl code for template.xml, with line numbers.
164             # You can set $INPUT using by setting the PETAL_INPUT environment variable.
165             # You can set $OUTPUT using by setting the PETAL_OUTPUT environment variable.
166             sub main::lcode
167             {
168 0     0   0 my $file = shift (@ARGV);
169 0         0 local $Petal::DISK_CACHE = 0;
170 0         0 local $Petal::MEMORY_CACHE = 0;
171 0         0 local $Petal::CACHE_ONLY = 0;
172 0         0 print Petal->new ($file)->_code_with_line_numbers;
173             }
174              
175              
176             sub load_code_generator
177             {
178 1620 100   1620 0 2960 if (not $CodeGeneratorLoaded)
179             {
180 73         3315 eval "require $CodeGenerator";
181 73 50       339 confess "Failed to load $CodeGenerator, $@" if $@;
182 73         215 $CodeGeneratorLoaded = 1;
183             }
184             }
185              
186              
187             # Instanciates a new Petal object.
188             sub new
189             {
190 215     215 0 46886 my $class = shift;
191 215   33     923 $class = ref $class || $class;
192 215 100       675 unshift (@_, 'file') if (@_ == 1);
193 215         599 my $self = bless { @_ }, $class;
194 215         477 $self->_initialize();
195            
196 215         683 return $self;
197             }
198              
199              
200             # (multi language mode)
201             # if the language has been specified, let's try to
202             # find which template we can use.
203             sub _initialize
204             {
205 215     215   248 my $self = shift;
206 215         460 my $file = $self->{file};
207 215 100       608 if ($file =~ /#/)
208             {
209 20         58 my ($file, $macro) = split /#/, $file, 2;
210 20         35 $self->{file} = $file;
211 20         67 $self->_initialize_lang();
212 20         56 $self->{file} .= "#$macro";
213             }
214             else
215             {
216 195         441 $self->_initialize_lang();
217             }
218             }
219              
220              
221             sub _initialize_lang
222             {
223 215     215   225 my $self = shift;
224 215   100     426 my $lang = $self->language() || return;
225 16         32 my @dirs = $self->base_dir();
226 16         21 @dirs = map { File::Spec->canonpath ("$_/$self->{file}") } @dirs;
  18         98  
227            
228 16         29 $self->{file} =~ s/\/$//;
229 16         41 my $filename = Petal::Functions::find_filename ($lang, @dirs);
230 16 50       66 $self->{file} .= "/$filename" if ($filename);
231             }
232              
233              
234             # (multi language mode)
235             # returns the current preferred language.
236             sub language
237             {
238 318     318 1 335 my $self = shift;
239 318   66     1290 return $self->{language} || $self->{lang};
240             }
241              
242              
243 0 0   0 1 0 sub default_language { exists $_[0]->{default_language} ? $_[0]->{default_language} : $LANGUAGE }
244 1 50   1 1 12 sub input { exists $_[0]->{input} ? $_[0]->{input} : $INPUT }
245 0 0   0 1 0 sub output { exists $_[0]->{output} ? $_[0]->{output} : $OUTPUT }
246 4 100   4 1 30 sub taint { exists $_[0]->{taint} ? $_[0]->{taint} : $TAINT }
247 0 0   0 1 0 sub error_on_undef_var { exists $_[0]->{error_on_undef_var} ? $_[0]->{error_on_undef_var} : $ERROR_ON_UNDEF_VAR }
248 4 100   4 1 34 sub disk_cache { exists $_[0]->{disk_cache} ? $_[0]->{disk_cache} : $DISK_CACHE }
249 4 100   4 1 25 sub memory_cache { exists $_[0]->{memory_cache} ? $_[0]->{memory_cache} : $MEMORY_CACHE }
250 4 100   4 1 24 sub cache_only { exists $_[0]->{cache_only} ? $_[0]->{cache_only} : $CACHE_ONLY }
251 4 100   4 1 31 sub max_includes { exists $_[0]->{max_includes} ? $_[0]->{max_includes} : $MAX_INCLUDES }
252              
253              
254             sub base_dir
255             {
256 257     257 1 269 my $self = shift;
257 257 50       474 return map { defined $_ ? $_ : () } $self->_base_dir();
  436         1040  
258             }
259              
260              
261             sub _base_dir
262             {
263 257     257   271 my $self = shift;
264 257 100       453 if (exists $self->{base_dir})
265             {
266 48         52 my $base_dir = $self->{base_dir};
267 48 100       76 if (ref $base_dir) { return @{$base_dir} }
  3         2  
  3         5  
268             else
269             {
270 45 50       77 die '\$self->{base_dir} is not defined' unless (defined $base_dir);
271 45         75 return $base_dir;
272             }
273             }
274             else
275             {
276 209 100       376 if (defined $BASE_DIR) { return ( $BASE_DIR, @BASE_DIR ) }
  200         405  
277 9         17 else { return @BASE_DIR }
278             }
279             }
280              
281              
282             # _include_compute_path ($path);
283             # ------------------------------
284             # Computes the new absolute path from the current
285             # path and $path
286             sub _include_compute_path
287             {
288 71     71   69 my $self = shift;
289 71         52 my $file = shift;
290            
291             # this is for metal self-includes
292 71 100       150 if ($file =~ /^#/)
293             {
294 2         4 $file = $self->{file} . $file;
295             }
296            
297 71 100       241 return $file unless ($file =~ /^\./);
298            
299 18         30 my $path = $self->{file};
300 18         44 ($path) = $path =~ /(.*)\/.*/;
301 18   100     61 $path ||= '.';
302 18         22 $path .= '/';
303 18         25 $path .= $file;
304            
305 18         86 my @path = split /\//, $path;
306 18         21 my @new_path = ();
307 18         37 while (scalar @path)
308             {
309 52         49 my $next = shift (@path);
310 52 100       104 next if $next eq '.';
311            
312 27 100       63 if ($next eq '..')
313             {
314 3 100       30 die "Cannot go above base directory: $file" if (scalar @new_path == 0);
315 1         2 pop (@new_path);
316 1         2 next;
317             }
318            
319 24         48 push @new_path, $next;
320             }
321            
322 16         51 return join '/', @new_path;
323             }
324              
325              
326             # Processes the current template object with the information contained in
327             # %hash. This information can be scalars, hash references, array
328             # references or objects.
329             #
330             # Example:
331             #
332             # my $data_out = $template->process (
333             # user => $user,
334             # page => $page,
335             # basket => $shopping_basket,
336             # );
337             #
338             # print "Content-Type: text/html\n\n";
339             # print $data_out;
340             sub process
341             {
342 204     204 0 14776 my $self = shift;
343 204         457 $self->_process_absolutize_pathes();
344            
345             # ok, from there on we need to override any global variable with stuff
346             # that might have been specified when constructing the object
347 204 50       437 local $TAINT = defined $self->{taint} ? $self->{taint} : $TAINT;
348 204 50       419 local $ERROR_ON_UNDEF_VAR = defined $self->{error_on_undef_var} ? $self->{error_on_undef_var} : $ERROR_ON_UNDEF_VAR;
349 204 100       492 local $DISK_CACHE = defined $self->{disk_cache} ? $self->{disk_cache} : $DISK_CACHE;
350 204 100       390 local $MEMORY_CACHE = defined $self->{memory_cache} ? $self->{memory_cache} : $MEMORY_CACHE;
351 204 100       355 local $CACHE_ONLY = defined $self->{cache_only} ? $self->{cache_only} : $CACHE_ONLY;
352 204 100       367 local $MAX_INCLUDES = defined $self->{max_includes} ? $self->{max_includes} : $MAX_INCLUDES;
353 204 100       486 local $INPUT = defined $self->{input} ? $self->{input} : $INPUT;
354 204 100       413 local $OUTPUT = defined $self->{output} ? $self->{output} : $OUTPUT;
355 204 100       416 local $BASE_DIR = defined $self->{base_dir} ? do { ref $self->{base_dir} ? undef : $self->{base_dir} } : $BASE_DIR;
  20 100       47  
356 204 100       581 local @BASE_DIR = defined $self->{base_dir} ? do { ref $self->{base_dir} ? @{$self->{base_dir}} : () } : @BASE_DIR;
  20 100       63  
  1         2  
357 204 50       533 local $LANGUAGE = defined $self->{default_language} ? $self->{default_language} : $LANGUAGE;
358 204 50       393 local $DEBUG_DUMP = defined $self->{debug_dump} ? $self->{debug_dump} : $DEBUG_DUMP;
359 204 100       459 local $DECODE_CHARSET = defined $self->{decode_charset} ? $self->{decode_charset} : $DECODE_CHARSET;
360 204 100       431 local $TranslationService = defined $self->{translation_service} ? $self->{translation_service} : $TranslationService;
361             # local $ENCODE_CHARSET = defined $self->{encode_charset} ? $self->{encode_charset} : $ENCODE_CHARSET;
362              
363             # prevent infinite includes from happening...
364 204         232 my $current_includes = $CURRENT_INCLUDES;
365 204 100       475 return "ERROR: MAX_INCLUDES : $CURRENT_INCLUDES" if ($CURRENT_INCLUDES > $MAX_INCLUDES);
366 202         285 local $CURRENT_INCLUDES = $current_includes + 1;
367            
368 202         198 my $res = undef;
369 202         260 eval {
370 202         200 my $hash = undef;
371 202 100       573 if (ref $_[0] eq 'Petal::Hash') { $hash = shift }
  69 100       86  
372 14         16 elsif (ref $_[0] eq 'HASH') { $hash = new Petal::Hash (%{shift()}) }
  14         81  
373 119         599 else { $hash = new Petal::Hash (@_) }
374            
375 202         451 my $coderef = $self->_code_memory_cached;
376 195 50       535 die "\$coderef is undefined\n\n" unless $coderef;
377 195 50       377 die "\$hash is undefined\n\n" unless $hash;
378 195         1822 $res = $coderef->($hash);
379             };
380            
381 202 100       3567 if ( $CACHE_ONLY == 1 ){ return 1; }
  2         15  
382            
383 200 100 33     1174 if (defined $@ and $@) { $res = $self->_handle_error ($@) }
  9 100 66     30  
384 5         29 elsif (defined $TranslationService && $CURRENT_INCLUDES == 1) { $res = Petal::I18N->process ($res) }
385              
386 192         2007 return $res;
387             }
388              
389              
390             # File::Spec->rel2abs() is pretty slow since it uses Cwd which does a
391             # super-ugly backtick. Hence this method absolutizes base directories
392             # only once. It is necessary to work with absolute base directories to
393             # avoid cache conflicts.
394             sub _process_absolutize_pathes
395             {
396 204     204   226 my $self = shift;
397            
398 204 100       445 if (defined $BASE_DIR)
399             {
400 177 100       3129 $BASE_DIR = File::Spec->rel2abs ($BASE_DIR) unless (
401             File::Spec->file_name_is_absolute ($BASE_DIR)
402             );
403             }
404            
405 194 100       1833 @BASE_DIR = ( map { File::Spec->file_name_is_absolute ($_) ? $_ : File::Spec->rel2abs ($_) }
406 204 50       419 map { defined $_ ? $_ : () } @BASE_DIR );
  194         540  
407            
408 204 100       574 if (defined $self->{base_dir})
409             {
410 20 100       49 if (ref $self->{base_dir})
411             {
412             $self->{base_dir} = [
413 2 50       27 map { File::Spec->file_name_is_absolute ($_) ? $_ : File::Spec->rel2abs ($_) }
414 2 50       6 map { defined $_ ? $_ : () } @{$self->{base_dir}}
  1         58  
415 1 50       5 ] if (defined $self->{base_dir});
416             }
417             else
418             {
419             $self->{base_dir} = File::Spec->rel2abs ($self->{base_dir}) unless (
420             File::Spec->file_name_is_absolute ($self->{base_dir})
421 19 50       316 );
422             }
423             }
424             }
425              
426              
427             sub _handle_error
428             {
429 9     9   13 my $self = shift;
430 9         12 my $error = shift;
431              
432 9 100       21 $Petal::HTML_ERRORS and do {
433 1         2 my $res = '
'; 
434 1         3 $res .= "Error: $error\n";
435 1         2 $res .= "=============\n";
436 1         2 $res .= "\n\n";
437 1         21 $res .= "Petal object dump:\n";
438 1         2 $res .= "==================\n";
439 1         4 $res .= Dumper ($self);
440 1         81 $res .= "\n\n";
441 1         2 $res .= "Stack trace:\n";
442 1         1 $res .= "============\n";
443 1         119 $res .= Carp::longmess();
444 1         105 $res .= "\n\n";
445 1         2 $res .= "Template perl code dump:\n";
446 1         1 $res .= "========================\n";
447              
448 1         2 my $dump = eval { $self->_code_with_line_numbers() };
  1         3  
449 1 50       367 $res .= ($dump) ? $dump : "(no dump available)";
450            
451 1         2 $res .= '';
452 1         3 return $res;
453             };
454            
455 8 100       17 $Petal::DEBUG_DUMP and do {
456 7         98 my $tmpdir = File::Spec->tmpdir();
457 7         46 my $tmpfile = $$ . '.' . time() . '.' . ( join '', map { chr (ord ('a') + int (rand (26))) } 1..10 );
  70         169  
458 7         14 my $debug = "$tmpdir/petal_debug.$tmpfile";
459            
460 7   50     884 open ERROR, ">$debug" || die "Cannot write-open \">$debug\"";
461            
462 7         64 print ERROR "Error: $error\n";
463 7 50       19 ref $error and do {
464 0         0 print ERROR "=============\n";
465             };
466 7         10 print ERROR "\n";
467            
468 7         10 print ERROR "Petal object dump:\n";
469 7         9 print ERROR "==================\n";
470 7         26 print ERROR Dumper ($self);
471 7         481 print ERROR "\n\n";
472            
473 7         9 print ERROR "Stack trace:\n";
474 7         7 print ERROR "============\n";
475 7         524 print ERROR Carp::longmess();
476 7         810 print ERROR "\n\n";
477            
478 7         9 print ERROR "Template perl code dump:\n";
479 7         8 print ERROR "========================\n";
480 7         6 my $dump = eval { $self->_code_with_line_numbers() };
  7         23  
481 7 100       1286 ($dump) ? print ERROR $dump : print ERROR "(no dump available)";
482            
483 7         68 die "[PETAL ERROR] $error. Debug info written in $debug";
484             };
485            
486 1 50       5 ! $Petal::DEBUG_DUMP and do {
487 1         14 die "[PETAL ERROR] $error. No debug info written.";
488             };
489             }
490              
491              
492             # $self->code_with_line_numbers;
493             # ------------------------------
494             # utility method to return the Perl code, each line being prefixed with
495             # its number... handy for debugging templates. The nifty line number padding
496             # patch was provided by Lucas Saud .
497             sub _code_with_line_numbers
498             {
499 8     8   9 my $self = shift;
500 8         15 my $code = $self->_code_disk_cached;
501              
502             # get lines of code
503 1         36 my @lines = split(/\n/, $code);
504              
505             # add line numbers
506 1         2 my $count = 0;
507             @lines = map {
508 1         2 my $cur_line = $_;
  85         50  
509 85         40 $count++;
510            
511             # space padding so the line numbers nicely line up with each other
512 85         114 my $line_num = sprintf ("%" . length(scalar(@lines)) . "d", $count);
513            
514             # put line number and line back together
515 85         113 "${line_num}. ${cur_line}";
516             } @lines;
517            
518 1         17 return join("\n", @lines);
519             }
520              
521              
522             # $self->_file;
523             # -------------
524             # setter / getter for the 'file' attribute
525             sub _file
526             {
527 540     540   440 my $self = shift;
528 540 50       1075 $self->{file} = shift if (@_);
529 540         702 $self->{file} =~ s/^\///;
530 540         672 return $self->{file};
531             }
532              
533              
534             sub _macro
535             {
536 233     233   235 my $self = shift;
537 233         498 my $file = $self->_file;
538 233 100       967 $file =~ s/^.*#// || return;
539 20         45 return $file;
540             }
541              
542              
543             sub _file_path_with_macro
544             {
545 23     23   23 my $self = shift;
546 23         41 my $file = $self->_file_path;
547 23         52 my $macro = $self->_macro;
548 23 50       41 my $res = $macro ? "$file#$macro" : $file;
549 23         58 return $res;
550             }
551              
552              
553             # $self->_file_path;
554             # ------------------
555             # computes the file of the absolute path where the template
556             # file should be fetched
557             sub _file_path
558             {
559 238     238   228 my $self = shift;
560 238         365 my $file = $self->_file;
561 238         346 $file =~ s/#.*$//;
562 238         489 my @dirs = $self->base_dir;
563            
564 238         431 foreach my $dir (@dirs)
565             {
566             # my $base_dir = File::Spec->canonpath ($dir);
567             # $base_dir = File::Spec->rel2abs ($base_dir) unless ($base_dir =~ /^\//);
568 242         284 my $base_dir = $dir;
569 242         299 $base_dir =~ s/\/$//;
570 242         1036 my $file_path = File::Spec->canonpath ($base_dir . '/' . $file);
571 242 100 66     8423 return $file_path if (-e $file_path and -r $file_path);
572             }
573            
574 8         752 Carp::confess ("Cannot find $file in @dirs. (typo? permission problem?)");
575             }
576              
577              
578             # $self->_file_data_ref;
579             # ----------------------
580             # slurps the template data into a variable and returns a
581             # reference to that variable
582             sub _file_data_ref
583             {
584 215     215   218 my $self = shift;
585 215         483 my $file_path = $self->_file_path;
586 207         379 $file_path =~ s/#.*$//;
587            
588 207 50       471 if ($] > 5.007)
589             {
590 207   50     730 my $encoding = Encode::resolve_alias ($DECODE_CHARSET) || 'utf8';
591 73 50   73   376 open FP, "<:encoding($encoding)", "$file_path" or die "Cannot read-open $file_path";
  73         94  
  73         420  
  207         10381  
592             }
593             else
594             {
595 0   0     0 open FP, "<$file_path" || die 'Cannot read-open $file_path';
596             }
597            
598 207         72737 my $res = join '', ;
599 207         7495 close FP;
600            
601             # kill template comments
602 207         1333 $res =~ s/\//gsm;
603            
604 207 100 100     1911 my $decode = ($OUTPUT =~ /HTML$/i or $INPUT =~ /HTML$/i) ?
605             new MKDoc::XML::Decode ('numeric', 'xhtml') :
606             new MKDoc::XML::Decode ('numeric');
607            
608 207         2247 $res = $decode->process ($res);
609 207         3789 return \$res;
610             }
611              
612              
613             # $self->_code_disk_cached;
614             # -------------------------
615             # Returns the Perl code data, using the disk cache if possible
616             sub _code_disk_cached
617             {
618 210     210   211 my $self = shift;
619 210 100 33     683 my $code = (defined $DISK_CACHE and $DISK_CACHE) ? Petal::Cache::Disk->get ($self->_file_path_with_macro, $self->language) : undef;
620 210 50       428 unless (defined $code)
621             {
622 210   66     494 my $macro = $self->_macro() || $MT_NAME_CUR;
623            
624 210         209 local ($MT_NAME_CUR);
625 210         215 $MT_NAME_CUR = $macro;
626            
627 210         444 my $data_ref = $self->_canonicalize;
628 198         359 load_code_generator();
629 198         598 $code = $CodeGenerator->process ($data_ref, $self);
630 196 100 33     869 Petal::Cache::Disk->set ($self->_file_path_with_macro, $code, $self->language) if (defined $DISK_CACHE and $DISK_CACHE);
631             }
632            
633 196         333 return $code;
634             }
635              
636              
637             # $self->_code_memory_cached;
638             # ---------------------------
639             # Returns the Perl code data, using the disk cache if possible
640             sub _code_memory_cached
641             {
642 202     202   216 my $self = shift;
643 202 100 33     682 my $code = (defined $MEMORY_CACHE and $MEMORY_CACHE) ? Petal::Cache::Memory->get ($self->_file_path_with_macro, $self->language) : undef;
644 202 50       411 unless (defined $code)
645             {
646 202         416 my $code_perl = $self->_code_disk_cached;
647 195         245 my $VAR1 = undef;
648            
649 195         34837 eval "$code_perl";
650 195 50       517 confess ($@ . "\n" . $self->_code_with_line_numbers) if $@;
651 195         202 $code = $VAR1;
652            
653 195 100 33     733 Petal::Cache::Memory->set ($self->_file_path_with_macro, $code, $self->language) if (defined $MEMORY_CACHE and $MEMORY_CACHE);
654             }
655            
656 195         303 return $code;
657             }
658              
659              
660             # $self->_code_cache;
661             # -------------------
662             # Returns TRUE if this object uses the code cache, FALSE otherwise
663             sub _memory_cache
664             {
665 0     0   0 my $self = shift;
666 0 0       0 return $self->{memory_cache} if (defined $self->{memory_cache});
667 0         0 return $MEMORY_CACHE;
668             }
669              
670              
671             # $self->_canonicalize;
672             # ---------------------
673             # Returns the canonical data which will be sent to the
674             # Petal::CodeGenerator module
675             sub _canonicalize
676             {
677 214     214   250 my $self = shift;
678 214   33     598 my $parser_type = $INPUTS->{$INPUT} || confess "unknown \$Petal::INPUT = $INPUT";
679 214   33     534 my $canonicalizer_type = $OUTPUTS->{$OUTPUT} || confess "unknown \$Petal::OUTPUT = $OUTPUT";
680            
681 214         446 my $data_ref = $self->_file_data_ref;
682 206         901 my $parser = $parser_type->new;
683 206         962 return $canonicalizer_type->process ($parser, $data_ref);
684             }
685              
686              
687             1;
688              
689              
690             =head1 NAME
691              
692             Petal - Perl Template Attribute Language - TAL for Perl!
693              
694              
695             =head1 SYNOPSIS
696              
697             in your Perl code:
698              
699             use Petal;
700             my $template = new Petal ('foo.xhtml');
701             print $template->process (bar => 'BAZ');
702              
703              
704             in foo.xhtml
705              
706            
707             Dummy Content
708            
709              
710              
711             and you get something like:
712              
713            
714             BAZ
715            
716              
717              
718             =head1 SUMMARY
719              
720             Petal is a XML based templating engine that is able to process any
721             kind of XML, XHTML and HTML.
722              
723             Petal borrows a lot of good ideas from the Zope Page Templates TAL
724             specification, it is very well suited for the creation of WYSIWYG XHTML
725             editable templates.
726              
727             The idea is to further enforce the separation of logic from presentation. With
728             Petal, graphic designers can use their favorite WYSIWYG editor to easily edit
729             templates without having to worry about the loops and ifs which happen behind
730             the scene.
731              
732              
733             =head1 NAMESPACE
734              
735             Although this is not mandatory, Petal templates should include use the namespace
736             L. Example:
737              
738            
739             lang="en"
740             xmlns="http://www.w3.org/1999/xhtml"
741             xmlns:tal="http://purl.org/petal/1.0/">
742              
743             Blah blah blah...
744             Content of the file
745             More blah blah...
746            
747              
748             If you do not specify the namespace, Petal will by default try to use the
749             C prefix. However, in all the examples of this POD we'll use the
750             C prefix to avoid too much typing.
751              
752              
753             =head1 KICKSTART
754              
755             Let's say you have the following Perl code:
756              
757             use Petal;
758             local $Petal::OUTPUT = 'XHTML';
759              
760             my $template = new Petal ('foo.xhtml');
761             $template->process ( my_var => some_object() );
762              
763             some_object() is a subroutine that returns some kind of object, may it be a scalar,
764             object, array referebce or hash reference. Let's see what we can do...
765              
766              
767             =head2 Version 1: WYSIWYG friendly prototype.
768              
769             Using TAL you can do:
770              
771             This is the variable 'my_var' :
772             Hola, Mundo!
773              
774             Now you can open your template in any WYSIWYG tool (mozilla composer,
775             frontpage, dreamweaver, adobe golive...) and work with less risk of damaging
776             your petal commands.
777              
778              
779             =head2 Version 2: Object-oriented version
780              
781             Let's now say that C is actually an object with a method hello_world()
782             that returns I. To output the same result, your line, which was:
783              
784             Hola, Mundo!
785              
786             Would need to be... EXACTLY the same. Petal lets you access hashes and objects
787             in an entirely transparent way and tries to automagically do The Right Thing
788             for you.
789              
790             This high level of polymorphism means that in most cases you can maintain your
791             code, swap hashes for objects, and not change a single line of your template
792             code.
793              
794              
795             =head2 Version 3: Personalizable
796              
797             Now let's say that your method hello_world() can take an optional
798             argument so that C<$some_object-Ehello_world ('Jack')> returns I.
799              
800             You would write:
801              
802             Hola, Mundo!
803              
804              
805             Optionally, you can get rid of the quotes by using two dashes, a la GNU
806             command-line option:
807              
808             Hola, Mundo!
809              
810              
811             So you can pass parameters to methods using double dashes or quotes.
812             Now let us say that your C object also has a method current_user()
813             that returns the current user real name. You can do:
814              
815             Hola, Mundo!
816              
817              
818             TRAP:
819              
820             You cannot write nested expressions such as:
821              
822             ${my_var/hello_world ${my_var/current_user}}
823              
824             This will NOT work. At least, not yet.
825              
826              
827             =head2 Version 4: Internationalized
828              
829             Let's say that you have a directory called C with the following
830             files:
831              
832             hello_world/en.xhtml
833             hello_world/fr.xhtml
834             hello_world/es.xhtml
835              
836             You can use Petal as follows in your Perl code:
837              
838             use Petal;
839             local $Petal::OUTPUT = 'XHTML';
840              
841             my $template = new Petal ( file => 'hello_world', lang => 'fr-CA' );
842             print $template->process ( my_var => some_object() );
843              
844             What will happen is that the C<$template> object will look in the
845             C directory and try to find a file named C, then
846             C, then will default to C. It works fine for includes, too!
847              
848             These internationalized templates can have whatever file-extension you like,
849             Petal searches on the first part of the filename. So you can call them
850             C, C, C or use whatever convention suits you.
851              
852             NOTE: There is now support for ZPT-like i18n attributes, which should
853             provide a much nicer framework. See L for details.
854              
855              
856             TIP:
857              
858             If you feel that 'en' should not be the default language, you can specify a
859             different default:
860              
861             my $template = new Petal (
862             file => 'hello_world',
863             language => 'zh',
864             default_language => 'fr' # vive la France!
865             );
866              
867              
868             TRAP:
869              
870             If you do specify the C option, you MUST use a path to a template
871             directory, not a file directory.
872              
873             Conversely, if you do not specify a C option, you MUST use a path to a
874             template file, not a directory.
875              
876              
877             =head1 OPTIONS
878              
879             When you create a Petal template object you can specify various options using
880             name => value pairs as arguments to the constructor. For example:
881              
882             my $template = Petal->new(
883             file => 'gerbils.html',
884             base_dir => '/var/www/petshop',
885             input => 'HTML',
886             output => 'HTML',
887             );
888              
889             The recognized options are:
890              
891              
892             =head2 file => I
893              
894             The template filename. This option is mandatory and has no default.
895              
896             Note: If you also use 'language' this option should point to a directory.
897              
898              
899             =head2 base_dir => I | [ I ] (default: '.')
900              
901             The directories listed in this option will be searched in turn to locate the
902             template file. A single directory can be specified as a scalar. For a
903             directory list use an arrayref.
904              
905              
906             =head2 input => 'HTML' | 'XHTML' | 'XML' (default: 'XML')
907              
908             Defines the format of the template files. Recognised values are:
909              
910             'HTML' - Alias for 'XHTML'
911             'XHTML' - Petal will use Petal::Parser to parse the template
912             'XML' - Petal will use Petal::Parser to parse the template
913              
914              
915             =head2 output => 'HTML' | 'XHTML' | 'XML' (default: 'XML')
916              
917             Defines the format of the data generated as a result of processing the template
918             files. Recognised values are:
919              
920             'HTML' - Petal will output XHTML, self-closing certain tags
921             'XHTML' - Alias for 'HTML'
922             'XML' - Petal will output generic XML
923              
924              
925             =head2 language => I
926              
927             For internationalized applications, you can use the 'file' option to point to a
928             I and select a language-specific template within that directory
929             using the 'language' option. Languages are selected using a two letter code
930             (eg: 'fr') optionally followed by a hyphen and a two letter country code (eg:
931             'fr-CA').
932              
933              
934             =head2 default_language => I (default: 'en')
935              
936             This language code will be used if no template matches the selected
937             language-country or language.
938              
939              
940             =head2 taint => I | I (default: I)
941              
942             If set to C, makes perl taint mode happy.
943              
944              
945             =head2 error_on_undef_var => I | I (default: I)
946              
947             If set to C, Petal will confess() errors when trying to access undefined
948             template variables, otherwise an empty string will be returned.
949              
950              
951             =head2 disk_cache => I | I (default: I)
952              
953             If set to C, Petal will not use the C module.
954              
955              
956             =head2 memory_cache => I | I (default: I)
957              
958             If set to C, Petal will not use the C module.
959              
960              
961             =head2 cache_only => I | I (default: I)
962              
963             If set to C, Petal will return true after having compiled a template into
964             perl code and a subroutine , and optionally using disk_cache or memory_cache if
965             either is set.
966              
967              
968             =head2 max_includes => I (default: 30)
969              
970             The maximum number of recursive includes before Petal stops processing. This
971             is to guard against accidental infinite recursions.
972              
973              
974             =head2 debug_dump => I | I (default: I)
975              
976             If this option is true, when Petal cannot process a template it will
977             output lots of debugging information in a temporary file which you can
978             inspect. The location for this file is wherever File::Spec->tmpdir()
979             specifies as a temp directory (usually /tmp on a unix system).
980              
981              
982             =head2 encode_charset => I (default: undef)
983              
984             This option is _DEPRECATED_ as of Petal 2.01.
985             Petal will now always return results in Perl's internal form.
986              
987             It doesn't guarantee that the result will be in UTF-8 or in your
988             local encoding, but at least the UTF-8 flag should be set properly.
989              
990             If you want to encode the results for a specific charset, you
991             should look at the module L.
992              
993              
994             =head2 decode_charset => I (default: undef)
995              
996             This option will work only if you use Perl 5.8 or greater.
997              
998             If specified, Petal will assume that the template to be processed (and its
999             sub-templates) are in the character set I.
1000              
1001             I can be any character set that can be used with the module L.
1002              
1003              
1004             =head1 TAL SYNTAX
1005              
1006             This functionality is directly and shamelessly stolen from the excellent TAL
1007             specification: L.
1008              
1009              
1010             =head2 define
1011              
1012             Abstract
1013              
1014            
1015              
1016             Evaluates C and assigns the returned value to C.
1017              
1018             Example
1019              
1020            
1021            
1022              
1023             Why?
1024              
1025             This can be useful if you have a C. You can set it
1026             to let's say C and then use C instead of using
1027             C.
1028              
1029              
1030             =head2 condition (ifs)
1031              
1032             Abstract
1033              
1034            
1035             blah blah blah
1036            
1037              
1038             Example
1039              
1040            
1041             Yo, authenticated!
1042            
1043              
1044             Why?
1045              
1046             Conditions can be used to display something if an expression
1047             is true. They can also be used to check that a list exists
1048             before attempting to loop through it.
1049              
1050              
1051             =head2 repeat (loops)
1052              
1053             Abstract
1054              
1055            
1056             blah blah blah
1057            
1058              
1059             Why?
1060              
1061             Repeat statements are used to loop through a list of values,
1062             typically to display the resulting records of a database query.
1063              
1064             Example:
1065              
1066            
  • $user/real_name
  • 1067              
    1068             A select list with one item selected:
    1069              
    1070            
    1071            
    1072             selected="selected"
    1073             tal:attributes="value self/selected_lang/value"
    1074             tal:content="self/selected_lang/label"
    1075             >English
    1076            
    1077             value="i-klingon"
    1078             tal:repeat="lang self/unselected_langs;"
    1079             tal:attributes="value lang/value"
    1080             tal:content="lang/label"
    1081             >Klingon
    1082            
    1083              
    1084             A table with rows of alternating colours set via CSS:
    1085              
    1086            
    1087            
    1088             tal:omit-tag=""
    1089             tal:repeat="audience self/audiences"
    1090             >
    1091            
    1092             class="odd"
    1093             tal:condition="repeat/odd"
    1094             >
    1095            
    1096             This a odd row, it comes before the even row.
    1097            
    1098            
    1099            
    1100             class="even"
    1101             tal:condition="repeat/even"
    1102             >
    1103            
    1104             This a even row.
    1105            
    1106            
    1107            
    1108            
    1109              
    1110             I is a local temporary object that only exists within a
    1111             petal:repeat loop. It has a bunch of methods useful for selecting
    1112             different positions in the loop:
    1113              
    1114             =head3 repeat/index
    1115              
    1116             I returns the numeric position of this item within the loop, starts with
    1117             one not zero.
    1118              
    1119             =head3 repeat/number
    1120              
    1121             I is an alias for I.
    1122              
    1123             =head3 repeat/even
    1124              
    1125             I is true if the position is even (0, 2, 4 ...)
    1126              
    1127             =head3 repeat/odd
    1128              
    1129             I is true is the position is odd (1, 3, 5 ...)
    1130              
    1131             =head3 repeat/start
    1132              
    1133             I is true if this is the first item.
    1134              
    1135             =head3 repeat/end
    1136              
    1137             I is true if this is the last item.
    1138              
    1139             =head3 repeat/inner
    1140              
    1141             I is true if this is not the I or I.
    1142              
    1143             =head2 attributes
    1144              
    1145             Abstract
    1146              
    1147            
    1148             blah blah blah
    1149            
    1150              
    1151             Example
    1152              
    1153            
    1154             lang="en-gb"
    1155             tal:attributes="href document/href_relative; lang document/lang">
    1156              
    1157             Why?
    1158              
    1159             Attributes statements can be used to template a tag's attributes.
    1160              
    1161              
    1162             =head2 content
    1163              
    1164             Abstract
    1165              
    1166             Dummy Data To Replace With EXPRESSION
    1167              
    1168             By default, the characters greater than, lesser than, double quote and
    1169             ampersand are encoded to the entities I<<>, I<>>, I<"> and I<&>
    1170             respectively. If you don't want them to (because the result of your expression
    1171             is already encoded) you have to use the C keyword.
    1172              
    1173             Example
    1174              
    1175             Dummy Title
    1176              
    1177            
    1178             blah blah blah
    1179            
    1180              
    1181             Why?
    1182              
    1183             It lets you replace the contents of a tag with whatever value the evaluation of
    1184             EXPRESSION returned. This is handy because you can fill your templates with
    1185             dummy content which will make them usable in a WYSIWYG tool.
    1186              
    1187              
    1188             =head2 replace
    1189              
    1190             Abstract
    1191              
    1192            
    1193             This time the entire tag is replaced
    1194             rather than just the content!
    1195            
    1196              
    1197             Example
    1198              
    1199             Dummy Title
    1200              
    1201             Why?
    1202              
    1203             Similar reasons to C. Note however that C and
    1204             C are *NOT* aliases. The former will replace the contents of the
    1205             tag, while the latter will replace the whole tag.
    1206              
    1207             Indeed you cannot use C and C in the same tag.
    1208              
    1209              
    1210             =head2 omit-tag
    1211              
    1212             Abstract
    1213              
    1214             Some contents
    1215              
    1216             Example
    1217              
    1218             I may not be bold.
    1219              
    1220             If C is evaluated as I, then the tag will be omited.
    1221             If C is evaluated as I, then the tag will stay in place.
    1222              
    1223             Why?
    1224              
    1225             omit-tag statements can be used to leave the contents of a tag in place while
    1226             omitting the surrounding start and end tags if the expression which is
    1227             evaluated is TRUE.
    1228              
    1229             TIP:
    1230              
    1231             If you want to ALWAYS remove a tag, you can use C
    1232              
    1233              
    1234             =head2 on-error
    1235              
    1236             Warning: this is currently only partially implemented. C may be used
    1237             in Petal templates, but the expression isn't evaluated - Petal simply prints
    1238             the expression as a string.
    1239              
    1240             Abstract
    1241              
    1242             ...
    1243              
    1244             Example
    1245              
    1246            

    1247             $object/method
    1248            

    1249              
    1250             Why?
    1251              
    1252             When Petal encounters an error, it usually dies with some obscure error
    1253             message. The C statement lets you trap the error and replace it
    1254             with a proper error message.
    1255              
    1256              
    1257             =head2 using multiple statements
    1258              
    1259             You can do things like:
    1260              
    1261            

    1262             tal:condition="children"
    1263             tal:repeat="child children"
    1264             tal:attributes="lang child/lang; xml:lang child/lang"
    1265             tal:content="child/data"
    1266             tal:on-error="string:Ouch!">Some Dummy Content

    1267              
    1268             Given the fact that XML attributes are not ordered, withing the same tag
    1269             statements will be executed in the following order:
    1270              
    1271             define
    1272             condition
    1273             repeat
    1274             attributes
    1275             content
    1276             OR
    1277             replace
    1278             OR
    1279             omit-tag
    1280             content
    1281              
    1282              
    1283             TRAP:
    1284              
    1285             Don't forget that the default prefix is C NOT C, until
    1286             you set the petal namespace in your HTML or XML document as follows:
    1287              
    1288            
    1289              
    1290              
    1291             =head1 METAL MACROS
    1292              
    1293             Petal supports an implementation of the METAL specification, which is a very
    1294             WYSIWYG compatible way of doing template includes.
    1295              
    1296              
    1297             =head2 define-macro
    1298              
    1299             In order to define a macro inside a file (i.e. a fragment to be included), you
    1300             use the metal:define-macro directive. For example:
    1301              
    1302             File foo.xml
    1303             ============
    1304              
    1305            
    1306            
    1307            

    1308             (c) Me (r)(tm) (pouet pouet)
    1309            

    1310            
    1311            
    1312              
    1313              
    1314             =head2 use-macro
    1315              
    1316             In order to use a previously defined macro, you use the metal:use-macro directive.
    1317             For example:
    1318              
    1319             File bar.xml
    1320             ============
    1321              
    1322            
    1323            
    1324             ... plenty of content ...
    1325              
    1326            

    1327             Page Footer.
    1328            

    1329            
    1330            
    1331              
    1332              
    1333             =head2 define-slot
    1334              
    1335             In any given macro you can define slots, which are bits of macros that can be
    1336             overridden by something else using the fill-macro directive. To re-use the
    1337             example above, imagine that we want to be able to optionally override the
    1338             (pouet pouet) bit with something else:
    1339              
    1340              
    1341             File foo.xml
    1342             ============
    1343              
    1344            
    1345            
    1346            

    1347             (c) Me (r)(tm) (pouet pouet)
    1348            

    1349            
    1350            
    1351              
    1352              
    1353             =head2 fill-slot
    1354              
    1355             Your including file can override any slot using the fill-slot instruction, i.e.
    1356              
    1357             File bar.xml
    1358             ============
    1359              
    1360            
    1361            
    1362             ... plenty of content ...
    1363              
    1364            

    1365             Page Footer. (bar baz)
    1366            

    1367            
    1368            
    1369              
    1370             This would result in the macro 'foo.xml#footer' to produce:
    1371              
    1372            
    1373            
    1374            

    1375             (c) Me (r)(tm) (bar baz)
    1376            

    1377            
    1378            
    1379              
    1380              
    1381             =head2 self includes
    1382              
    1383             In Zope, METAL macros are expanded first, and then the TAL instructions are processed.
    1384             However with Petal, METAL macros are expanded at run-time just like regular includes,
    1385             which allows for recursive macros.
    1386              
    1387             This example templates a sitemap, which on a hierarchically organized site would
    1388             be recursive by nature:
    1389              
    1390            
    1391             xmlns:petal="http://purl.org/petal/1.0/">
    1392            
    1393            

    Sitemap:

    1394              
    1395            
  • 1396            
    1397             petal:attributes="href child/Full_Path"
    1398             petal:content="child/Title"
    1399             >Child Document Title
    1400            
    1401             petal:define="children child/Children"
    1402             petal:condition="children"
    1403             petal:repeat="child children"
    1404             >
    1405            
  • Dummy Child 1
  • 1406            
  • Dummy Child 2
  • 1407            
  • Dummy Child 3
  • 1408            
    1409            
    1410            
    1411            
    1412              
    1413              
    1414             =head1 EXPRESSIONS AND MODIFIERS
    1415              
    1416             Petal has the ability to bind template variables to the following Perl
    1417             datatypes: scalars, lists, hash, arrays and objects. The article describes
    1418             the syntax which is used to access these from Petal templates.
    1419              
    1420             In the following examples, we'll assume that the template is used as follows:
    1421              
    1422             my $hashref = some_complex_data_structure();
    1423             my $template = new Petal ('foo.xml');
    1424             print $template->process ( $hashref );
    1425              
    1426             Then we will show how the Petal Expression Syntax maps to the Perl way of
    1427             accessing these values.
    1428              
    1429              
    1430             =head2 accessing scalar values
    1431              
    1432             Perl expression
    1433              
    1434             $hashref->{'some_value'};
    1435              
    1436             Petal expression
    1437              
    1438             some_value
    1439              
    1440             Example
    1441              
    1442            
    1445             Hello, World
    1446              
    1447              
    1448             =head2 accessing hashes & arrays
    1449              
    1450             Perl expression
    1451              
    1452             $hashref->{'some_hash'}->{'a_key'};
    1453              
    1454             Petal expression
    1455              
    1456             some_hash/a_key
    1457              
    1458             Example
    1459              
    1460            
    1463             Hello, World
    1464              
    1465              
    1466             Perl expression
    1467              
    1468             $hashref->{'some_array'}->[12]
    1469              
    1470             Petal expression
    1471              
    1472             some_array/12
    1473              
    1474             Example
    1475              
    1476            
    1479             Hello, World
    1480              
    1481             Note: You're more likely to want to loop through arrays:
    1482              
    1483            
    1484            
    1485            
  • 1486             tal:content="value">Hello, World
    1487            
    1488              
    1489              
    1490             =head2 accessing object methods
    1491              
    1492             Perl expressions
    1493              
    1494             1. $hashref->{'some_object'}->some_method();
    1495             2. $hashref->{'some_object'}->some_method ('foo', 'bar');
    1496             3. $hashref->{'some_object'}->some_method ($hashref->{'some_variable'})
    1497              
    1498             Petal expressions
    1499              
    1500             1. some_object/some_method
    1501             2a. some_object/some_method 'foo' 'bar'
    1502             2b. some_object/some_method "foo" "bar"
    1503             2c. some_object/some_method --foo --bar
    1504             3. some_object/some_method some_variable
    1505              
    1506             Note that the syntax as described in 2c works only if you use strings
    1507             which do not contain spaces.
    1508              
    1509             Example
    1510              
    1511            

    1512             2 times
    1513             2 equals
    1514             4
    1515            

    1516            
    1517              
    1518             =head2 composing
    1519              
    1520             Petal lets you traverse any data structure, i.e.
    1521              
    1522             Perl expression
    1523              
    1524             $hashref->{'some_object'}
    1525             ->some_method()
    1526             ->{'key2'}
    1527             ->some_other_method ( 'foo', $hash->{bar} );
    1528              
    1529             Petal expression
    1530              
    1531             some_object/some_method/key2/some_other_method --foo bar
    1532              
    1533              
    1534             =head2 true:EXPRESSION
    1535              
    1536             If EXPRESSION returns an array reference
    1537             If this array reference has at least one element
    1538             Returns TRUE
    1539             Else
    1540             Returns FALSE
    1541              
    1542             Else
    1543             If EXPRESSION returns a TRUE value (according to Perl 'trueness')
    1544             Returns TRUE
    1545             Else
    1546             Returns FALSE
    1547              
    1548             the C modifiers should always be used when doing Petal conditions.
    1549              
    1550              
    1551             =head2 false:EXPRESSION
    1552              
    1553             I'm pretty sure you can work this one out by yourself :-)
    1554              
    1555              
    1556             =head2 set:variable_name EXPRESSION
    1557              
    1558             Sets the value returned by the evaluation of EXPRESSION in
    1559             C<$hash-E{variable_name}>. For instance:
    1560              
    1561             Perl expression:
    1562              
    1563             $hash->{variable_name} = $hash->{object}->method();
    1564              
    1565             Petal expression:
    1566              
    1567             set:variable_name object/method
    1568              
    1569              
    1570             =head2 string:STRING_EXPRESSION
    1571              
    1572             The C modifier lets you interpolate petal expressions within a string
    1573             and returns the value.
    1574              
    1575             string:Welcome $user/real_name, it is $date!
    1576              
    1577             Alternatively, you could write:
    1578              
    1579             string:Welcome ${user/real_name}, it is ${date}!
    1580            
    1581             The advantage of using curly brackets is that it lets you interpolate
    1582             expressions which invoke methods with parameters, i.e.
    1583              
    1584             string:The current CGI 'action' param is: ${cgi/param --action}
    1585              
    1586              
    1587             =head1 ADVANCED PETAL
    1588              
    1589              
    1590             =head2 writing your own modifiers
    1591              
    1592             Petal lets you write your own modifiers, either using coderefs
    1593             or modules.
    1594              
    1595              
    1596             =head3 Coderefs
    1597              
    1598             Let's say that you want to write an uppercase: modifier, which
    1599             would uppercase the result of an expression evaluation, as in:
    1600              
    1601             uppercase:string:Hello, World
    1602              
    1603             Would return
    1604              
    1605             HELLO, WORLD
    1606              
    1607             Here is what you can do:
    1608              
    1609             # don't forget the trailing colon in C !!
    1610             $Petal::Hash::MODIFIERS->{'uppercase:'} = sub {
    1611             my $hash = shift;
    1612             my $args = shift;
    1613              
    1614             my $result = $hash->fetch ($args);
    1615             return uc ($result);
    1616             };
    1617              
    1618              
    1619             =head3 Modules.
    1620              
    1621             You might want to use a module rather than a coderef. Here is the example above
    1622             reimplemented as a module:
    1623              
    1624             package Petal::Hash::UpperCase;
    1625             use strict;
    1626             use warnings;
    1627            
    1628             sub process {
    1629             my $class = shift;
    1630             my $hash = shift;
    1631             my $args = shift;
    1632              
    1633             my $result = $hash->fetch ($args);
    1634             return uc ($result);
    1635             }
    1636              
    1637             1;
    1638              
    1639             As long as your module is in the namespace Petal::Hash::,
    1640             Petal will automatically pick it up and assign it to its lowercased
    1641             name, i.e. in our example C.
    1642              
    1643             If your modifier is OUTSIDE Petal::Hash::, you need to
    1644             make Petal aware of its existence as follows:
    1645              
    1646             use MyPetalModifier::UpperCase;
    1647             $Petal::Hash::MODIFIERS->{'uppercase:'} = 'MyPetalModifier::UpperCase';
    1648              
    1649              
    1650             =head1 Expression keywords
    1651              
    1652              
    1653             =head3 XML encoding / structure keyword
    1654              
    1655             By default Petal will encode C<&>, C<<>, C<>> and C<"> to C<&>, C<<>,
    1656             C<>> and C<"> respectively. However sometimes you might want to display
    1657             an expression which is already encoded, in which case you can use the
    1658             C keyword.
    1659              
    1660             structure my/encoded/variable
    1661              
    1662             Note that this is a language I, not a modifier. It does not use a
    1663             trailing colon.
    1664              
    1665              
    1666             =head3 Petal::Hash caching and fresh keyword
    1667              
    1668             Petal caches the expressions which it resolves, i.e. if you write the
    1669             expression:
    1670              
    1671             string:$foo/bar, ${baz/buz/blah}
    1672              
    1673             Petal::Hash will compute it once, and then for subsequent accesses to that
    1674             expression always return the same value. This is almost never a problem, even
    1675             for loops because a new Petal::Hash object is used for each iteration in order
    1676             to support proper scoping.
    1677              
    1678             However, in some rare cases you might not want to have that behavior, in which
    1679             case you need to prefix your expression with the C keyword, i.e.
    1680              
    1681             fresh string:$foo/bar, ${baz/buz/blah}
    1682              
    1683             You can use C with C if you need to:
    1684              
    1685             fresh structure string:$foo/bar, ${baz/buz/blah}
    1686              
    1687             However the reverse does not work:
    1688              
    1689            
    1690             structure fresh string:$foo/bar, ${baz/buz/blah}
    1691              
    1692              
    1693             =head2 TOY FUNCTIONS (For debugging or if you're curious)
    1694              
    1695              
    1696             =head3 perl -MPetal -e canonical template.xml
    1697              
    1698             Displays the canonical template for template.xml.
    1699             You can set C<$Petal::INPUT> using by setting the PETAL_INPUT environment variable.
    1700             You can set C<$Petal::OUTPUT> using by setting the PETAL_OUTPUT environment variable.
    1701              
    1702              
    1703             =head3 perl -MPetal -e code template.xml
    1704              
    1705             Displays the perl code for template.xml.
    1706             You can set C<$Petal::INPUT> using by setting the PETAL_INPUT environment variable.
    1707             You can set C<$Petal::OUTPUT> using by setting the PETAL_OUTPUT environment variable.
    1708              
    1709              
    1710             =head3 perl -MPetal -e lcode template.xml
    1711              
    1712             Displays the perl code for template.xml, with line numbers.
    1713             You can set C<$Petal::INPUT> using by setting the PETAL_INPUT environment variable.
    1714             You can set C<$Petal::OUTPUT> using by setting the PETAL_OUTPUT environment variable.
    1715              
    1716              
    1717             =head2 What does Petal do internally?
    1718              
    1719             The cycle of a Petal template is the following:
    1720              
    1721             1. Read the source XML template
    1722             2. $INPUT (XML or HTML) throws XML events from the source file
    1723             3. $OUTPUT (XML or HTML) uses these XML events to canonicalize the template
    1724             4. Petal::CodeGenerator turns the canonical template into Perl code
    1725             5. Petal::Cache::Disk caches the Perl code on disk
    1726             6. Petal turns the perl code into a subroutine
    1727             7. Petal::Cache::Memory caches the subroutine in memory
    1728             8. Petal executes the subroutine
    1729             9. (optional) Petal internationalizes the resulting output.
    1730              
    1731             If you are under a persistent environment a la mod_perl, subsequent calls to
    1732             the same template will be reduced to step 8 until the source template changes.
    1733              
    1734             Otherwise, subsequent calls will resume at step 6, until the source template
    1735             changes.
    1736              
    1737             If you are using the mod_perl prefork MPM, you can precompile Petal templates
    1738             into Apache's shared memory at startup by using the cache_only option. This
    1739             will allow you to run through steps 1-7 without passing any data to Petal.
    1740              
    1741              
    1742             =head1 DECRYPTING WARNINGS AND ERRORS
    1743              
    1744              
    1745             =head2 "Cannot import module $module. Reason: $@" (nonfatal)
    1746              
    1747             Petal was not able to import one of the modules. This error warning will be
    1748             issued when Petal is unable to load a plugin because it has been badly install
    1749             or is just broken.
    1750              
    1751              
    1752             =head2 "Petal modifier encode: is deprecated" (nonfatal)
    1753              
    1754             You don't need to use encode:EXPRESSION to XML-encode expression anymore,
    1755             Petal does it for you. encode: has been turned into a no-op.
    1756              
    1757              
    1758             =head2 Cannot find value for ... (FATAL)
    1759              
    1760             You tried to invoke an/expression/like/this/one but Petal could not resolve
    1761             it. This could be because an/expression/like evaluated to undef and hence the
    1762             remaining this/one could not be resolved.
    1763              
    1764             Usually Petal gives you a line number and a dump of your template as Perl
    1765             code. You can look at the perl code to try to determine the faulty bit in
    1766             your template.
    1767              
    1768              
    1769             =head2 not well-formed (invalid token) at ... (FATAL)
    1770              
    1771             Petal was trying to parse a file that is not well-formed XML or that has strange
    1772             entities in it. Try to run xmllint on your file to see if it's well formed or
    1773             try to use the $Petal::INPUT = 'XHTML' option.
    1774              
    1775              
    1776             =head2 other errors
    1777              
    1778             Either I've forgot to document it, or it's a bug. Send an email to the Petal
    1779             mailing list.
    1780              
    1781              
    1782             =head1 EXPORTS
    1783              
    1784             None.
    1785              
    1786              
    1787             =head1 AUTHOR
    1788              
    1789             Copyright 2003 - MKDoc Ltd.
    1790              
    1791             Authors: Jean-Michel Hiver,
    1792             Fergal Daly ,
    1793             and others.
    1794              
    1795             This module free software and is distributed under the same license as Perl
    1796             itself. Use it at your own risk.
    1797              
    1798             Thanks to everybody on the list who contributed to Petal in the form of
    1799             patches, bug reports and suggestions. See README for a list of contributors.
    1800              
    1801              
    1802             =head1 SEE ALSO
    1803              
    1804             Join the Petal mailing list:
    1805              
    1806             http://lists.webarch.co.uk/mailman/listinfo/petal
    1807              
    1808             Mailing list archives:
    1809              
    1810             http://lists.webarch.co.uk/pipermail/petal
    1811              
    1812              
    1813             Have a peek at the TAL / TALES / METAL specs:
    1814              
    1815             http://wiki.zope.org/ZPT/TAL
    1816             http://wiki.zope.org/ZPT/TALES
    1817             http://wiki.zope.org/ZPT/METAL
    1818