| 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__ |