NAME
PAB3 - Perl Application Builder / Version 3
SYNOPSIS
use PAB3;
DESCRIPTION
PAB3
provides a framework for building rapid applications in Perl5. It also includes a template handler for producing output. This part is defined here.
Examples
Following example loads a template from template1.tpx, does a loop over the %ENV variable and prints the output on STDOUT.
-------------------------------------------------------------------
test1.pl
-------------------------------------------------------------------
#!/usr/bin/perl -w
use PAB3;
my $pab = PAB3->new();
$pab->make_script_and_run( 'template1.tpx' );
-------------------------------------------------------------------
template1.tpx
-------------------------------------------------------------------
main script:
<*= $0 *>
environment:
<* LOOP HASH %ENV *>
<* PRINT "[$_] => " . $ENV{$_} . "\n" *>
<* END LOOP *>
# or - unregistered
<* loop foreach( keys %ENV ) *>
<* = "[$_] => " . $ENV{$_} . "\n" *>
<* end loop *>
# or - perl like
<* foreach( keys %ENV ) { *>
<* print "[$_] => " . $ENV{$_} . "\n" *>
<* } *>
METHODS
- setenv ()
-
Set some useful variables to the interpreters environment
the variables are:
$ENV{'SCRIPT_PATH'} : path to the main script $ENV{'SCRIPT'} : name of the main script
- new ( [%arg] )
-
Create a new instance of the PAB3 (template handler) class.
Posible arguments are:
path_cache => path to save parsed templates path_template => path to the template files auto_cache => create cache files automatically. 'path_cache' is required prg_start => begin of program sequence, default is '<*' prg_end => end of program sequence, default is '*>' cmd_sep => command separator, to define more directives in one program sequence, default is ';;' record_name => name of default record in loops, default is '$_' logger => reference to a PAB3::Logger class warn => warn on error, default is OFF die => die on error, default is ON class_name => name of the variable for this class. eg '$pab' It is needed when templates including templates. If its undefined, a variable $PAB3::_CURRENT will be used as a reference to the current PAB3 class.
Example:
$pab = PAB3->new( 'path_cache' => '/path/to/cache', 'path_template' => '/path/to/template-files', );
- parse_template ( $template )
-
Parse the template given at $template and return Perl code. If $template points to an existing file, the content of the file will be parsed. In the other case the content of the variable will be used as template.
Example:
$code = $pab->parse_template( '<*= $0 *>' ); eval( $code );
- make_script_and_run ( $template )
- make_script_and_run ( $template, $cache )
- make_script_and_run ( $template, $cache, $package )
-
Parse the template given at $template, generate Perl code and execute it. If $cache is set to a filename or "auto_cache" is enabled, the Perl code will be saved into a file. If the cache file already exists and the template has not been changed, the template will not be parsed again. Third parameter $package defines the package where the Perl code should be executed. If $package has not been specified the package from
caller(0)
is used.Returns TRUE on success or FALSE on error.
Example:
# parse the template and execute it $pab->make_script_and_run( 'template.htm' ); # parse the template, cache it into file and execute it $pab->make_script_and_run( 'template.htm', 'template.pl' );
- register_loop ( $id, $source, $s_type )
- register_loop ( $id, $source, $s_type, $record, $r_type )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object, $arg )
- register_loop ( $id, $source, $s_type, $record, $r_type, $object, $arg, $fixed )
-
Registers a loop to be used inside templates.
Loops need not registered here. It also can be declared in the template.
Arguments
$id
Loop identifier
$source
the source of the loop.
$s_type
the type of the source. One of these constants: PAB_ARRAY, PAB_HASH or PAB_FUNC
$record
the record in the loop.
$r_type
the type of the record. One of these constants: PAB_SCALAR, PAB_FUNC, PAB_ARRAY or PAB_HASH
$object
a object for $source or $record functions.
$arg
arguments passed to the source if it is a function, as an array reference
$fixed
installes the loop as fixed. it can not be overwritten
Combinations
Following combinations are possible:
-------------------------------------- | Source | Record | Object | -------------------------------------- | PAB_ARRAY | PAB_SCALAR | - | | PAB_ARRAY | PAB_FUNC | yes | | PAB_HASH | PAB_SCALAR | - | | PAB_HASH | PAB_FUNC | yes | | PAB_FUNC | PAB_SCALAR | yes | | PAB_FUNC | PAB_ARRAY | yes | | PAB_FUNC | PAB_HASH | yes | --------------------------------------
The constants can be accessed in three ways, by the object like $pab->SCALAR, by the module like PAB3::SCALAR and by export like PAB_SCALAR. See more at EXPORTS
Source as Array, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_SCALAR ) # result foreach $record( @source ) { }
Source as Array, Record as Function
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_FUNC ) # result foreach $<iv>( @source ) { &record( $<iv> [, <arg>] ); }
Source as Array, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_ARRAY, 'record' => PAB_FUNC, 'object' ) # result foreach $<iv>( @source ) { $object->record( $<iv> [, <arg>] ); }
Source as Hash, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_SCALAR ) # result foreach $record( keys %source ) { }
Source as Hash, Record as Function
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_FUNC ) # result foreach $<iv>( keys %source ) { &record( $<iv> [, <arg>] ); }
Source as Hash, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_HASH, 'record' => PAB_FUNC, 'object' ) # result foreach $<iv>( keys %source ) { $object->record( $<iv> [, <arg>] ); }
Source as Function, Record as Scalar
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_SCALAR ) # result while( $record = &source( [<arg>] ) ) { }
Source as Function, Record as Scalar, Object
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_SCALAR, 'object' ) # result while( $record = $object->source( [<arg>] ) ) { }
Source as Function, Record as Array
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_ARRAY ) # result while( @record = &source( [<arg>] ) ) { }
Source as Function, Record as Hash
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_HASH ) # result while( %record = &source( [<arg>] ) ) { }
Source as Function, Record as Function
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_FUNC ) # result while( $<iv> = &source( [<arg>] ) ) { &record( $<iv> [, <arg>] ); }
Source as Function, Record as Function, Object
# definition register_loop( 'id', 'source' => PAB_FUNC, 'record' => PAB_FUNC, 'object' ) # result while( $<iv> = $object->source( [<arg>] ) ) { $object->record( $<iv> [, <arg>] ); }
Examples
Example of a loop over an array with record as subroutine:
use PAB3 qw(:const); my @Array1 = ( 1, 2, 3 ); $pab->register_loop( 'MYLOOP', 'Array1' => PAB_ARRAY , 'init_record' => PAB_FUNC ); sub init_record { $Record = shift; ... }
Example of an enumeration loop:
$pab->register_loop( 'MYLOOP', 'enum' => PAB_FUNC, 'Record' => PAB_SCALAR ); $Counter = 10; sub enum { if( $Counter == 0 ) { $Counter = 10; return 0; } return $Counter --; }
--- inside the template ---
<* LOOP MYLOOP *> <* PRINT $Record . "\n" *> <* END LOOP *>
See also
- add_hashmap ( $loop_id, $hashname, $fieldmap )
- add_hashmap ( $loop_id, $hashname, $fieldmap, $hm_save )
-
Add a hashmap to the parser. Hashmaps are designed to translate hashes in templates into arrays in the parsed script. For example: you use $var->{'Key'} in your template. With a hashmap you can convert it into an array like $var->[0] without taking care of the indices. This can noticable make the execution time faster.
Parameters
$loop_id
If it is defined only the program sequences inside the loop will be converted, otherwise the complete template is will be converted.
$hashname
Specifies the name of the hash to be translated.
$fieldmap
Can be a reference to an array of fieldnames or a reference to a hash containing fieldnames as keys and the assiocated indices as values.
$hm_save
If $fieldmap is an arrayref, the new generated hashmap can be saved in this parameter.
Return Values
Returns TRUE on success or FALSE if it fails.
Example
@data = ( [ 'Smith', 'John', 33 ], [ 'Thomson', 'Peggy', 45 ], [ 'Johanson', 'Gustav', 27 ], ); @fields = ( 'Name', 'Prename', 'Age' ); # map all $per items in loop "Person" from hash to array $pab->add_hashmap( 'Person', 'per', \@fields ); $pab->make_script_and_run( 'template' );
--- template ---
<* LOOP Person foreach $per(@data) *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP *>
Warning
If an empty result from a db query is returned, no hashmap can be created. If your template needs to be compiled and uses hashmaps, which are empty, you will get an error. You should recompile affected templates once by running them with valid hashmaps. Or you can use a hashmap cache handler. See more at PAB3::HashmapCache.
- reset ()
-
Clears loop definitions and hashmaps in the PAB3 class.
- require ( $filename )
-
Loads the required file and compiles it into a package and runs it once it has been changed.
Example:
&PAB3::require( 'config.inc.pl' ); - or - $pab->require( 'foo.pl' );
- require_and_run ( $filename )
-
Loads the required file and compiles it into a package once it has been changed. Runs it on every call.
Example:
&PAB3::require_and_run( 'dosomething.pl' ); - or - $pab->require_and_run( 'foo.pl' );
PAB3 TEMPLATE LANGUAGE SYNTAX
The little extended language is needed to extract the PAB3 and Perl elements from the rest of the template. By default program sequences are included in <* ... *> and directives are separated by ;; . These parameters can be overwritten by new().
Examples
<p><* PRINT localtime *></p>
<*
my $pos = int( rand( 3 ) );;
my @text =
(
'I wish you a nice day.',
'Was happy to see you.',
'Would be nice to see you back.'
)
*>
<* if $pos == 0 *>
<p>I wish you a nice day.</p>
<* elsif $pos == 1 *>
<p>Was happy to see you.</p>
<* else *>
<p>Would be nice to see you back.</p>
<* end if *>
<!-- or shortly -->
<p><* = $text[$pos] *></p>
Directives
The following list explains the directives available within the PAB3 template system. All directives are case insensitive. The description is using the default program and command separators.
- PRINT <expression>
- = <expression>
-
Prints the output returned from <expression>.
<* PRINT <expression> *>
or shortly
<* = <expression> *>
Example:
<* print $0, "\n" *> <* PRINT 'Now: ' . time . "\n" *> <* = 'Or formated: ' . &PAB3::Utils::strftime( '%c', time ) *>
Performance info Combining multiple expressions into one string can speed up the print process. For example:
faster: <* print $x . ' some data: ' . $str *> slower: <* print $x, ' some data: ', $str *>
Joining several PRINT directives into one directive does not realy affect to the speed, because the optimizer will do it automatically.
- : <expression>
- <expression>
-
Executes <expression> wihout printing the output. This is also the default action if no directive has been specified.
<* : <expression> *>
or
<* <expression> *>
Example:
<* : $my_var = 1 *> <* : &my_sub( $my_var ) *> <* $x = $y *>
- IF <condition>
- ELSIF <condition>
- ELSE
- END IF
-
Enclosed block is processed if the <condition> is true.
<* IF <condition> *> ... <* ELSIF <condition> *> ... <* ELSE *> ... <* END IF *>
- INCLUDE <template>
-
Process another template file. Please note the "class_name" at new().
<* INCLUDE <expression> *>
Example:
<* include banner.tpl *> - or - <* $banner = int( rand( 3 ) ) + 1 *> <* include banner${banner}.tpl *>
- LOOP
- LOOP <id>
- LOOP <id> <exp1>
- LOOP <id> <exp1> <exp2>
- LOOP <exp1>
- END LOOP
-
Performs a predefined loop, a loop registered by register_loop or an unregistered loop. Predefined loops are ARRAY and HASH. These are using <exp1> as source and <exp2> as record. In registered loops <exp1> optionally can be used as record and <exp2> as an argument. Unregistered loops can be used with or without <id>. The loop must be defined in <exp1> without brackets. The difference between registered and unregistered loops is that registered loops are defined in the perl script and unregistered loops are defined in the template.
<* LOOP <id> [<exp1> [<exp2>]] *> ... <* END LOOP *>
Example of an ARRAY loop
<* LOOP ARRAY @INC $_ *> <* PRINT $_ . "\n" *> <* END LOOP *>
Example of a HASH loop
<* LOOP HASH %ENV $_ *> <* PRINT $_ . ' = ' . $ENV{$_} . "\n" *> <* END LOOP *>
Example of a registered loop
--- perl script ---
use PAB3 qw(:const); $pab = PAB3->new( ... ); @data = ( [ 'Smith', 'John', 33 ], [ 'Thomson', 'Peggy', 45 ], [ 'Johanson', 'Gustav', 27 ], ); $pab->register_loop( 'PERSON', 'data' => PAB_ARRAY, 'per' => PAB_HASH ); $pab->make_script_and_run( 'template' );
--- template ---
<* LOOP PERSON *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP PERSON *>
Example of a registered loop with hashmap
--- perl script ---
use PAB3 qw(:const); $pab = PAB3->new( ... ); @data = ( [ 'Smith', 'John', 33 ], [ 'Thomson', 'Peggy', 45 ], [ 'Johanson', 'Gustav', 27 ], ); @fields = ( 'Name', 'Prename', 'Age' ); $pab->register_loop( 'PERSON', 'data' => PAB_ARRAY, 'per' => PAB_ARRAY ); $pab->add_hashmap( 'Person', 'per', \@fields ); $pab->make_script_and_run( 'template' );
--- template ---
<* LOOP PERSON *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP PERSON *>
Example of unregistered loops
--- perl script ---
use PAB3 qw(:const); $pab = PAB3->new( ... ); @data = ( [ 'Smith', 'John', 33 ], [ 'Thomson', 'Peggy', 45 ], [ 'Johanson', 'Gustav', 27 ], ); @fields = ( 'Name', 'Prename', 'Age' ); $pab->add_hashmap( 'PersonMapped', 'per', \@fields ); $pab->make_script_and_run( 'template' );
--- template ---
# without id <* LOOP foreach $per( @data ) *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP *> # with id <* LOOP Person foreach $per( @data ) *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP Person *> # with hashmap <* LOOP PersonMapped foreach $per (@data) *> <* = $per->{'Prename'} . ' ' . $per->{'Name'} *> is <* = $per->{'Age'} *> years old <* END LOOP *>
See also register_loop(), add_hashmap()
- SUB <expression>
- END SUB
-
Defines a subroutine in the style
local <expression> = sub { ... };
.<* SUB <expression> *> ... <* END SUB *>
Example:
<* SUB *action *> <* PRINT $ENV{'SCRIPT'} . '?do=' . ( $_[0] || '' ) *> <* END SUB *> <a href="<* &action( 'open' ) *>">Open</a>
- COMMENTS
-
Comments are copied.
<* #... *>
Example:
# comment out directives. <* #print $foo *>
- !X <directive>
-
This special directive prints the content in <directive> as a new directive. It can be useful to generate templates from templates.
<* !X <directive> *>
Example:
<* $foo = '$bar' *> <* !X print $foo *> produces: <* print $bar *> <* !X print \$foo *> produces: <* print $foo *>
EXPORTS
By default nothing is exported. To export constants like PAB_SCALAR etc use the export tag ":const"
AUTHORS
Christian Mueller <christian_at_hbr1.com>
COPYRIGHT
The PAB3 module is free software. You may distribute under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.