blib/lib/Text/TagTemplate.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 245 | 280 | 87.5 |
branch | 98 | 140 | 70.0 |
condition | 5 | 15 | 33.3 |
subroutine | 38 | 41 | 92.6 |
pod | 24 | 27 | 88.8 |
total | 410 | 503 | 81.5 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | #=============================================================================== | ||||||
2 | # | ||||||
3 | # Text::TagTemplate | ||||||
4 | # | ||||||
5 | # A Perl module for working with simple templates, mainly for CGI, mod_perl, | ||||||
6 | # and HTML use. | ||||||
7 | # | ||||||
8 | # Copyright (C) 2000 SF Interactive, Inc. All rights reserved. | ||||||
9 | # | ||||||
10 | # Maintainer: Matisse Enzer |
||||||
11 | # Author: Jacob Davies |
||||||
12 | # | ||||||
13 | # This library is free software; you can redistribute it and/or | ||||||
14 | # modify it under the terms of the GNU Lesser General Public | ||||||
15 | # License as published by the Free Software Foundation; either | ||||||
16 | # version 2.1 of the License, or (at your option) any later version. | ||||||
17 | # | ||||||
18 | # This library is distributed in the hope that it will be useful, | ||||||
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||||
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||||
21 | # Lesser General Public License for more details. | ||||||
22 | # | ||||||
23 | # You should have received a copy of the GNU Lesser General Public | ||||||
24 | # License along with this library; if not, write to the Free Software | ||||||
25 | # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||||
26 | # | ||||||
27 | #=============================================================================== | ||||||
28 | |||||||
29 | package Text::TagTemplate; | ||||||
30 | 1 | 1 | 844 | use strict; | |||
1 | 2 | ||||||
1 | 32 | ||||||
31 | 1 | 1 | 22 | use 5.004; | |||
1 | 3 | ||||||
1 | 29 | ||||||
32 | 1 | 1 | 17 | use Carp qw(cluck confess); | |||
1 | 1 | ||||||
1 | 49 | ||||||
33 | 1 | 1 | 714 | use English qw(-no_match_vars); | |||
1 | 2010 | ||||||
1 | 7 | ||||||
34 | 1 | 1 | 472 | use vars qw( $VERSION ); | |||
1 | 2 | ||||||
1 | 54 | ||||||
35 | # '$Revision: 1.1 $' =~ /([\d.]+)/; | ||||||
36 | $VERSION = '1.83'; | ||||||
37 | 1 | 1 | 1012 | use IO::File; | |||
1 | 17288 | ||||||
1 | 151 | ||||||
38 | require Exporter; | ||||||
39 | 1 | 1 | 9 | use vars qw ( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS ); | |||
1 | 1 | ||||||
1 | 3326 | ||||||
40 | @ISA = qw( Exporter ); | ||||||
41 | @EXPORT = qw( ); | ||||||
42 | @EXPORT_OK = qw( | ||||||
43 | auto_cap | ||||||
44 | unknown_action | ||||||
45 | tags | ||||||
46 | add_tag | ||||||
47 | list_tag | ||||||
48 | add_list_tag | ||||||
49 | add_tags | ||||||
50 | delete_tag | ||||||
51 | clear_tags | ||||||
52 | template_string template_file | ||||||
53 | list | ||||||
54 | entry_string | ||||||
55 | entry_file | ||||||
56 | entry_callback | ||||||
57 | join_string | ||||||
58 | join_file | ||||||
59 | join_tags | ||||||
60 | parse | ||||||
61 | parse_file | ||||||
62 | parse_list | ||||||
63 | parse_list_files | ||||||
64 | tag_start | ||||||
65 | tag_contents | ||||||
66 | tag_end | ||||||
67 | tag_pattern | ||||||
68 | ); | ||||||
69 | %EXPORT_TAGS = ( standard => [ qw( tags add_tag add_tags list_tag add_list_tag | ||||||
70 | delete_tag clear_tags | ||||||
71 | template_string template_file | ||||||
72 | list | ||||||
73 | entry_string entry_file entry_callback | ||||||
74 | join_string join_file join_tags | ||||||
75 | parse parse_file parse_list | ||||||
76 | parse_list_files ) ], | ||||||
77 | config => [ qw( auto_cap unknown_action ) ] ); | ||||||
78 | |||||||
79 | #=============================================================================== | ||||||
80 | # F U N C T I O N D E C L A R A T I O N S | ||||||
81 | #=============================================================================== | ||||||
82 | |||||||
83 | sub new; | ||||||
84 | sub auto_cap; | ||||||
85 | sub unknown_action; | ||||||
86 | sub tags; | ||||||
87 | sub add_tag; | ||||||
88 | sub list_tag; | ||||||
89 | sub add_list_tag; | ||||||
90 | sub add_tags; | ||||||
91 | sub delete_tag; | ||||||
92 | sub clear_tags; | ||||||
93 | sub template_string; | ||||||
94 | sub template_file; | ||||||
95 | sub list; | ||||||
96 | sub entry_string; | ||||||
97 | sub entry_file; | ||||||
98 | sub entry_callback; | ||||||
99 | sub join_string; | ||||||
100 | sub join_file; | ||||||
101 | sub join_tags; | ||||||
102 | |||||||
103 | sub parse; | ||||||
104 | sub parse_file; | ||||||
105 | sub parse_list; | ||||||
106 | sub parse_list_files; | ||||||
107 | |||||||
108 | sub tag_start; | ||||||
109 | sub tag_contents; | ||||||
110 | sub tag_end; | ||||||
111 | sub tag_pattern; | ||||||
112 | |||||||
113 | sub _self_or_default; | ||||||
114 | sub _get_file; | ||||||
115 | sub _htmlesc($); | ||||||
116 | sub _urlesc($); | ||||||
117 | |||||||
118 | #=============================================================================== | ||||||
119 | # P A C K A G E G L O B A L S | ||||||
120 | #=============================================================================== | ||||||
121 | |||||||
122 | # Filehandles: | ||||||
123 | # GET_FILE | ||||||
124 | |||||||
125 | #=============================================================================== | ||||||
126 | # F I L E V A R I A B L E S | ||||||
127 | #=============================================================================== | ||||||
128 | |||||||
129 | my $default_object; # Used if we're skipping making template objects and just | ||||||
130 | # using the default object. | ||||||
131 | |||||||
132 | #=============================================================================== | ||||||
133 | # P R I V A T E F U N C T I O N S | ||||||
134 | #=============================================================================== | ||||||
135 | |||||||
136 | #------------------------------------------------------------------------------- | ||||||
137 | # _self_or_default( @_ ) | ||||||
138 | # | ||||||
139 | # Takes an @_ argument list, and if it doesn't include a Text::TagTemplate | ||||||
140 | # object at the beginning, it unshifts the default object. | ||||||
141 | # *** DEBUG *** | ||||||
142 | # This breaks inheritance, although it can be made inheritance-safe. | ||||||
143 | |||||||
144 | sub _self_or_default { | ||||||
145 | 300 | 300 | 340 | my( $class ) = @_; | |||
146 | 300 | 50 | 33 | 1307 | return @_ if defined $class and !ref $class | ||
33 | |||||||
147 | and $class eq 'Text::TagTemplate'; | ||||||
148 | 300 | 50 | 33 | 2059 | return @_ if defined $class | ||
33 | |||||||
149 | and ( ref $class eq 'Text::Template' | ||||||
150 | or UNIVERSAL::isa $class, 'Text::TagTemplate' ); | ||||||
151 | 0 | 0 | 0 | $default_object = Text::TagTemplate->new | |||
152 | unless defined $default_object; | ||||||
153 | 0 | 0 | unshift @_, $default_object; | ||||
154 | 0 | 0 | return @_; | ||||
155 | } | ||||||
156 | |||||||
157 | #------------------------------------------------------------------------------- | ||||||
158 | # _get_file( $file ) | ||||||
159 | # | ||||||
160 | # Slurps the supplied file; confesses if it can't find it. | ||||||
161 | |||||||
162 | sub _get_file | ||||||
163 | { | ||||||
164 | 19 | 19 | 26 | my( $file ) = @_; | |||
165 | 19 | 54 | local $INPUT_RECORD_SEPARATOR = undef; | ||||
166 | 19 | 50 | 607 | open( GET_FILE, "<$file" ) or confess( "couldn't open $file: $ERRNO" ); | |||
167 | 19 | 362 | my $string = |
||||
168 | 19 | 50 | 191 | close( GET_FILE ) or confess( "couldn't close $file: $ERRNO" ); | |||
169 | 19 | 69 | return $string; | ||||
170 | } | ||||||
171 | |||||||
172 | #------------------------------------------------------------------------------- | ||||||
173 | # _htmlesc( $str ) | ||||||
174 | # | ||||||
175 | # HTML-escapes a string. | ||||||
176 | |||||||
177 | sub _htmlesc($) | ||||||
178 | { | ||||||
179 | 0 | 0 | 0 | my( $str ) = @_; | |||
180 | 0 | 0 | 0 | return undef unless defined $str; | |||
181 | 0 | 0 | $str =~ s/&/&/g; | ||||
182 | 0 | 0 | $str =~ s/"/"/g; | ||||
183 | 0 | 0 | $str =~ s/</g; | ||||
184 | 0 | 0 | $str =~ s/>/>/g; | ||||
185 | 0 | 0 | return $str; | ||||
186 | } | ||||||
187 | |||||||
188 | #------------------------------------------------------------------------------- | ||||||
189 | # _urlesc( $str ) | ||||||
190 | # | ||||||
191 | # URL-escapes a string. | ||||||
192 | |||||||
193 | sub _urlesc($) | ||||||
194 | { | ||||||
195 | 0 | 0 | 0 | my( $str ) = @_; | |||
196 | 0 | 0 | 0 | return undef unless defined $str; | |||
197 | 0 | 0 | $str =~ s/([^a-zA-Z0-9_\-.])/ uc sprintf '%%%02x', ord $1 /eg; | ||||
0 | 0 | ||||||
198 | 0 | 0 | return $str; | ||||
199 | } | ||||||
200 | |||||||
201 | #=============================================================================== | ||||||
202 | # P E R L D O C | ||||||
203 | #=============================================================================== | ||||||
204 | |||||||
205 | =head1 NAME | ||||||
206 | |||||||
207 | Text::TagTemplate | ||||||
208 | |||||||
209 | =head1 VERSION | ||||||
210 | |||||||
211 | 1.82 | ||||||
212 | |||||||
213 | =head1 SYNOPSIS | ||||||
214 | |||||||
215 | use Text::TagTemplate qw( :standard ); | ||||||
216 | |||||||
217 | # Define a single tag to substitute in a template. | ||||||
218 | add_tag( MYTAG => 'Hello world.' ); | ||||||
219 | |||||||
220 | # Define several tags all at once. The tags() method wipes out | ||||||
221 | # all current tags. | ||||||
222 | tags( +{ FOO => 'The string foo.', # Single-quoted string | ||||||
223 | BAR => "$ENV{ USER }", # Double-quoted string | ||||||
224 | LIST => join( ' |
||||||
225 | |||||||
226 | # Functions or subroutines that get called each time | ||||||
227 | # the tag is replaced, possibly producing different | ||||||
228 | # results for the same tag if it appears twice or more. | ||||||
229 | TIME => \&time(), # Reference to a function | ||||||
230 | SUB => sub { # Anonymous subroutine | ||||||
231 | my( $params ) = @_; | ||||||
232 | return $params->{ NAME }; | ||||||
233 | } | ||||||
234 | } ); | ||||||
235 | |||||||
236 | # Add a couple of tags to the existing set. Takes a hash-ref. | ||||||
237 | add_tags( +{ TAG1 => "Hello $ENV{ USER }", | ||||||
238 | TAG2 => rand( 10 ), # random number between 0 and 10 | ||||||
239 | } ); | ||||||
240 | |||||||
241 | # Set the template file to use. | ||||||
242 | template_file( 'template.htmlt' ); | ||||||
243 | |||||||
244 | # This is list of items to construct a list from. | ||||||
245 | list( 'One', 'Two', 'Three' ); | ||||||
246 | |||||||
247 | # These are template-fragment files to use for making the list. | ||||||
248 | entry_file( 'entry.htmlf' ); | ||||||
249 | join_file( 'join.htmlf' ); | ||||||
250 | |||||||
251 | # This is a callback sub used to make the tags for each entry in a | ||||||
252 | # parsed list. | ||||||
253 | entry_callback( sub { | ||||||
254 | my( $item ) = @_; | ||||||
255 | return +{ ITEM => $item }; | ||||||
256 | } ); | ||||||
257 | |||||||
258 | # Add a new tag that contains the whole parsed list. | ||||||
259 | add_tag( LIST => parse_list_files ); | ||||||
260 | |||||||
261 | # Print the template file with substitutions. | ||||||
262 | print parse_file; | ||||||
263 | |||||||
264 | =head1 DESCRIPTION | ||||||
265 | |||||||
266 | This module is designed to make the process of constructing web-based | ||||||
267 | applications (such as CGI programs and Apache::Registry scripts) much easier, | ||||||
268 | by separating the logic and application development from the HTML coding, and | ||||||
269 | allowing ongoing changes to the HTML without requiring non-programmers to | ||||||
270 | modify HTML embedded deep inside Perl code. | ||||||
271 | |||||||
272 | This module provides a mechanism for including special HTML-like tags | ||||||
273 | in a file (or scalar) and replacing those tags at run-time with | ||||||
274 | dynamically generated content. For example the special tag | ||||||
275 | <#USERINFO FIELD="favorite_color"> | ||||||
276 | |||||||
277 | might be replaced by "green" after doing a database lookup. Usually | ||||||
278 | each special tag will have its own subroutine which is executed every time | ||||||
279 | the tag is seen. | ||||||
280 | |||||||
281 | Each subroutine can be basically anything you might want | ||||||
282 | to do in Perl including database lookups or whatever. You simply create | ||||||
283 | subroutines to return whatever is appropriate for replacing each special | ||||||
284 | tag you create. | ||||||
285 | |||||||
286 | Attributes in the special tags (such as the FIELD="favorite_color" | ||||||
287 | in the example above) are passed to the matching subroutine. | ||||||
288 | |||||||
289 | It is not web-specific, though, despite the definite bias that way, and the | ||||||
290 | template-parsing can just as easily be used on any other text documents. | ||||||
291 | The examples here will assume that you are using it for convential CGI | ||||||
292 | applications. | ||||||
293 | |||||||
294 | It provides functions for parsing strings, and constructing lists of repeated | ||||||
295 | elements (as in the output of a search engine). | ||||||
296 | |||||||
297 | It is object-oriented, but -- like the CGI module -- it does not require the | ||||||
298 | programmer to use an OO interface. You can just import the ``:standard'' set | ||||||
299 | of methods and use them with no object reference, and it will create and use an | ||||||
300 | internal object automatically. This is the recommended method of using it | ||||||
301 | unless you either need multiple template objects, or you are concerned about | ||||||
302 | namespace pollution. | ||||||
303 | |||||||
304 | =head1 TEMPLATES | ||||||
305 | |||||||
306 | The structure of templates is as any other text file, but with extra elements | ||||||
307 | added that are processed by the CGI as it prints the file to the browser. These | ||||||
308 | extra elements are referred to in this manual as ``tags'', which should not be | ||||||
309 | confused with plain HTML tags -- these tags are replaced before the browser | ||||||
310 | even begins to process the HTML tags. The syntax for tags intentionally | ||||||
311 | mimics HTML tags, though, to simplify matters for HTML-coders. | ||||||
312 | |||||||
313 | A tag looks like this: | ||||||
314 | |||||||
315 | <#TAG> | ||||||
316 | |||||||
317 | or optionally with parameters like: | ||||||
318 | |||||||
319 | <#TAG NAME=VALUE> | ||||||
320 | |||||||
321 | or with quoted parameters like: | ||||||
322 | |||||||
323 | <#TAG NAME="Value, including spaces etc."> | ||||||
324 | |||||||
325 | Tags may be embedded in other tags (as of version 1.5), e.g. | ||||||
326 | <#USERINFO DISPLAY="<#FAVORITE_COLOR>"> | ||||||
327 | |||||||
328 | The tag name is the first part after the opening <# of the whole tag. It must | ||||||
329 | be a simple identifier -- I recommend sticking to the character set [A-Z_] for | ||||||
330 | this. The following parameters are optional and only used if the tag-action is | ||||||
331 | a callback subroutine (see below). They are supplied in HTML-style name/value | ||||||
332 | pairs. The parameter name like the tag name must be a simple identifier, and | ||||||
333 | again I recommend that it is drawn from the character set [A-Z_]. The value | ||||||
334 | can be any string, quoted if it contains spaces and the like. Even if quoted, | ||||||
335 | it may not contain any of: | ||||||
336 | |||||||
337 | < > " & = | ||||||
338 | |||||||
339 | which should be replaced with their HTML escape equivalents: | ||||||
340 | |||||||
341 | < > " & = | ||||||
342 | |||||||
343 | This may be a bug. At present, other HTML escapes are not permitted in the | ||||||
344 | value. This may also be a bug. | ||||||
345 | |||||||
346 | Tag names and parameter names are, by default, case-insensitive (they are | ||||||
347 | converted to upper-case when supplied). You can change this behaviour by | ||||||
348 | using the auto_cap() method. I don't recommend doing that, though. | ||||||
349 | |||||||
350 | There are four special parameters that can be supplied to any tag, HTMLESC and | ||||||
351 | URLESC. Two of them cause the text returned by the tag to be HTML or URL escaped, | ||||||
352 | which makes outputting data from plain-text sources like databases or text | ||||||
353 | files easier for the programmer. An example might be: | ||||||
354 | |||||||
355 | <#FULL_NAME HTMLESC> | ||||||
356 | |||||||
357 | which would let the programmer simply put the full-name data into the tag | ||||||
358 | without first escaping it. Another might be: | ||||||
359 | |||||||
360 | |||||||
361 | |||||||
362 | |||||||
363 | |||||||
364 | A typical template might look like: | ||||||
365 | |||||||
366 | |
||||||
367 | |||||||
368 | |||||||
369 | This is a tag: <#TAG> |
||||||
370 | |||||||
371 | This is a list: |
||||||
372 | |||||||
373 | <#LIST> | ||||||
374 | |||||||
375 | This is a tag that calls a callback: <#ITEM ID=358> |
||||||
376 | |||||||
377 | |||||||
378 | |||||||
379 | Note that it is a full HTML document. | ||||||
380 | |||||||
381 | =head1 TAGS | ||||||
382 | |||||||
383 | You can supply the tags that will be used for substitutions in several ways. | ||||||
384 | Firstly, you can set the tags that will be used directly, erasing all tags | ||||||
385 | currently stored, using the tags() method. This method -- when given an | ||||||
386 | argument -- removes all present tags and replaces them with tags drawn from the | ||||||
387 | hash-reference you must supply. For example: | ||||||
388 | |||||||
389 | tags( +{ FOO => 'A string called foo.', | ||||||
390 | BAR => 'A string called bar.' } ); | ||||||
391 | |||||||
392 | The keys to the hash-ref supplied are the tag names; the values are the | ||||||
393 | substitution actions (see below for more details on actions). | ||||||
394 | |||||||
395 | If you have an existing hash you can use it to define several tags. | ||||||
396 | For example: | ||||||
397 | |||||||
398 | tags( \%ENV ); | ||||||
399 | |||||||
400 | would add a tag for each environment variable in the %ENV hash. | ||||||
401 | |||||||
402 | Secondly, you can use the add_tags() method to add all the tags in the supplied | ||||||
403 | hash-ref to the existing tags, replacing the existing ones where there is | ||||||
404 | conflict. For example: | ||||||
405 | |||||||
406 | add_tags( +{ FOOBAR => 'A string called foobar added.', | ||||||
407 | BAR => 'This replaces the previous value for BAR' } ); | ||||||
408 | |||||||
409 | Thirdly, you can add a single tag with add_tag(), which takes two arguments, | ||||||
410 | the tag name and the tag value. For example: | ||||||
411 | |||||||
412 | add_tag( FOO => 'This replaces the previous value for FOO' ); | ||||||
413 | |||||||
414 | Which one of these is the best one to use depends on your application and | ||||||
415 | coding style, of course. | ||||||
416 | |||||||
417 | =head1 ACTIONS | ||||||
418 | |||||||
419 | Whichever way you choose to supply tags for substitutions, you will need to | ||||||
420 | supply an action for each tag. These come in two sorts: scalar values (or | ||||||
421 | scalar refs, which are treated the same way), and subroutine references for | ||||||
422 | callbacks. | ||||||
423 | |||||||
424 | =head2 Scalar Text Values | ||||||
425 | |||||||
426 | A scalar text value is simply used as a string and substituted in the | ||||||
427 | output when parsed. All of the following are scalar text values: | ||||||
428 | |||||||
429 | tags( +{ FOO => 'The string foo.', # Single-quoted string | ||||||
430 | BAR => "$ENV{ USER }", # Double-quoted string | ||||||
431 | LIST => join( ' |
||||||
432 | } ); | ||||||
433 | |||||||
434 | =head2 Subroutine References | ||||||
435 | |||||||
436 | If the tag action is a subroutine reference then it is treated as a callback. | ||||||
437 | The value supplied to it is a single hash-ref containing the parameter | ||||||
438 | name/value pairs supplied in the tag in the template. For example, | ||||||
439 | if the tag looked like: | ||||||
440 | |||||||
441 | <#TAG NAME="Value"> | ||||||
442 | |||||||
443 | the callback would have an @_ that looked like: | ||||||
444 | |||||||
445 | +{ NAME => 'Value' } | ||||||
446 | |||||||
447 | The callback must return a simple scalar value that will be substituted in the | ||||||
448 | output. For example: | ||||||
449 | |||||||
450 | add_tag( TAG => sub { | ||||||
451 | my( $params ) = @_; | ||||||
452 | my $name = $params->{ NAME }; | ||||||
453 | my $text = DatabaseLookup("$name"); | ||||||
454 | return $text; | ||||||
455 | } | ||||||
456 | } ); | ||||||
457 | |||||||
458 | |||||||
459 | You can use these callbacks to allow the HTML coder to look up data in a | ||||||
460 | database, to set global configuration parameters, and many other situations | ||||||
461 | where you wish to allow more flexible user of your templates. | ||||||
462 | |||||||
463 | For example, the supplied value can be the key to a database lookup and the | ||||||
464 | callback returns a value from the database; or it can be used to set context | ||||||
465 | for succeeding tags so that they return different values. This sort of thing | ||||||
466 | is tricky to code but easy to use for the HTMLer, and can save a great deal of | ||||||
467 | future coding work. | ||||||
468 | |||||||
469 | =head2 Default Action | ||||||
470 | |||||||
471 | If no action is supplied for a tag, the default action is used. The default | ||||||
472 | default action is to confess() with an error, since usually the use of unknown tags | ||||||
473 | indicates a bug in the application. You may wish to simply ignore unknown tags | ||||||
474 | and replace them with blank space, in which case you can use the | ||||||
475 | unknown_action() method to change it. If you wish to ignore unknown | ||||||
476 | tags, you set this to the special value ``IGNORE''. For example: | ||||||
477 | |||||||
478 | unknown_action( 'IGNORE' ); | ||||||
479 | |||||||
480 | Unknown tags will then be left in the output (and typically ignored by | ||||||
481 | web browsers.) The default action is indicated by the special value | ||||||
482 | ``CONFESS''. If you want to have unknown tags just be replaced by warning text | ||||||
483 | (and be logged with a cluck() call), use the special value ``CLUCK''. | ||||||
484 | For example: | ||||||
485 | |||||||
486 | unknown_action( 'CLUCK' ); | ||||||
487 | |||||||
488 | If the default action is a subroutine reference then the name of the | ||||||
489 | unknown tag is passed as a parameter called ''TAG''. For example: | ||||||
490 | |||||||
491 | unknown_action( sub { | ||||||
492 | my( $params ) = @_; | ||||||
493 | my $tagname = $params->{ TAG }; | ||||||
494 | return ""; | ||||||
495 | } ); | ||||||
496 | |||||||
497 | You may also specify a custom string to be substituted for any | ||||||
498 | unknown tags. For example: | ||||||
499 | |||||||
500 | unknown_action( '***Unknown Tag Used Here***' ); | ||||||
501 | |||||||
502 | =head1 PARSING | ||||||
503 | |||||||
504 | Once you have some tags defined by your program you need to specify which | ||||||
505 | template to parse and replace tags in. | ||||||
506 | |||||||
507 | You can supply a string to parse, or the name of file to use. | ||||||
508 | The latter is usually easier. For example: | ||||||
509 | |||||||
510 | template_string( 'A string containing some tag: <#FOO>' ); | ||||||
511 | |||||||
512 | or: | ||||||
513 | |||||||
514 | template_file( 'template.htmlt' ); | ||||||
515 | |||||||
516 | These methods just set the internal string or file to look for; the actual | ||||||
517 | parsing is done by the parse() or parse_file() methods. | ||||||
518 | These return the parsed template, they don't store it internally | ||||||
519 | anywhere, so you have to store or print it yourself. For example: | ||||||
520 | |||||||
521 | print parse_file; | ||||||
522 | |||||||
523 | will print the current template file using the current set of tags for | ||||||
524 | substitutions. Or: | ||||||
525 | |||||||
526 | $parsed = parse; | ||||||
527 | |||||||
528 | will put the parsed string into $parsed using the current string and tags for | ||||||
529 | substitutions. | ||||||
530 | |||||||
531 | These methods can also be called using more parameters to skip the internally | ||||||
532 | stored strings, files, and tags. See the per-method documentation below for | ||||||
533 | more details; it's probably easier to do it the step-by-step method, though. | ||||||
534 | |||||||
535 | =head1 MAKING LISTS | ||||||
536 | |||||||
537 | One of the things that often comes up in CGI applications is the need to | ||||||
538 | produce a list of results -- say from a search engine. | ||||||
539 | |||||||
540 | Because you don't | ||||||
541 | necessarily know in advance the number of elements, and usually you want each | ||||||
542 | element formatted identically, it's hard to do this in a single template. | ||||||
543 | |||||||
544 | This | ||||||
545 | module provides a convenient interface for doing this using two templates | ||||||
546 | for each list, each a fragment of the completed list. The ``entry'' | ||||||
547 | template is used for each entry in the list. | ||||||
548 | The ``join'' template is inserted in between each pair of entries. | ||||||
549 | You only need to use a ''join'' template if you, say, want a | ||||||
550 | dividing line between each | ||||||
551 | entry but not one following the end of the list. The entry template | ||||||
552 | is the interesting one. | ||||||
553 | |||||||
554 | There's a complicated way of making a list tag and an easy way. I suggest | ||||||
555 | using the easy way. Let's say you have three items in a list and each of them | ||||||
556 | is a hashref containing a row from a database. You also have a file with a | ||||||
557 | template fragment that has tags with the same names as the columns in that | ||||||
558 | database. To make a list using three copies of that template and add it as a | ||||||
559 | tag to the current template object, you can do: | ||||||
560 | |||||||
561 | add_list_tag( ITEM_LIST => \@list ); | ||||||
562 | |||||||
563 | and then when you use the tag, you can specify the template file in a parameter like this: | ||||||
564 | |||||||
565 | <#ITEM_LIST ENTRY_FILE="entry.htmlf"> | ||||||
566 | |||||||
567 | If the columns in the database are "name", "address" and "phone", that template might look like: | ||||||
568 | |||||||
569 | |
||||||
570 | Address: <#ADDRESS HTMLESC> |
||||||
571 | Phone: <#PHONE HTMLESC | ||||||
572 | |||||||
573 | Note that the path to the template can be absolute or relative; it can | ||||||
574 | be any file on the system, so make sure you trust your HTML people if you | ||||||
575 | use this method to make a list tag for them. | ||||||
576 | |||||||
577 | The second argument to add_list_tag is that list of tag hashrefs. It might | ||||||
578 | look like: | ||||||
579 | |||||||
580 | +[ +{ | ||||||
581 | NAME => 'Jacob', | ||||||
582 | ADDRESS => 'A place', | ||||||
583 | PHONE => 'Some phone', | ||||||
584 | }, +{ | ||||||
585 | NAME => 'Matisse', | ||||||
586 | ADDRESS => 'Another place', | ||||||
587 | PHONE => 'A different phone', | ||||||
588 | }, ] | ||||||
589 | |||||||
590 | and for each entry in that list, it will use the hash ref as a miniature | ||||||
591 | set of tags for that entry. | ||||||
592 | |||||||
593 | If you want to use the long way to make a list (not recommended; it's what | ||||||
594 | add_list_tag() uses internally), there are three things you need to set: | ||||||
595 | |||||||
596 | =item A list (array). | ||||||
597 | |||||||
598 | =item An entry template. | ||||||
599 | |||||||
600 | =item A subroutine that takes one element of the list as an argument and | ||||||
601 | returns a hash reference to a set of tags (which should appear in the | ||||||
602 | entry_template.) | ||||||
603 | |||||||
604 | You set the list of elements that you want to be made into a parsed list using | ||||||
605 | the list() method. It just takes a list. Obviously, the ordering in that list | ||||||
606 | is important. Each element is a scalar, but it can be a reference, of course, | ||||||
607 | and will usually be either a key or a reference to a more complex set of data. | ||||||
608 | For example: | ||||||
609 | |||||||
610 | list( $jacob, $matisse, $alejandro ); | ||||||
611 | |||||||
612 | or | ||||||
613 | list( \%hash1, \%hash2, \%hash3 ); | ||||||
614 | |||||||
615 | You set the templates for the entry and join templates with the entry_string() | ||||||
616 | & join_string() or entry_file() & join_file() methods. These work in the way | ||||||
617 | you would expect. For example: | ||||||
618 | |||||||
619 | entry_string( ' Name: <#NAME> City: <#CITY> ' ); |
||||||
620 | join_string( '' ); | ||||||
621 | |||||||
622 | or: | ||||||
623 | |||||||
624 | entry_file( 'entry.htmlf' ); | ||||||
625 | join_file( 'join.htmlf' ); | ||||||
626 | |||||||
627 | Usually the _file methods are the ones you want. | ||||||
628 | |||||||
629 | In the join template, you can either just use the existing tags stored in the | ||||||
630 | object (which is recommended, since usually you don't care what's in the join | ||||||
631 | template, if you use it at all) or you can supply your own set of tags with the | ||||||
632 | join_tags() method, which works just like the tags() method. | ||||||
633 | |||||||
634 | The complicated part is the callback. You must supply a subroutine | ||||||
635 | to generate the tags for each entry. It's easier than it seems. | ||||||
636 | |||||||
637 | The callback is set with the entry_callback() method. It is called | ||||||
638 | for each entry in the list, and its sole argument will be the item | ||||||
639 | we are looking at from the list, a single scalar. It must return a | ||||||
640 | hash-ref of name/action pairs of the tags that appear in the | ||||||
641 | entry template. A callback might look like this: | ||||||
642 | |||||||
643 | entry_callback( sub { | ||||||
644 | my( $person ) = @_; # $person is assumed to be a hash-ref | ||||||
645 | |||||||
646 | my $tags= +{ NAME => $person->name, | ||||||
647 | CITY => $person->city }; | ||||||
648 | |||||||
649 | return $tags; | ||||||
650 | } ); | ||||||
651 | |||||||
652 | You then have to make the list from this stuff, using the parse_list() or | ||||||
653 | parse_list_files() methods. These return the full parsed list as a string. | ||||||
654 | For example: | ||||||
655 | |||||||
656 | $list = parse_list; | ||||||
657 | |||||||
658 | or more often you'll be wanting to put that into another tag to put into your | ||||||
659 | full-page template, like: | ||||||
660 | |||||||
661 | add_tag( LIST => parse_list_files ); | ||||||
662 | |||||||
663 | That example above might produce a parsed list looking like: | ||||||
664 | |||||||
665 | Name: Jacob City: Norwich |
||||||
666 | Name: Matisse City: San Francisco |
||||||
667 | Name: Alejandro City: San Francisco |
||||||
668 | |||||||
669 | which you could then insert into your output. | ||||||
670 | |||||||
671 | If you're lazy and each item in your list is either a hashref or can easily | ||||||
672 | be turned into one (for example, by returning a row from a database as a | ||||||
673 | hashref) you may just want to return it directly, like this: | ||||||
674 | |||||||
675 | entry_callback( sub { | ||||||
676 | ( $userid ) = @_; | ||||||
677 | $sth = $dbh->prepare( <<"EOS" ); | ||||||
678 | SELECT * FROM users WHERE userid = "$userid" | ||||||
679 | EOS | ||||||
680 | $sth->execute; | ||||||
681 | return $sth->fetchrow_hashref; | ||||||
682 | } ); | ||||||
683 | |||||||
684 | or more even more lazily, something like this: | ||||||
685 | |||||||
686 | $sth = $dbh->prepare( <<"EOS" ); | ||||||
687 | SELECT * FROM users | ||||||
688 | EOS | ||||||
689 | $sth->execute; | ||||||
690 | while ( $user = $sth->fetchrow_hashref ) { | ||||||
691 | push @users, $user; | ||||||
692 | } | ||||||
693 | list( @users ); | ||||||
694 | entry_callback( sub { return $_[ 0 ] } ); | ||||||
695 | |||||||
696 | Isn't that easy? What's even easier is that the default value for | ||||||
697 | entry_callback() is C, so if your list is a list | ||||||
698 | of hashrefs, you don't even need to touch it. | ||||||
699 | |||||||
700 | =head1 WHICH INTERFACE? | ||||||
701 | |||||||
702 | You have a choice when using this module. You may either use an | ||||||
703 | object-oriented interface, where you create new instances of | ||||||
704 | Text::TagTemplate objects and call methods on them, or you may use the | ||||||
705 | conventional interface, where you import these methods into your namespace and | ||||||
706 | call them without an object reference. This is very similar to the way the CGI | ||||||
707 | module does things. I recommend the latter method, because the other forces | ||||||
708 | you to do a lot of object referencing that isn't particularly clear to read. | ||||||
709 | You might need to use it if you want multiple objects or you are concerned | ||||||
710 | about namespace conflicts. You'll also want to use the object interface | ||||||
711 | if you're running under mod_perl, because mod_perl uses a global to | ||||||
712 | store the template object, and it won't get deallocated between handler calls. | ||||||
713 | |||||||
714 | For the OO interface, just use: | ||||||
715 | |||||||
716 | use Text::TagTemplate; | ||||||
717 | my $parser = new Text::TagTemplate; | ||||||
718 | |||||||
719 | For the conventional interface, use: | ||||||
720 | |||||||
721 | use Text::TagTemplate qw( :standard ); | ||||||
722 | |||||||
723 | and you'll get all the commonly-used methods automatically imported. If you | ||||||
724 | want the more obscure configuration methods, you can have them too with: | ||||||
725 | |||||||
726 | use Text::TagTemplate qw( :standard :config ); | ||||||
727 | |||||||
728 | The examples given here all use the conventional interface, for clarity. The | ||||||
729 | OO interface would look like: | ||||||
730 | |||||||
731 | $parser = new Text::TagTemplate; | ||||||
732 | $parser->template_file( 'default.htmlt' ); | ||||||
733 | $parser->parse; | ||||||
734 | |||||||
735 | =cut | ||||||
736 | |||||||
737 | #=============================================================================== | ||||||
738 | # P U B L I C F U N C T I O N S | ||||||
739 | #=============================================================================== | ||||||
740 | |||||||
741 | =head1 PER-METHOD DOCUMENTATION | ||||||
742 | |||||||
743 | The following are the public methods provided by B |
||||||
744 | |||||||
745 | =cut | ||||||
746 | |||||||
747 | #------------------------------------------------------------------------------- | ||||||
748 | |||||||
749 | =head1 B |
||||||
750 | |||||||
751 | Instantiate a new template object. | ||||||
752 | Optionally take a hash or hash-ref of tags to add initially. | ||||||
753 | |||||||
754 | my $parser = Text::TagTemplate->new(); | ||||||
755 | my $parser = Text::TagTemplate->new( %tags ); | ||||||
756 | my $parser = Text::TagTemplate->new( \%tags ); | ||||||
757 | |||||||
758 | =cut | ||||||
759 | |||||||
760 | sub new | ||||||
761 | { | ||||||
762 | 3 | 3 | 0 | 873 | my( $class, @tags ) = @_; | ||
763 | 3 | 7 | my $self = +{}; | ||||
764 | 3 | 33 | 13 | $class = ref( $class ) || $class; | |||
765 | |||||||
766 | 3 | 5 | $self->{ AUTO_CAP } = 1; | ||||
767 | 3 | 5 | $self->{ UNKNOWN_ACTION } = 'CONFESS'; | ||||
768 | |||||||
769 | 3 | 5 | $self->{ TAGS } = +{}; | ||||
770 | 3 | 5 | $self->{ STRING } = ''; | ||||
771 | 3 | 3 | $self->{ FILE } = undef; | ||||
772 | 3 | 5 | $self->{ LIST } = []; | ||||
773 | 3 | 3 | $self->{ ENTRY_STRING } = ''; | ||||
774 | 3 | 7 | $self->{ ENTRY_FILE } = undef; | ||||
775 | 3 | 0 | 11 | $self->{ ENTRY_CALLBACK } = sub { return $_[ 0 ] }; | |||
0 | 0 | ||||||
776 | 3 | 6 | $self->{ JOIN_STRING } = ''; | ||||
777 | 3 | 5 | $self->{ JOIN_FILE } = undef; | ||||
778 | 3 | 4 | $self->{ JOIN_TAGS } = undef; | ||||
779 | 3 | 11 | $self->{ TAG_START } = '<#'; | ||||
780 | 3 | 4 | $self->{ TAG_CONTENTS } = '[^<>]*'; | ||||
781 | 3 | 4 | $self->{ TAG_END } = '>'; | ||||
782 | |||||||
783 | 3 | 6 | bless $self, $class; | ||||
784 | |||||||
785 | 3 | 100 | 9 | $self->add_tags( @tags ) if @tags; | |||
786 | 3 | 9 | return $self; | ||||
787 | } | ||||||
788 | |||||||
789 | |||||||
790 | =head1 Setting the Tag Pattern | ||||||
791 | |||||||
792 | The default pattern for tags is C |
||||||
793 | This is implemented internally as a regular expression: | ||||||
794 | C<(?-xism:E |
||||||
795 | override using the next three methods I |
||||||
796 | and I |
||||||
797 | |||||||
798 | For example, you might want to use a pattern for tags that does I |
||||||
799 | like HTML tags, perhaps to avoid confusing some HTML parsing tool. | ||||||
800 | |||||||
801 | Examples; | ||||||
802 | |||||||
803 | To use tags like this: | ||||||
804 | |||||||
805 | /* TAGNAME attribute=value attribute2=value */ | ||||||
806 | |||||||
807 | Do this: | ||||||
808 | |||||||
809 | tag_start('/\*'); # you must escape the * character | ||||||
810 | tag_contents('[^*]*'); # * inside [] does not need escaping | ||||||
811 | tag_end('\*/'); # escape the * | ||||||
812 | |||||||
813 | =cut | ||||||
814 | |||||||
815 | #------------------------------------------------------------------------------- | ||||||
816 | |||||||
817 | =over 4 | ||||||
818 | |||||||
819 | =item C |
||||||
820 | |||||||
821 | Set and or get the pattern used to find the start of tags. | ||||||
822 | |||||||
823 | With no arguments returns the current value. The default value is C |
||||||
824 | |||||||
825 | If an argument is supplied it is used to replace the current value. | ||||||
826 | Returns the new value. | ||||||
827 | |||||||
828 | See also tag_contents() and tag_end(), below. | ||||||
829 | |||||||
830 | =cut | ||||||
831 | |||||||
832 | sub tag_start { | ||||||
833 | 2 | 2 | 1 | 5 | my($self,$pattern) = _self_or_default @_; | ||
834 | 2 | 50 | 6 | if ($pattern) { | |||
835 | 2 | 5 | $self->{TAG_START} = $pattern; | ||||
836 | } | ||||||
837 | 2 | 3 | return $self->{TAG_START}; | ||||
838 | } | ||||||
839 | |||||||
840 | #------------------------------------------------------------------------------- | ||||||
841 | |||||||
842 | =item C |
||||||
843 | |||||||
844 | Set and or get the pattern used to find the content of tags, that is | ||||||
845 | the stuff in between the I |
||||||
846 | |||||||
847 | With no arguments returns the current value. The default value is C<[^E |
||||||
848 | |||||||
849 | If an argument is supplied it is used to replace the current value. | ||||||
850 | Returns the new value. | ||||||
851 | |||||||
852 | |||||||
853 | The pattern should be something that matches any number of characters that | ||||||
854 | are not the end of the tag. (See I |
||||||
855 | use an atom followed by *. In the defaul pattern C<[^E |
||||||
856 | C<[^E |
||||||
857 | E |
||||||
858 | |||||||
859 | Examples: | ||||||
860 | |||||||
861 | Set the contents pattern to match anything that is not C<--> | ||||||
862 | |||||||
863 | =cut | ||||||
864 | |||||||
865 | sub tag_contents { | ||||||
866 | 2 | 2 | 1 | 5 | my($self,$pattern) = _self_or_default @_; | ||
867 | 2 | 50 | 7 | if ($pattern) { | |||
868 | 2 | 3 | $self->{TAG_CONTENTS} = $pattern; | ||||
869 | } | ||||||
870 | 2 | 5 | return $self->{TAG_CONTENTS}; | ||||
871 | } | ||||||
872 | |||||||
873 | #------------------------------------------------------------------------------- | ||||||
874 | |||||||
875 | =item C |
||||||
876 | |||||||
877 | Set and or get the pattern used to find the end of tags. | ||||||
878 | |||||||
879 | With no arguments returns the current value. The default value is C |
||||||
880 | |||||||
881 | If an argument is supplied it is used to replace the current value. | ||||||
882 | Returns the new value. | ||||||
883 | |||||||
884 | =cut | ||||||
885 | |||||||
886 | sub tag_end { | ||||||
887 | 2 | 2 | 1 | 4 | my($self,$pattern) = _self_or_default @_; | ||
888 | 2 | 50 | 6 | if ($pattern) { | |||
889 | 2 | 3 | $self->{TAG_END} = $pattern; | ||||
890 | } | ||||||
891 | 2 | 4 | return $self->{TAG_END}; | ||||
892 | } | ||||||
893 | |||||||
894 | #------------------------------------------------------------------------------- | ||||||
895 | |||||||
896 | =item C |
||||||
897 | |||||||
898 | Returns the complete pattern used to find tags. The value is returned as a | ||||||
899 | quoted regular expression. The default value is C<(?-xism:E |
||||||
900 | |||||||
901 | Equivalant to: | ||||||
902 | |||||||
903 | $start = tag_start(); | ||||||
904 | $contents = tag_contents(); | ||||||
905 | $end = tag_end(); | ||||||
906 | return qr/$start($contents)$end/; | ||||||
907 | |||||||
908 | =cut | ||||||
909 | |||||||
910 | sub tag_pattern { | ||||||
911 | 108 | 108 | 0 | 152 | my ($self) = _self_or_default @_; | ||
912 | 108 | 579 | return qr/$self->{TAG_START}($self->{TAG_CONTENTS})$self->{TAG_END}/; | ||||
913 | } | ||||||
914 | |||||||
915 | #------------------------------------------------------------------------------- | ||||||
916 | |||||||
917 | =item C |
||||||
918 | |||||||
919 | Returns whether tag names will automatically be capitalised, and if a value | ||||||
920 | is supplied sets the auto-capitalisation to this value first. Default is | ||||||
921 | 1; changing it is not recommended but hey go ahead and ignore me anyway, | ||||||
922 | what do I know? Setting it to false will make tag names case-sensitive and | ||||||
923 | you probably don't want that. | ||||||
924 | |||||||
925 | =cut | ||||||
926 | |||||||
927 | sub auto_cap | ||||||
928 | { | ||||||
929 | 2 | 2 | 1 | 223 | my( $self, $auto_cap ) = _self_or_default @_; | ||
930 | 2 | 50 | 5 | $self->{ AUTO_CAP } = $auto_cap if defined $auto_cap; | |||
931 | 2 | 10 | return $self->{ AUTO_CAP }; | ||||
932 | } | ||||||
933 | |||||||
934 | #------------------------------------------------------------------------------- | ||||||
935 | |||||||
936 | =item C |
||||||
937 | |||||||
938 | Returns what to do with unknown tags. If a value is supplied sets the action | ||||||
939 | to this value first. If the action is the special value 'CONFESS' then it will | ||||||
940 | confess() at that point. This is the default. If the action is the special | ||||||
941 | value 'IGNORE' then unknown tags will be ignored by the module, and | ||||||
942 | will appear unchanged in the parsed output. If the special value 'CLUCK' is | ||||||
943 | used then the the unknown tags will be replaced by warning text and logged with a cluck() call. (See L |
||||||
944 | like warn() and (die(), but with a stack trace.) | ||||||
945 | Other special values may be supplied later, so if scalar | ||||||
946 | actions are require it is suggested that a scalar ref be supplied, where | ||||||
947 | these special actions will not be taken no matter what the value. | ||||||
948 | |||||||
949 | =cut | ||||||
950 | |||||||
951 | sub unknown_action | ||||||
952 | { | ||||||
953 | 3 | 3 | 1 | 20 | my( $self, $unknown_action ) = _self_or_default @_; | ||
954 | 3 | 100 | 9 | $self->{ UNKNOWN_ACTION } = $unknown_action if defined $unknown_action; | |||
955 | 3 | 11 | return $self->{ UNKNOWN_ACTION }; | ||||
956 | } | ||||||
957 | |||||||
958 | #------------------------------------------------------------------------------- | ||||||
959 | |||||||
960 | =item C |
||||||
961 | |||||||
962 | Returns the contents of the tags as a hash-ref of tag/action pairs. | ||||||
963 | If tags are supplied as a hash or hashref, it first sets the contents to | ||||||
964 | these tags, clearing all previous tags. | ||||||
965 | |||||||
966 | =cut | ||||||
967 | |||||||
968 | sub tags | ||||||
969 | { | ||||||
970 | 10 | 10 | 1 | 21 | my( $self, @tags ) = _self_or_default @_; | ||
971 | 10 | 100 | 23 | if ( @tags ) { | |||
972 | 2 | 8 | $self->clear_tags; | ||||
973 | 2 | 6 | $self->add_tags( @tags ); | ||||
974 | } | ||||||
975 | 10 | 73 | return $self->{ TAGS }; | ||||
976 | } | ||||||
977 | |||||||
978 | #------------------------------------------------------------------------------- | ||||||
979 | |||||||
980 | =item C |
||||||
981 | |||||||
982 | Adds a new tag. Takes a tag name and the tag action. | ||||||
983 | |||||||
984 | =cut | ||||||
985 | |||||||
986 | # *** DEBUG *** Probably redundant. | ||||||
987 | |||||||
988 | sub add_tag | ||||||
989 | { | ||||||
990 | 7 | 7 | 1 | 16 | my( $self, $name, $action ) = _self_or_default @_; | ||
991 | 7 | 50 | 22 | $name = uc $name if $self->{ AUTO_CAP }; | |||
992 | 7 | 17 | $self->{ TAGS }->{ $name } = $action; | ||||
993 | 7 | 15 | return 1; | ||||
994 | } | ||||||
995 | |||||||
996 | sub list_tag | ||||||
997 | { | ||||||
998 | 1 | 1 | 0 | 6 | my( $self, $list, $entry_callback, @join_tags ) | ||
999 | = _self_or_default @_; | ||||||
1000 | |||||||
1001 | return sub { | ||||||
1002 | 1 | 1 | 2 | my %params = %{ $_[ 0 ] }; | |||
1 | 4 | ||||||
1003 | 1 | 2 | my( $entry_string, $join_string ); | ||||
1004 | 1 | 50 | 6 | if ( exists $params{ ENTRY_STRING } ) { | |||
50 | |||||||
1005 | 0 | 0 | $entry_string = $params{ ENTRY_STRING }; | ||||
1006 | } elsif ( exists $params{ ENTRY_FILE } ) { | ||||||
1007 | 1 | 3 | $entry_string = _get_file $params{ ENTRY_FILE }; | ||||
1008 | } else { | ||||||
1009 | 0 | 0 | $entry_string = ''; | ||||
1010 | } | ||||||
1011 | 1 | 50 | 6 | if ( exists $params{ JOIN_STRING } ) { | |||
50 | |||||||
1012 | 0 | 0 | $join_string = $params{ JOIN_STRING }; | ||||
1013 | } elsif ( exists $params{ JOIN_FILE } ) { | ||||||
1014 | 0 | 0 | $join_string = _get_file $params{ JOIN_FILE }; | ||||
1015 | } else { | ||||||
1016 | 1 | 2 | $join_string = ''; | ||||
1017 | } | ||||||
1018 | 1 | 4 | return $self->parse_list( $list, $entry_string, $join_string, | ||||
1019 | $entry_callback, @join_tags ); | ||||||
1020 | 1 | 5 | }; | ||||
1021 | } | ||||||
1022 | #------------------------------------------------------------------------------- | ||||||
1023 | |||||||
1024 | =item C |
||||||
1025 | |||||||
1026 | Add a tag that will build a parsed list, allowing the person using the tag to | ||||||
1027 | supply the filename of the entry and join templates, or to supply the strings | ||||||
1028 | directly in tag parameters (which is currently annoying given the way they need | ||||||
1029 | to be escaped). The tag will take parameters for ENTRY_STRING, ENTRY_FILE, | ||||||
1030 | JOIN_STRING or JOIN_FILE. | ||||||
1031 | |||||||
1032 | No checking is currently performed on the filenames given. This shouldn't be a security problem unless you're allowing untrusted users to write your templates for you, which mean it's a bug that I need to fix (since I want untrusted users to be able to write templates under some circumstnaces). | ||||||
1033 | |||||||
1034 | =cut | ||||||
1035 | |||||||
1036 | sub add_list_tag | ||||||
1037 | { | ||||||
1038 | 1 | 1 | 1 | 2 | my( $self, $tag_name, $list, $entry_callback, @join_tags ) | ||
1039 | = _self_or_default @_; | ||||||
1040 | |||||||
1041 | 1 | 6 | $self->add_tag( | ||||
1042 | $tag_name=> $self->list_tag( $list, $entry_callback, | ||||||
1043 | @join_tags ) | ||||||
1044 | ); | ||||||
1045 | 1 | 3 | return 1; | ||||
1046 | } | ||||||
1047 | |||||||
1048 | #------------------------------------------------------------------------------- | ||||||
1049 | |||||||
1050 | =item C |
||||||
1051 | |||||||
1052 | Adds a bunch of tags. Takes a hash or hash-ref of tag/action pairs. | ||||||
1053 | |||||||
1054 | =cut | ||||||
1055 | |||||||
1056 | sub add_tags | ||||||
1057 | { | ||||||
1058 | 6 | 6 | 1 | 11 | my( $self, @tags ) = _self_or_default @_; | ||
1059 | 6 | 8 | my $tags; | ||||
1060 | 6 | 100 | 18 | if ( @tags > 1 ) { | |||
50 | |||||||
1061 | 4 | 19 | %$tags = @tags; | ||||
1062 | } elsif ( @tags == 1 ) { | ||||||
1063 | 2 | 3 | $tags = $tags[ 0 ]; | ||||
1064 | } | ||||||
1065 | 6 | 18 | foreach my $name ( keys %$tags ) { | ||||
1066 | 14 | 50 | 37 | my $uc_name = $self->{ AUTO_CAP } ? uc $name : $name; | |||
1067 | 14 | 38 | $self->{ TAGS }->{ $uc_name } = $tags->{ $name }; | ||||
1068 | } | ||||||
1069 | 6 | 22 | return 1; | ||||
1070 | } | ||||||
1071 | |||||||
1072 | #------------------------------------------------------------------------------- | ||||||
1073 | |||||||
1074 | =item C |
||||||
1075 | |||||||
1076 | Delete a tag by name. | ||||||
1077 | |||||||
1078 | =cut | ||||||
1079 | |||||||
1080 | sub delete_tag | ||||||
1081 | { | ||||||
1082 | 1 | 1 | 1 | 293 | my( $self, $name ) = _self_or_default @_; | ||
1083 | 1 | 50 | 5 | my $uc_name = $self->{ AUTO_CAP } ? uc $name : $name; | |||
1084 | 1 | 3 | delete $self->{ TAGS }->{ $uc_name }; | ||||
1085 | 1 | 3 | return 1; | ||||
1086 | } | ||||||
1087 | |||||||
1088 | #------------------------------------------------------------------------------- | ||||||
1089 | |||||||
1090 | =item C |
||||||
1091 | |||||||
1092 | Clears all existing tags. | ||||||
1093 | |||||||
1094 | =cut | ||||||
1095 | |||||||
1096 | sub clear_tags | ||||||
1097 | { | ||||||
1098 | 3 | 3 | 1 | 256 | my( $self ) = _self_or_default @_; | ||
1099 | 3 | 7 | $self->{ TAGS } = +{}; | ||||
1100 | 3 | 16 | return 1; | ||||
1101 | } | ||||||
1102 | |||||||
1103 | #------------------------------------------------------------------------------- | ||||||
1104 | |||||||
1105 | =item C
|
||||||
1106 | |||||||
1107 | Returns (and sets if supplied) the list of values to be used in parse_list() | ||||||
1108 | or parse_list_files() calls. | ||||||
1109 | |||||||
1110 | =cut | ||||||
1111 | |||||||
1112 | sub list | ||||||
1113 | { | ||||||
1114 | 2 | 2 | 1 | 320 | my( $self, @list ) = _self_or_default @_; | ||
1115 | 2 | 100 | 6 | $self->{ LIST } = \@list if @list; | |||
1116 | 2 | 3 | return @{ $self->{ LIST } }; | ||||
2 | 9 | ||||||
1117 | } | ||||||
1118 | |||||||
1119 | #------------------------------------------------------------------------------- | ||||||
1120 | |||||||
1121 | =item C |
||||||
1122 | |||||||
1123 | Returns (and sets if supplied) the default template string for parse(). | ||||||
1124 | |||||||
1125 | =cut | ||||||
1126 | |||||||
1127 | sub template_string | ||||||
1128 | { | ||||||
1129 | 2 | 2 | 1 | 5 | my( $self, $template_string ) = _self_or_default @_; | ||
1130 | 2 | 100 | 9 | $self->{ STRING } = $template_string if defined $template_string; | |||
1131 | 2 | 8 | return $self->{ STRING }; | ||||
1132 | } | ||||||
1133 | |||||||
1134 | #------------------------------------------------------------------------------- | ||||||
1135 | |||||||
1136 | =item C |
||||||
1137 | |||||||
1138 | Returns (and sets if supplied) the default template file for parse_file(). | ||||||
1139 | |||||||
1140 | =cut | ||||||
1141 | |||||||
1142 | sub template_file | ||||||
1143 | { | ||||||
1144 | 2 | 2 | 1 | 322 | my( $self, $template_file ) = _self_or_default @_; | ||
1145 | 2 | 100 | 7 | $self->{ FILE } = $template_file if defined $template_file; | |||
1146 | 2 | 8 | return $self->{ FILE }; | ||||
1147 | } | ||||||
1148 | |||||||
1149 | #------------------------------------------------------------------------------- | ||||||
1150 | |||||||
1151 | =item C |
||||||
1152 | |||||||
1153 | Returns (and sets if supplied) the entry string to be used in parse_list() | ||||||
1154 | calls. | ||||||
1155 | |||||||
1156 | =cut | ||||||
1157 | |||||||
1158 | sub entry_string | ||||||
1159 | { | ||||||
1160 | 2 | 2 | 1 | 6 | my( $self, $entry_string ) = _self_or_default @_; | ||
1161 | 2 | 100 | 6 | $self->{ ENTRY_STRING } = $entry_string if defined $entry_string; | |||
1162 | 2 | 8 | return $self->{ ENTRY_STRING }; | ||||
1163 | } | ||||||
1164 | |||||||
1165 | #------------------------------------------------------------------------------- | ||||||
1166 | |||||||
1167 | =item C |
||||||
1168 | |||||||
1169 | Returns (and sets if supplied) the entry file to be used in | ||||||
1170 | parse_list_files() calls. | ||||||
1171 | |||||||
1172 | =cut | ||||||
1173 | |||||||
1174 | sub entry_file | ||||||
1175 | { | ||||||
1176 | 2 | 2 | 1 | 6 | my( $self, $entry_file ) = _self_or_default @_; | ||
1177 | 2 | 100 | 8 | $self->{ ENTRY_FILE } = $entry_file if defined $entry_file; | |||
1178 | 2 | 8 | return $self->{ ENTRY_FILE }; | ||||
1179 | } | ||||||
1180 | |||||||
1181 | #------------------------------------------------------------------------------- | ||||||
1182 | |||||||
1183 | =item C |
||||||
1184 | |||||||
1185 | Returns (and sets if supplied) the callback sub to be used in parse_list() | ||||||
1186 | or parse_list_files() calls. If you don't set this, the default is just to | ||||||
1187 | return the item passed in, which will only work if the item is a hashref | ||||||
1188 | suitable for use as a set of tags. | ||||||
1189 | |||||||
1190 | =cut | ||||||
1191 | |||||||
1192 | sub entry_callback | ||||||
1193 | { | ||||||
1194 | 2 | 2 | 1 | 4 | my( $self, $entry_callback ) = _self_or_default @_; | ||
1195 | 2 | 100 | 8 | $self->{ ENTRY_CALLBACK } = $entry_callback if defined $entry_callback; | |||
1196 | 2 | 12 | return $self->{ ENTRY_CALLBACK }; | ||||
1197 | } | ||||||
1198 | |||||||
1199 | #------------------------------------------------------------------------------- | ||||||
1200 | |||||||
1201 | =item C |
||||||
1202 | |||||||
1203 | Returns (and sets if supplied) the join string to be used in parse_list() | ||||||
1204 | calls. | ||||||
1205 | |||||||
1206 | =cut | ||||||
1207 | |||||||
1208 | sub join_string | ||||||
1209 | { | ||||||
1210 | 2 | 2 | 1 | 4 | my( $self, $join_string ) = _self_or_default @_; | ||
1211 | 2 | 100 | 6 | $self->{ JOIN_STRING } = $join_string if defined $join_string; | |||
1212 | 2 | 8 | return $self->{ JOIN_STRING }; | ||||
1213 | } | ||||||
1214 | |||||||
1215 | #------------------------------------------------------------------------------- | ||||||
1216 | |||||||
1217 | =item C |
||||||
1218 | |||||||
1219 | Returns (and sets if supplied) the join file to be used in | ||||||
1220 | parse_list_files() calls. | ||||||
1221 | |||||||
1222 | =cut | ||||||
1223 | |||||||
1224 | sub join_file | ||||||
1225 | { | ||||||
1226 | 2 | 2 | 1 | 6 | my( $self, $join_file ) = _self_or_default @_; | ||
1227 | 2 | 100 | 6 | $self->{ JOIN_FILE } = $join_file if defined $join_file; | |||
1228 | 2 | 7 | return $self->{ JOIN_FILE }; | ||||
1229 | } | ||||||
1230 | |||||||
1231 | #------------------------------------------------------------------------------- | ||||||
1232 | |||||||
1233 | =item C |
||||||
1234 | |||||||
1235 | Returns (and sets if supplied) the join tags to be used in parse_list() and | ||||||
1236 | parse_list_files() calls. | ||||||
1237 | |||||||
1238 | =cut | ||||||
1239 | |||||||
1240 | sub join_tags | ||||||
1241 | { | ||||||
1242 | 4 | 4 | 1 | 8 | my( $self, @join_tags ) = _self_or_default @_; | ||
1243 | 4 | 5 | my $join_tags; | ||||
1244 | 4 | 100 | 13 | if ( @join_tags > 1 ) { | |||
100 | |||||||
1245 | 1 | 3 | %$join_tags = @join_tags; | ||||
1246 | } elsif ( @join_tags == 1 ) { | ||||||
1247 | 1 | 1 | $join_tags = $join_tags[ 0 ]; | ||||
1248 | } | ||||||
1249 | 4 | 100 | 8 | if ( defined $join_tags ) { | |||
1250 | 2 | 5 | $self->{ JOIN_TAGS } = +{}; | ||||
1251 | 2 | 9 | foreach my $name ( keys %$join_tags ) { | ||||
1252 | 4 | 50 | 10 | my $uc_name = $self->{ AUTO_CAP } ? uc $name : $name; | |||
1253 | 4 | 8 | $self->{ JOIN_TAGS }->{ $uc_name } | ||||
1254 | = $join_tags->{ $name }; | ||||||
1255 | } | ||||||
1256 | } | ||||||
1257 | 4 | 24 | return $self->{ JOIN_TAGS }; | ||||
1258 | } | ||||||
1259 | |||||||
1260 | #------------------------------------------------------------------------------- | ||||||
1261 | |||||||
1262 | =item C |
||||||
1263 | |||||||
1264 | Parse a string, either the default string, or a string supplied. | ||||||
1265 | Returns the string. Can optionally also take the tags hash or hash-ref directly | ||||||
1266 | as well. | ||||||
1267 | |||||||
1268 | =cut | ||||||
1269 | |||||||
1270 | sub parse | ||||||
1271 | { | ||||||
1272 | 106 | 106 | 1 | 175 | my( $self, $string, @tags ) = _self_or_default @_; | ||
1273 | 106 | 100 | 198 | $string = defined $string ? $string : $self->{ STRING }; | |||
1274 | 106 | 455 | my $tags; | ||||
1275 | 106 | 100 | 176 | if ( @tags ) { | |||
1276 | 83 | 100 | 122 | if ( @tags > 1 ) { | |||
1277 | 4 | 15 | %$tags = @tags; | ||||
1278 | } else { | ||||||
1279 | 79 | 82 | $tags = $tags[ 0 ]; | ||||
1280 | } | ||||||
1281 | 83 | 102 | my $uc_tags = +{}; | ||||
1282 | 83 | 178 | foreach my $name ( keys %$tags ) { | ||||
1283 | 91 | 50 | 225 | my $uc_name = $self->{ AUTO_CAP } ? uc $name : $name; | |||
1284 | 91 | 231 | $uc_tags->{ $uc_name } = $tags->{ $name }; | ||||
1285 | } | ||||||
1286 | 83 | 124 | $tags = $uc_tags; | ||||
1287 | } else { | ||||||
1288 | 23 | 39 | $tags = $self->{ TAGS }; | ||||
1289 | } | ||||||
1290 | |||||||
1291 | # Loop until we have replaced all the tags. | ||||||
1292 | 106 | 187 | my $regex = $self->tag_pattern(); | ||||
1293 | 106 | 551 | while ( $string =~ /$regex/g ) { | ||||
1294 | 119 | 205 | my $contents = $1; | ||||
1295 | 119 | 123 | my $q_contents = quotemeta $contents; | ||||
1296 | 119 | 141 | my $o_contents = $contents; # preserve in case we're ignoring. | ||||
1297 | # Remove leading and trailing whitespace. | ||||||
1298 | 119 | 212 | $contents =~ s/^\s+//; | ||||
1299 | 119 | 143 | $contents =~ s/\s+$//; | ||||
1300 | # Remove whitespace in quoted values. | ||||||
1301 | 119 | 130 | $contents =~ s|"([^"]*)"| | ||||
1302 | 8 | 16 | my $value = $1; | ||||
1303 | 8 | 18 | $value =~ s/ /\ /g; | ||||
1304 | 8 | 14 | $value =~ s/\t/\ /g; | ||||
1305 | 8 | 11 | $value =~ s/\n/\ /g; | ||||
1306 | 8 | 14 | $value =~ s/\r/\ /g; | ||||
1307 | 8 | 12 | $value =~ s/=/\=/g; | ||||
1308 | 8 | 21 | $value; | ||||
1309 | |egm; | ||||||
1310 | # Remove whitespace between parameters/equals-signs/values. | ||||||
1311 | 119 | 125 | $contents =~ s/\s+=\s+/=/g; | ||||
1312 | |||||||
1313 | 119 | 146 | my %params = (); | ||||
1314 | # Chop up the contents into the tag name and the params. | ||||||
1315 | 119 | 231 | my( $tag, @param_pairs ) = split ' ', $contents; | ||||
1316 | 119 | 177 | foreach my $param_pair ( @param_pairs ) { | ||||
1317 | # Split it; value is optional. | ||||||
1318 | 8 | 19 | my( $name, $value ) = split /=/, $param_pair; | ||||
1319 | 8 | 50 | 12 | $value = defined $value ? $value : ''; | |||
1320 | # Dequote the values. | ||||||
1321 | # *** DEBUG *** | ||||||
1322 | # Should use full de-HTML-escape here. | ||||||
1323 | 8 | 23 | $value =~ s/</ | ||||
1324 | 8 | 17 | $value =~ s/>/>/gi; | ||||
1325 | 8 | 13 | $value =~ s/"/"/gi; | ||||
1326 | 8 | 13 | $value =~ s/ / /g; | ||||
1327 | 8 | 20 | $value =~ s/ /\t/g; | ||||
1328 | 8 | 12 | $value =~ s/ /\n/g; | ||||
1329 | 8 | 9 | $value =~ s/ /\r/g; | ||||
1330 | 8 | 14 | $value =~ s/=/=/g; | ||||
1331 | 8 | 15 | $value =~ s/&/&/gi; | ||||
1332 | 8 | 50 | 23 | $name = uc $name if $self->{ AUTO_CAP }; | |||
1333 | 8 | 22 | $params{ $name } = $value; | ||||
1334 | } | ||||||
1335 | |||||||
1336 | 119 | 154 | my $uc_tag = uc $tag; | ||||
1337 | 119 | 146 | my $action = $tags->{ $uc_tag }; | ||||
1338 | 119 | 100 | 210 | unless ( exists $tags->{ $uc_tag } ) { | |||
1339 | 1 | 50 | 8 | if ( $self->{ UNKNOWN_ACTION } eq 'CONFESS' ) { | |||
50 | |||||||
50 | |||||||
1340 | 0 | 0 | confess "unknown tag: $tag"; | ||||
1341 | } elsif ( $self->{ UNKNOWN_ACTION } eq 'CLUCK' ) { | ||||||
1342 | 0 | 0 | $action = "unknown tag: $tag"; | ||||
1343 | 0 | 0 | cluck "unknown tag: $tag"; | ||||
1344 | } elsif ( $self->{ UNKNOWN_ACTION } eq 'IGNORE' ) { | ||||||
1345 | 1 | 17 | $string | ||||
1346 | =~ s/$self->{TAG_START}$q_contents$self->{TAG_END}/\000#$o_contents\000/; | ||||||
1347 | } else { | ||||||
1348 | # let sub refs know which tags this is. | ||||||
1349 | 0 | 0 | $params{ TAG } = $tag; | ||||
1350 | 0 | 0 | $action = $self->{ UNKNOWN_ACTION }; | ||||
1351 | } | ||||||
1352 | } | ||||||
1353 | # Undefined actions are assumed to mean just use ''. | ||||||
1354 | 119 | 100 | 166 | $action = '' unless defined $action; | |||
1355 | |||||||
1356 | 119 | 149 | my $rep; | ||||
1357 | 119 | 150 | my $type = ref $action; | ||||
1358 | 119 | 100 | 165 | unless ( $type ) { | |||
1359 | # Tag scalar replacement. | ||||||
1360 | 110 | 124 | $rep = $action; | ||||
1361 | } else { | ||||||
1362 | 9 | 50 | 20 | if ( $type eq 'SCALAR' ) { | |||
50 | |||||||
1363 | # Substitute scalar-refs as strings. | ||||||
1364 | 0 | 0 | $rep = $$action; | ||||
1365 | } elsif ( $type eq 'CODE' ) { | ||||||
1366 | # Code-refs are callbacks with the params. | ||||||
1367 | 9 | 28 | $rep = &$action( \%params ); | ||||
1368 | } else { | ||||||
1369 | # Bad action ref-type; just use ''. | ||||||
1370 | 0 | 0 | $rep = ''; | ||||
1371 | } | ||||||
1372 | } | ||||||
1373 | |||||||
1374 | # Now we might want to HTML-escape or URL-escape the text. | ||||||
1375 | 119 | 50 | 368 | if ( exists $params{ HTMLESC } ) { | |||
50 | |||||||
1376 | 0 | 0 | $rep = _htmlesc $rep; | ||||
1377 | } elsif ( exists $params{ URLESC } ) { | ||||||
1378 | 0 | 0 | $rep = _urlesc $rep; | ||||
1379 | } | ||||||
1380 | 119 | 50 | 261 | if ( exists $params{ SELECTEDIF } ) { | |||
50 | |||||||
1381 | 0 | 0 | 0 | if ( $rep eq $params{ VALUE } ) { | |||
1382 | 0 | 0 | $rep = 'SELECTED'; | ||||
1383 | } else { | ||||||
1384 | 0 | 0 | $rep = ''; | ||||
1385 | } | ||||||
1386 | } elsif ( exists $params{ CHECKEDIF } ) { | ||||||
1387 | 0 | 0 | 0 | if ( $rep eq $params{ VALUE } ) { | |||
1388 | 0 | 0 | $rep = 'CHECKED'; | ||||
1389 | } else { | ||||||
1390 | 0 | 0 | $rep = ''; | ||||
1391 | } | ||||||
1392 | } | ||||||
1393 | |||||||
1394 | # Substitute in the string. | ||||||
1395 | { | ||||||
1396 | 1 | 1 | 7 | no warnings; # Avoid stoopid warnings in case $rep is empty | |||
1 | 1 | ||||||
1 | 687 | ||||||
119 | 99 | ||||||
1397 | 119 | 2615 | $string =~ s/$self->{TAG_START}$q_contents$self->{TAG_END}/$rep/; | ||||
1398 | } | ||||||
1399 | } | ||||||
1400 | |||||||
1401 | 106 | 100 | 202 | if ( $self->{ UNKNOWN_ACTION } eq 'IGNORE' ) { | |||
1402 | 7 | 17 | $string =~ s/\000#([^\000]*)\000/$self->{TAG_START}$1$self->{TAG_END}/g; | ||||
1403 | } | ||||||
1404 | |||||||
1405 | 106 | 361 | return $string; | ||||
1406 | } | ||||||
1407 | |||||||
1408 | #------------------------------------------------------------------------------- | ||||||
1409 | |||||||
1410 | =item C |
||||||
1411 | |||||||
1412 | Parses a file, either the default file or the supplied filename. | ||||||
1413 | Returns the parsed file. Dies if the file cannot be read. Can optionally | ||||||
1414 | take the tags hash or hash-ref directly. | ||||||
1415 | |||||||
1416 | =cut | ||||||
1417 | |||||||
1418 | sub parse_file | ||||||
1419 | { | ||||||
1420 | 4 | 4 | 1 | 11 | my( $self, $file, @tags ) = _self_or_default @_; | ||
1421 | 4 | 100 | 12 | $file = defined $file ? $file : $self->{ FILE }; | |||
1422 | 4 | 6 | my $string = _get_file( $file ); | ||||
1423 | 4 | 11 | $string = $self->parse( $string, @tags ); | ||||
1424 | 4 | 21 | return $string; | ||||
1425 | } | ||||||
1426 | |||||||
1427 | #------------------------------------------------------------------------------- | ||||||
1428 | |||||||
1429 | =item C |
||||||
1430 | |||||||
1431 | =item or C |
||||||
1432 | |||||||
1433 | =item or C |
||||||
1434 | |||||||
1435 | Makes a string from a list of entries, either the default or a supplied list. | ||||||
1436 | |||||||
1437 | At least one template string is needed: the one to use for each entry, | ||||||
1438 | and another is optional, to be used to join the entries. | ||||||
1439 | |||||||
1440 | A callback subroutine must be supplied | ||||||
1441 | using entry_callback(), which takes the entry value from the list and must | ||||||
1442 | return a hash-ref of tags to be interpolated in the entry string. This will | ||||||
1443 | be called for each entry in the list. You can also supply a set of | ||||||
1444 | tags for the join string using join_tags(), but by default the main tags will | ||||||
1445 | be used in that string. | ||||||
1446 | |||||||
1447 | You can also optionally supply the strings for the entry and join template. | ||||||
1448 | Otherwise the strings set previously (with entry_string() and join_string() ) | ||||||
1449 | will be used. | ||||||
1450 | |||||||
1451 | Finally, you can also supply the callback sub and join tags directly if you | ||||||
1452 | want. | ||||||
1453 | |||||||
1454 | =cut | ||||||
1455 | |||||||
1456 | sub parse_list | ||||||
1457 | { | ||||||
1458 | 15 | 15 | 1 | 30 | my( $self, $list, $entry_string, $join_string, | ||
1459 | $entry_callback, @join_tags ) = _self_or_default @_; | ||||||
1460 | $list = defined $list ? $list | ||||||
1461 | 15 | 100 | 34 | : $self->{ LIST }; | |||
1462 | $entry_string = defined $entry_string ? $entry_string | ||||||
1463 | 15 | 100 | 24 | : $self->{ ENTRY_STRING }; | |||
1464 | $join_string = defined $join_string ? $join_string | ||||||
1465 | 15 | 100 | 19 | : $self->{ JOIN_STRING }; | |||
1466 | $entry_callback = defined $entry_callback ? $entry_callback | ||||||
1467 | 15 | 100 | 25 | : $self->{ ENTRY_CALLBACK }; | |||
1468 | 15 | 16 | my $join_tags; | ||||
1469 | 15 | 100 | 30 | if ( @join_tags > 1 ) { | |||
100 | |||||||
1470 | 2 | 10 | %$join_tags = @join_tags; | ||||
1471 | } elsif ( @join_tags == 1 ) { | ||||||
1472 | 2 | 2 | $join_tags = $join_tags[ 0 ]; | ||||
1473 | } else { | ||||||
1474 | 11 | 16 | $join_tags = $self->{ JOIN_TAGS }; | ||||
1475 | } | ||||||
1476 | |||||||
1477 | # Call the callback for each entry and parse the entry string. | ||||||
1478 | 15 | 21 | my @element_strings = (); | ||||
1479 | 15 | 21 | foreach my $element ( @$list ) { | ||||
1480 | 75 | 143 | my @tags = &$entry_callback( $element ); | ||||
1481 | 75 | 363 | my $string = $self->parse( $entry_string, @tags ); | ||||
1482 | 75 | 192 | push @element_strings, $string; | ||||
1483 | } | ||||||
1484 | |||||||
1485 | # Parse the join string, with join tags (if any) or the default tags. | ||||||
1486 | 15 | 33 | $join_string = $self->parse( $join_string, @join_tags ); | ||||
1487 | |||||||
1488 | # Join it all together and return it. | ||||||
1489 | 15 | 37 | my $string = join $join_string, @element_strings; | ||||
1490 | 15 | 50 | 85 | return @element_strings ? $string : ''; | |||
1491 | } | ||||||
1492 | |||||||
1493 | #------------------------------------------------------------------------------- | ||||||
1494 | |||||||
1495 | =item C |
||||||
1496 | |||||||
1497 | =item or C |
||||||
1498 | |||||||
1499 | =item or C |
||||||
1500 | |||||||
1501 | =item or C |
||||||
1502 | |||||||
1503 | =item or C |
||||||
1504 | |||||||
1505 | Exactly as parse_list(), but using filenames, not strings. | ||||||
1506 | |||||||
1507 | =cut | ||||||
1508 | |||||||
1509 | sub parse_list_files | ||||||
1510 | { | ||||||
1511 | 7 | 7 | 1 | 19 | my( $self, $list, $entry_file, $join_file, $entry_callback, @join_tags ) | ||
1512 | = _self_or_default @_; | ||||||
1513 | $list = defined $list ? $list | ||||||
1514 | 7 | 100 | 19 | : $self->{ LIST }; | |||
1515 | $entry_file = defined $entry_file ? $entry_file | ||||||
1516 | 7 | 100 | 13 | : $self->{ ENTRY_FILE }; | |||
1517 | $join_file = defined $join_file ? $join_file | ||||||
1518 | 7 | 100 | 12 | : $self->{ JOIN_FILE }; | |||
1519 | 7 | 50 | 20 | my $entry_string = defined $entry_file ? _get_file( $entry_file ) | |||
1520 | : ''; | ||||||
1521 | 7 | 50 | 19 | my $join_string = defined $join_file ? _get_file( $join_file ) | |||
1522 | : ''; | ||||||
1523 | |||||||
1524 | 7 | 14 | my @params = ( $list, $entry_string, $join_string ); | ||||
1525 | 7 | 100 | 16 | push @params, $entry_callback if defined $entry_callback; | |||
1526 | 7 | 7 | push @params, @join_tags; | ||||
1527 | 7 | 16 | return $self->parse_list( @params ); | ||||
1528 | } | ||||||
1529 | |||||||
1530 | 1; | ||||||
1531 | |||||||
1532 | #=============================================================================== | ||||||
1533 | # P E R L D O C | ||||||
1534 | #=============================================================================== | ||||||
1535 | |||||||
1536 | __END__ |