The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

CGI::Builder::Magic - CGI::Builder and Template::Magic integration

VERSION 1.31

The latest versions changes are reported in the Changes file in this distribution. To have the complete list of all the extensions of the CBF, see "Extensions List" in CGI::Builder

INSTALLATION

Prerequisites
    CGI::Builder    >= 1.31
    Template::Magic >= 1.36
CPAN
    perl -MCPAN -e 'install CGI::Builder::Magic'

You have also the possibility to use the Bundle to install all the extensions and prerequisites of the CBF in just one step. Please, notice that the Bundle will install A LOT of modules that you might not need, so use it specially if you want to extensively try the CBF.

    perl -MCPAN -e 'install Bundle::CGI::Builder::Complete'
Standard installation

From the directory where this file is located, type:

    perl Makefile.PL
    make
    make test
    make install

SYNOPSIS

    # just include it in your build
    
    use CGI::Builder
    qw| CGI::Builder::Magic
      |;

DESCRIPTION

Note: You should know CGI::Builder.

This module transparently integrates CGI::Builder and Template::Magic in a very handy, powerful and flexible framework that can save you a lot of coding, time and resources.

With this module, you don't need to produce the page_content within your page handlers anymore (unless you want to); you don't even need to manage a template system yourself (unless you want to).

If you use any template system on your own (i.e. not integrated in a CBF extension), you will have to write all this code explicitly:

  • create a page handler for each page as usual

  • create a new template object and assign a new template file

  • find the runtime values and assign them to the template object

  • run the template process and set the page_content to the produced output

You can save all that by just including this module in your build, because it implements an internal transparent and automagic template system that even without your explicit intervention is capable of finding the correct template and the correct runtime values to fill it, and generates the page_content automagically. With this module you can even eliminate the page handlers that are just setting the page_content, because the page is auto-magically sent by the template system.

How to organize your CBB

Add these steps to the recommendations in "Design your application" in CGI::Builder:

  1. Prepare a template for each page addressed by your application or prepare a Page Handler for those which will not have a template

  2. Define just the page handlers that needs to do something special

  3. Set the variables or the subs in the *::Lookups package that the internal Template::Magic object will look up (that could be picked up by one or more templates processing)

The Template System

This module uses Template::Magic specially for these advantages:

  • Template::Magic is a module that can auto-magically look up the runtime values in packages, hashes and blessed objects

  • It has the simplest possible template syntax (idiot-proof), and it is written in pure perl (no compiler needed), so it is perfect to be used by (commercial) user-customizable CGI applications.

  • It uses minimum memory because it prints the output while it is produced, avoiding to collect in memory the whole (and sometime huge) content.

The integration with Template::Magic allows you to move all the output-related stuff out of the page handlers, producing a cleaner and easiest to maintain CBB.

Note: All the CBF extensions are fully mod_perl 1 and 2 compatible (i.e. you can use them under both CGI and mod_perl). Anyway, an extremely powerful combination with this extension is the Apache::CGI::Builder, that can easily implement a sort of Perl Side Include (sort of easier, more powerful and flexible "Server Side Include").

How it works

This module implements a default value for the page_content property: a CODE reference that produces and print the page content by using an internal Template::Magic object with HTML syntax.

The default template file used to produce the output is the result of the concatenation (File::Spec->catfile) of the page_path, page_name and page_suffix properties, but you can set it otherwise if you want to use a different template file.

Since the page_content property is set to its own default value before the page handler is called, the page handler can completely (and usually should) avoid to produce any output.

    sub PH_myPage
    {
      ... do_something_useful ...
      ... no_need_to_set_page_content ...
      ... returned_value_will_be_ignored ...
    }

Since the CBF calls the Page Handler related with the page_name, without expecting any returned value from it, an ideal organized Magic application uses the Page Handlers only if the application has something special to do for any particular page. The output production is usually handled auto-magically by the template system.

The output will be generated internally by the merger of the template file and the runtime values that are looked up from the FooBar::Lookup package ('FooBar' is not literal, but stands for your application namespace plus the '::Lookups' string).

In simplest cases you can also avoid to create the page handler for certain pages: by default the template with the same page name will be used to produce the output.

This does not mean that you cannot do things otherwise when you need to. Just create a page handler and set there all the properties that you want to override:

   sub PH_mySpecialPage
   {
     my $s = shift ;
     $s->tm_lookups = { special_key => 'that' } ;
     $s->tm_template = '/that/special/template' ;
   }

Since the page handler sets the tm_lookups and the tm_template properties, the application will add your hash to the usual lookup, and the template system will print with a specific template and not with the default 'mySpecialPage.html'.

If some page handler needs to produce the output on its own (completely bypassing the template system) it can do so by setting the page_content property as usual (i.e. with the page content or with a reference to it)

   sub PH_mySpecialPage
   {
     my $s = shift ;
      ... do_something_useful ...
     # will bypass the template system
     $s->page_content  = 'something';
     $s->page_content .= 'something more';
   }

For the 'mySpecialPage' page, the application will not use the template system at all, because the page_content property was set to the output.

Note: For former CGI::Application users: the returned value of any page handler will be ALWAYS ignored, so set explicitly the page_content property when needed (or ignore it if you want to use the template system).

Lookups

Lookups are 'code locations' where the Template::Magic system will search the runtime values to substitute the labels in your template. (See "lookups" in Template::Magic for details)

Special Labels

This module automatically adds to the Template::Magic object some useful lookups which make available several ready to use labels inside your templates. You don't need to write any code in your CBB in order to use these labels:

  • all the page_error keys

    If your CBB or some other extensions (like the CGI::Builder::DFVCheck) set some page_error key value pair, they will be available as labels in your template:

        $s->page_error( err_email => 'The email field is not valid' );

    in your template you can use:

        <!--{err_email}-->

    that will be substituted with 'The email field is not valid'.

  • the FillInForm block label

    The special block label 'FillInForm' is very useful to redisplay a HTML form that has some input error and re-filling all the fields with the values that the user has just submitted.

    In order to do so, you have just to use it inside your template by making a block that surrounds the HTML form:

        <!--{FillInForm}-->
        <form action="tank_you_page" method="get">
        Name: <input name="name" type="text" value=""><br>
        Email: <input name="email" type="text" value=""><br>
        <input type="submit" name="submit" value="Submit">
        </form>
        <!--{/FillInForm}-->
  • the CGISESSID label

    When you include in your CBB the CGI::Builder::Session extension, you will have magically available a label that will be substituted with the current session id. The label identifier is the same name contained in the $CGI::Session::NAME variable which is usually 'CGISESSID', unless you have set it otherwise.

       <!--{CGISESSID}-->

    E.g.: You can use it to set the value of an hidden field in your forms.

    Note: The simple use of this label in a template might internally create a CGI::Session object (cs property) thus eventually generating a new session on its own if no session object has been used in your CBB yet.

*::Lookups package

This is a special package that your application should define to allow the internal Template::Magic object to auto-magically look up the run time values you want to define.

The name of this package is contained in the "tm_lookups_package" class property. The default value for this property is 'FooBar::Lookup' where 'FooBar' is not literal, but stands for your CBB namespace plus the '::Lookups' string, so if you define a CBB package as 'WebApp' you should define a 'WebApp::Lookups' package too (or set the tm_lookup_package property with the name of the package you will use as the lookup).

In this package you should define all the variables and subs needed to supply any runtime value that will be substituted in place of the matching label or block in any template.

The lookup is confined to the *::Lookups package on purpose. It would be simpler to use the same CBB package, but this would extend the lookup to all the properties, methods and handlers of your CBB and this might cause conflict and security holes. So, by just adding one line to your CBB, (e.g. 'package FooBar::Lookups;') you can separate your CBB from the lookup-allowed part of it.

Note: If for any reason you need to use more than one *::Lookup package, you can set the tm_lookups_package to a reference to an ARRAY of packages names. Obviously you can also put each lookups package in its own '.pm' file, thus making them simply loadable from different CBBs.

*::Lookups subs

The subs in the *::Lookups package(s) are executed by the template lookup whenever a label with the same identifier is found. They receive your application object ($self) in $_[0], so even if they are defined in a different package, they are just like the other methods in your CBB class.

The subs will receive the Template::Magic::Zone object as $_[1], so you can interact with the zone as usual (see Template::Magic)

Important Note: Usually a sub in any *::Lookups package is an ending point and should not need to call any other subs in the same *::Lookups package. If you feel the need to do otherwise, you probably should re-read Template::Magic because you are trying to do something that Template::Magic is already doing auto-magically. Anyway, if you found some esoteric situation that I never thinked about, you can do *::Lookups subs callable from the same package by just making your CBB package a subclass of *::Lookups package by adding a simple push our @ISA, 'FooBar::Lookups'; statement in it.

How to add lookup locations

If you want the Template::Magic object to look up in some more location, e.g. if you want the object to loookup in the param hash and in %ENV, you can choose beetween a couple of solutions: if your need is temporary (i.e. just for some specific Page Handler) you can use the tm_lookups property or if your need is application-wide (i.e. for all the pages) you can use the tm_new_args class group property.

This is the first option which will add the lookups only for the 'some_special_page':

    sub PH_some_special_page {
        $s->tm_lookups = [ scalar $s->param ,      # param hash ref
                           \%ENV  ] ;              # %ENV ref
    }

This is the second option, which will add the lookups for all the pages processed by the template system:

    __PACKAGE__->tm_new_args
      ( lookups => [ scalar $s->param ,      # param hash ref
                     \%ENV  ]);              # %ENV ref

Note: The first option uses the temporary lookups capability of Template::Magic, while the second one uses the constructor array lookups. They have almost the same effect on the single output, but the first is cleared after each template process, while the second is stored into the object itself (thus used for all the successive template process). See Template::Magic for more details.

Warning: The tm_new_args() accessor is a class accessor, and is used ONLY when a new Template::Magic object is about to be created. This means that if you write something like this:

    sub PH_some_special_page {
        __PACKAGE__->tm_new_args
          ( lookups => [ scalar $s->param ,      # param hash ref
                         \%ENV  ]);              # %ENV ref
    }

Probably the effect will not be what you might espect. More specifically, if the tm object has been used before the 'some_special_page' has been requested, the statement has simply no effect, since the tm object is already created and stored. If the tm object has not been used before the 'some_special_page' has been requested, then the statement will have its effect but the object will contain the lookup locations for all the successive requests.

The template syntax

This module implements a Template::Magic::HTML object, so the used markers are the default HTML markers e.g.:

    <!--{a_block_label}--> content <!--{/a_block_label}-->

and the value handlers are the default HTML handler, so including TableTiler and FillInForm handlers by default. Please, read Template::Magic and Template::Magic::HTML.

Example

    package WebApp ;
    use CGI::Builder
    qw| CGI::Builder::Magic
      | ;
    
    # no need to setup page handlers to set the page_content
    # just setup the package where Template::Magic will looks up
    # the run time valuess
    
    package WebApp::Lookups ;
    
    # this value will be substituted to each
    # 'app_name' label in EACH TEMPLATE that include it
    our $app_name = 'WebApp 1.0' ;
    
    # same for each 'Time' label
    sub Time { scalar localtime }
    
    # and same for each 'ENV_table' block
    sub ENV_table {
        my ($self,        # $self is your WebApp object
            $zone) = @_ ; # $zone is the Template::Magic::Zone object
        my @table ;
        while (my @line = each %ENV) {
          push @table, \@line
        }
        \@table ;
    }

An auto-magically used template (it contains the 'ENV_table block', and the 'app_name' and 'Time' labels)

    <html>
    
    <head>
    <meta http-equiv=content-type content="text/html;charset=iso-8859-1">
    <title>ENVIRONMENT</title>
    <style media=screen type=text/css><!--
    td   { font-size: 9pt; font-family: Arial }
    --></style>
    </head>
    
    <body bgcolor=#ffffff>
    <table border=0 cellpadding=3 cellspacing=1 width=100%>
    <tr><td bgcolor=#666699 nowrap colspan=2><font size=3 color=white><b>ENVIRONMENT</b></font></td></tr>
    <!--{ENV_table}-->
    <tr valign=top>
    <td bgcolor=#d0d0ff nowrap><b>the key goes here</b></td>
    <td bgcolor=#e6e6fa width=100%>the value goes here</td>
    </tr>
    <!--{/ENV_table}-->
    </table>
    Generated by <!--{app_name}--> - <!--{Time}-->
    </body>
    
    </html>

SPECIAL INTEGRATIONS

This extension will add some special features to your CBB when some specific extension is included.

Apache::CGI::Builder (Perl Side Include)

SSI (Server Side Includes) are directives that are placed in HTML pages, and evaluated on the server while the pages are being served. The Apache server uses the mod_include Apache module to process the pages, but you can configure it to process the pages by using your own CBB, that can easily implement a lot of more custom 'directives' in the form of simple labels.

In other words: your own CBB transparently process the pages of a web dir, supplying the dinamic content that will be included in the page just before they are served.

With this technique your application does not need to handle neither page names, nor page handlers, nor template managements: all that is auto-magically handled by the combination of Apache::CGI::Builder and CGI::Builder::Magic extensions.

Please, take a look at the 'perl_side_include' example in this distribution to understand all the advantages offered by this technique.

CGI::Builder::Session

When you include in your CBB the CGI::Builder::Session extension, you will have magically available a label that will be substituted with the current session id. See the CGISESSID label for details.

CGI::Builder::DFVCheck

The CGI::Builder::DFVCheck extension sets the CBF page_error property with the errors found in your forms. CGI::Builder::Magic adds that property to its lookups, so each error found will have its own label defined. See " CGI::Builder::DFVCheck" for more details.

PROPERTY and GROUP ACCESSORS

This module adds some template properties (all those prefixed with 'tm_') to the standard CBF properties. The default of these properties are usually smart enough to do the right job for you, but you can fine-tune the behaviour of your CBB by setting them to the value you need.

tm_lookups

This property allows you to access and set the 'lookups' argument passed to the Template::Magic::nprint() method (see "nprint ( arguments )" in Template::Magic). It is undefined by default.

tm_template

This property allows you to access and set the 'template' argument passed to the Template::Magic::nprint() method (see "nprint ( arguments )" in Template::Magic). Its default is the concatenation (File::Spec->catfile) of the page_path, page_name and page_suffix properties, but you can set it otherwise if you want to use a different template file.

tm_container_template

This property allows you to access and set the 'container_template' argument passed to the Template::Magic::nprint() method (see "nprint ( arguments )" in Template::Magic).

CBF changed property defaults

CBF page_suffix

This module sets the default of the page_suffix to '.html'. If this extension is used under Apache::CGI::Application the page_suffix will be set to the real file name suffix. (see Apache::CGI::Builder)

You can override it by just setting another suffix of your choice.

CBF page_content

This module sets the default of the page_content to a CODE reference that produces the page content by using an internal Template::Magic object with HTML syntax (see also "How it works"). If you want to bypass the template system in any Page Handler, just explicitly set the page_content to the content you want to send.

ADVANCED FEATURES

In this section you can find all the most advanced or less used features that document all the details of this module. In most cases you don't need to use them, anyway, knowing them will not hurt.

Class Accessors

This extension implements a Template::Magic system that is "persistent" under mod_perl (no persistency is available under normal CGI environment).

The persistency is implemented by storing the object (and the other variables that concur to its creation) in package variables, which are persistent under mod_perl. (see also "Global Varibales Persistence" in CGI::Builder)

This technique allows to save some processing time by creating the Template::Magic object just once -the first time it is accessed- and using the same object for all the successive requests that involve template processing.

The package variables used for the template system are accessed by the following OOTools class accessors:

tm

This class property returns the internal Template::Magic object.

This is not intended to be used to generate the page output - which is automagically generated - but it could be useful to generate other outputs (e.g. messages for sendmail) by using the same template object, thus preserving the same arguments.

   # way to access the tm_object
   $tm_obj = __PACKAGE__->tm ;
   $tm_obj = My::CBB->tm ;
   $tm_obj = $s->tm ;

Note: You can change the default arguments of the object by using the tm_new_args property group, or you can completely override the creation of the internal object by overriding the tm_new() method.

tm_new_args( arguments )

This class group accessor handles the Template::Magic constructor arguments that are used in the creation of the internal Template::Magic object. Use it to add some more lookups your application might need, or finetune the behaviour if you know what you are doing (see "How to add lookup locations" and "new ( [constructor_arrays] )" in Template::Magic).

   __PACKAGE__->tm_new_args(...) ;

Note: You can completely override the creation of the internal object by overriding the tm_new() method.

tm_lookups_package

This class property allows you to access and set the name of the package where the Template::Magic object will look up by default. The default value for this property is'FooBar::Lookup' where 'FooBar' is not literal, but stands for your application namespace plus the '::Lookups' string. (i.e. 'WebApp::Lookup').

   __PACKAGE__->tm_lookups_package('My::Special::Lookups') ;

If you need to use more than one *::Lookups package, you can also set this property to a reference to an ARRAY of packages names, and all the subs in each package will receive the reference to the CBB object in $_[0].

   __PACKAGE__->tm_lookups_package([ 'My::Special::Lookups',
                                     'My::Other::Lookups'  ] ) ;

tm_extra_value_handlers

This class group accessor handles the 'TableTiler' and 'FillInForm' value handlers. You must explicitly exclude them in order to save some loading and execution time (if your application doesn't use them):

   __PACKAGE__->tm_extra_value_handlers( 'FillInForm' => 0
                                       , 'TableTiler' => 0
                                       );

Advanced methods

tm_new()

This method is not intended to be used directly in your CBB. It is used internally to initialize and return the Template::Magic object. You can override it if you know what you are doing, or you can simply ignore it ;-).

Note: This method will add to the object lookups the tm_lookups_package package(s), plus an internal CGI::Builder::Magic::Lookups special package, used for the Special Integration features. This last package is added as the latest lookup location, thus allowing you to eventually override its methods in your own *::Lookups package(s).

CBF overridden methods

page_content_check

This extension use this method to check if the template file exists before using its template print method, thus avoiding a fatal error when the requested page is not found.

Note: You don't need to directly use this method since it's internally called at the very start of the RESPONSE phase. You don't need to override it if you want just to send a different header status, since the CBF sets the status just if it is not defined yet.

EFFICIENCY

You should add a couple of optional statements to your CBB in order to load at compile time the TableTiler and the FillInForm autoloaded handlers (just if you use them in your templates):

    use CGI (); # as recommended in the C::B manpage
    use Template::Magic qw( -compile TableTiler FillInForm );

If you can do so, you could also put the statements directly in the startup.pl file. See also "The -compile pragma" in Template::Magic.

SUPPORT

See "SUPPORT" in CGI::Builder.

AUTHOR and COPYRIGHT

© 2004 by Domizio Demichelis (http://perl.4pro.net)

All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as perl itself.

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 508:

L<> starts or ends with whitespace

Around line 623:

Non-ASCII character seen before =encoding in '©'. Assuming CP1252