NAME

TX - a simple template system based on Text::Template::Library

SYNOPSIS

 use TX;
 my $T=TX->new( delimiters=>[qw/<% %>/],
                path=>[qw!/path/to/dir1 /path/to/dir2 ...!],
                binmode=>':utf8',             # how to read template files
                cachesize=>$max_cached_templates,
                evalcache=>\%another_hash,
                evalcachesize=>$max_items_in_another_hash,
                export_include=>0,            # default is 1
                auto_reload_templates=>1,     # default is 0
                prepend=>'use warnings',      # default not set
                output=>sub {...},            # default undef
                package=>'My::Dummy',         # default TX::__
                );

 $T->include( 'template1', key=>'value', ...);
 $T->include( 'template1', {OUTPUT=>'', ...}, key=>'value', ...);

or

 use TX qw/include/;

 @ENV{qw/TEMPLATE_PATH TEMPLATE_BINMODE
         TEMPLATE_DELIMITERS TEMPLATE_EVALCACHE/}=
   ('/path/to/dir1:/path/to/dir2', ':utf8', "<%\t%>", 1);

 include( 'template1', {OUTPUT=>'', ...}, key=>'value', ...);

template1.tmpl may contain:

 <% define mymacro %>
 ...
 <% /define %>

 call macro defined in the same template:
   <% include '#mymacro', key=>'value', ... %>

 call macro defined somewhere else:
   <% include 'library#libmacro1', key=>'value', ... %>

library.tmpl may contain:

 <% define libmacro1 %>
 ...
 <% /define %>

 <% define libmacro2 %>
 ...
 <% /define %>

DESCRIPTION

Text::Template::Base and Text::Template::Library are good at processing single templates. They lack the ability to manage sets of template files. This module adds that functionality in a (what I think) user friendly manner.

The most important function of this module is include. It actually processes the template. include can be called in 2 ways, as simple subroutine or as object method. The second way introduces much more features and hence should be prefered. If called as simple subroutine an internal object is created and and initialized from environment variables.

The object oriented interface

All keys passed to the constructor new are also usable as accessor methods, e.g. $object->output=sub {...};. They methods can be used as Lvalues.

TX->new(key=>value, ...)

creates a TX object. Options are passed as key, value pairs.

$object->include($template, \%options, key=>value, ...)

This method processes the template $template. The template may be given as a filename or the basename of a filename (filename without extension) or as a hash reference.

In the former case the template is looked up in the template search path unless it is already present in the template cache.

If a hash is passed in as template it is expected to have at least the following entries, template - the template string (that would be otherwise read from the template file) and filename - a name under which the template can be cached. Make sure to use file names that may not occur in your operating system, e.g. names starting with a \0 character.

Data is passed to the template as key, value pairs after the optional \%options parameter. These parameters are collected into a hash and made accessible inside the template as %V. So, a value passed by a certain KEY is accessed from the template as $V{KEY}.

Further, the 2 hashes %L and %G are available to pass data around. %G is a global hash in a certain meaning. Normally, it is initialized as an empty hash by the outermost include call, the one that is invoked from your perl program in contrast to invocations from within templates. All templates and template modules share the same %G. When the outermost include call is done it is accessible as %{$object->G}. So if you carry around large data structures, open filehandles or similar that may cause undesireable side effects consider to undef it after the call:

 $template->include(...);
 undef $template->G;            # G is an lvalue function

As said before %G is normally initialized as an empty hash. But suppose there is a set of templates that somehow belong together and want to carry around data between toplevel calls. %G is not usable in this case. But if the preserve_G object property is set and $template->G is set to a hash reference before the outermost call %G will not be reset as in:

 $template->G=\my %G;
 $G{'meaning of life'}=42;
 $template->preserve_G=1;
 $template->include(...);
 # $G{'meaning of life'} is still 42 if not
 # overwritten by the template

This way it can be used to pass data in and out of a template and to carry data around between toplevel include calls.

%L is sort of local. Each time include is called a new %L hash is created. For example:

 [% define m1 %]
   G=[% ++$G{g} %] L=[% ++$L{l} %]
 [% /define %]

 [% $G{g}=10; $L{l}=10; '' #init some hash members %]

 [% ++$G{g}         # will output 11 %]
 [% ++$L{l}         # will output 11 %]
 [% include '#m1'   # will output G=12 L=1 (a localized %L is used) %]
 [% ++$G{g}         # will output 13 %]
 [% ++$L{l}         # will output 12 %]

Code fragments are evaluated with use strict in effect. The 3 hashes %V, %G and %L are declared with the our keyword.

The optional \%options hash reference is used to modify the current include operation. You can

In case of an error include throws an exception. If the error occures in a template the template file name and line number are given along with the error message. If a template throws an error object or any other reference it is propagated unchanged.

$object->G

returns \%G after a call to include.

$object->clear_cache
$object->clear_cache($string_or_regexp, $delete)
$object->clear_cache($string)

Clears the template cache. If called without parameters the whole cache is cleared.

If 2 parameters are given the first is interpreted as regexp. It may be a string containing a regexp or a Regexp object (the result of a qr/.../). If the second parameter is true all matching cache elements are dropped otherwise all non-matching. That means in the latter case matching cache elements are preserved.

If only one parameter is given and it is a Regexp object all non-matching cache elements are dropped.

If only one parameter is given and it is a string the first character of the string value decides if the matching or non-matching cache elements are to be removed. If it is a exclamation mark (!) it is deleted from the string. Then the string is interpreted as regular expression and all matching cache elements are dropped. Otherwise the whole string (including the first character) is interpreted as regular expression and all non-matching cache elements are dropped.

Functional Interface

If include is called without the first parameter being a TX object or subclassed object of TX the default object $TX::TX is used. $TX::TX is initialized at the first call according to the environment variables as explained above.

SUBCLASSING

TX is internally represented a an array. The first few elements are used to hold its properties. @TX::attributes holds a list of property names. If a subclass wants to add new properties it must not override the existing ones. So, new attributes can be added this way:

  package My::TX;

  use strict;
  use warnings;

  use TX;
  @My::TX::ISA=qw/TX/;

  our @attributes;
  BEGIN {
    # define attributes and implement accessor methods
    @attributes=(TX::attributes(), qw/p1 p2 _p3/);
    for( my $i=TX::attributes(); $i<@attributes; $i++ ) {
      my $method_num=$i;
      ## no critic
      no strict 'refs';
      *{__PACKAGE__.'::'.$attributes[$method_num]}=
        sub : lvalue {$_[0]->[$method_num]};
      ## use critic
    }
  }
  sub attributes {@attributes}

Now, if a user calls My::TX->new(p1=>..., _p3=>...) the inherited constructor initializes $self->p1 but prints a warning for _p3. _p3 begins with an underline and hence is treated as private. _p3 will not be assinged.

Optionally you can also define an init() method to initialize private data and process left over parameters:

  package My::TX;
  sub {
    my ($I, %param)=@_;
    $I->_p3=some_processing(delete $param{p3});
    return $I->SUPER::init(%param);
  }

or slightly more effective:

  package My::TX;
  sub {
    my ($I, %param)=@_;
    $I->_p3=some_processing(delete $param{p3});
    @_=($I, %param);
    goto \&TX::init;
  }

The init() method must delete the parameters it knows about from @_ and return the rest. So, this is also valid:

  package My::TX;
  sub {
    my ($I, %param)=@_;
    $I->SUPER::init;
    $I->_p3=some_processing(delete $param{p3});
    return %param;
  }

Note, you must call TX::init at some point.

SEE ALSO

Text::Template::Base, Text::Template::Library

AUTHOR

Torsten Foertsch, <torsten.foertsch@gmx.net<gt>

COPYRIGHT AND LICENSE

Copyright (C) 2008-2009 by Torsten Foertsch

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.