File Coverage

lib/Petal.pm
Criterion Covered Total %
statement 299 325 92.0
branch 127 164 77.4
condition 30 53 56.6
subroutine 45 52 86.5
pod 11 14 78.5
total 512 608 84.2


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

    1254             $object/method
    1255            

    1256              
    1257             Why?
    1258              
    1259             When Petal encounters an error, it usually dies with some obscure error
    1260             message. The C statement lets you trap the error and replace it
    1261             with a proper error message.
    1262              
    1263              
    1264             =head2 using multiple statements
    1265              
    1266             You can do things like:
    1267              
    1268            

    1269             tal:condition="children"
    1270             tal:repeat="child children"
    1271             tal:attributes="lang child/lang; xml:lang child/lang"
    1272             tal:content="child/data"
    1273             tal:on-error="string:Ouch!">Some Dummy Content

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

    1315             (c) Me (r)(tm) (pouet pouet)
    1316            

    1317            
    1318            
    1319              
    1320              
    1321             =head2 use-macro
    1322              
    1323             In order to use a previously defined macro, you use the metal:use-macro directive.
    1324             For example:
    1325              
    1326             File bar.xml
    1327             ============
    1328              
    1329            
    1330            
    1331             ... plenty of content ...
    1332              
    1333            

    1334             Page Footer.
    1335            

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

    1354             (c) Me (r)(tm) (pouet pouet)
    1355            

    1356            
    1357            
    1358              
    1359              
    1360             =head2 fill-slot
    1361              
    1362             Your including file can override any slot using the fill-slot instruction, i.e.
    1363              
    1364             File bar.xml
    1365             ============
    1366              
    1367            
    1368            
    1369             ... plenty of content ...
    1370              
    1371            

    1372             Page Footer. (bar baz)
    1373            

    1374            
    1375            
    1376              
    1377             This would result in the macro 'foo.xml#footer' to produce:
    1378              
    1379            
    1380            
    1381            

    1382             (c) Me (r)(tm) (bar baz)
    1383            

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

    Sitemap:

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

    1519             2 times
    1520             2 equals
    1521             4
    1522            

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