Bric::Templates(3p)   User Contributed Perl Documentation  Bric::Templates(3p)



Name
       Bric::Templates - Producing Templates on the Bricolage System

Version
       $LastChangedRevision$

Date
       $LastChangedDate: 2005-12-04 03:19:49 +0100 (Sun, 04 Dec 2005) $

Background
       Before talking about templates, let's take a moment to discuss all the
       major players in the publish process and get the terminology down. The
       major players involved in publishing a story are:

       o   Element Types

       o   Elements

       o   Templates

       o   Fields

       A quick word about each of these elements.

   Element Types
       These are content container definitions. They describe what kinds of
       content that a story based on the element type will have. For instance,
       an "Editorial" element type might define that an Editorial contains "An
       author name, a title, and one or more paragraphs". Element types cannot
       affect the formatting or look of a story, just the structure of the
       content.

   Elements
       Elements are instances of element types, and contain the content of
       stories.  The structure of Elements adheres to that defined by their
       types.

   Templates
       For a given element, a template formats its content for output. The
       formatted content will then be saved in one or more files by the
       Bricolage burner.

   Fields
       Fields contain the content itself. Given an element type to constrain
       the types of fields, a content author then enters the content into
       fields. Upon preview or publication of the story, this content is then
       run through a template to produce one ore more output files.

Template Overview
   More About Elements
       The first place one starts when making a new story is with an element.
       An element is based on an element type, which defines the structure of
       a story.  For example, a "Column" element type might define a column
       story as having:

       o   An author field

       o   A column topic field

       o   One or more paragraph fields

       Given this definition, a content author creating a new column element
       will have these three types of fields available to her.

       Elements may also contain other elements. For example, the "Column"
       element type above might be used for a column reviewing music. A music
       column might want to have a short blurb about the albums that it
       reviews. So we create another element type called "Music Blurb" with
       these fields:

       o   Artist name

       o   Album name

       o   Label name

       o   Summary

       Now in our "Column" element type we can add the "Music Blurb" element
       type as a Subelement. So now the structure looks like this:

       o   An author field

       o   A column topic field

       o   One or more paragraph fields

       o   Any number of Music Blurb subelements

       Now a content author editing a Column story has the ability to add an
       author field, a topic for the column, a few paragraphs, and a blurb
       about the album she is reviewing. Element types can defined elements to
       be nested as deeply as needed. So an element can contain an subelement,
       that contains another subelement, etc.

       The most important thing to understand about element types is that they
       simply define the structure of the content that the author is allowed
       to use when creating or editing a story. The element type has no
       bearing on the actual content itself, or the formatting of that data!

   Template Basics
       Templates are the objects that actually format content. There are three
       basic types of templates: element templates, category templates, and
       utility templates.  We'll start with the most common, element
       templates.

       An element template is associated with a single element type and knows
       how to format content for elements of that type. For example, for our
       hypothetical "Column" element type, we might create a template to
       output HTML like this:

         <html>
           <head><title>$column_topic</title></head>
           <body>
             <h1>$column_topic</h1>
             <h2>By $author</h2>

             <p>$para1</p>
             <p>$para2</p>
             ...
             display_element(music_blurb)
             ...
           </body>
         </html>

       This example doesn't represent the actual syntax for inserting values,
       but is meant to convey a template's relationship to an element. We'll
       get into the nuts and bolts later.

       Note that the Music Blurb element element is referenced by its "key
       name", which is defined by the element type, and is simply passed to a
       display function. Remember, element templates represent the content for
       only a single element; another element template formats a the Music
       Blurb element.

   Templates And Categories
       While a template formats the contents of a single element, there may be
       many templates that all format the same element. Why? Well, templates
       also belong to a single category. Imagine that the site for which we've
       created the current element and template examples is an arts and media
       site. There might be different sections of the site: one for music, one
       for theater, and one for gallery art. This site might therefore define
       the following categories:

       o   music

       o   theater

       o   gallery

       Categories may contain subcategories. This is just to provide greater
       categorization detail:

       o   music

       o   music/dj

       o   music/classical

       o   music/rock

       o   theater

       o   theater/broadway

       o   theater/community

       o   gallery

       o   gallery/painting

       o   gallery/sculpture

       In addition to these categories, Bricolage always provides a "root"
       category for each site. If you don't want something to be specific to a
       particular category, you can assign it to the root category. Root is
       usually shown as "/" in Bricolage, and category URIs always end in "/":

       o   /

       o   /music/

       o   /music/dj/

       o   /music/clasical/

       o   /music/rock/

       o   ...

       So, what does this all mean for templates? By allowing many templates,
       each associated with a different category, to format the same element,
       we can have a custom format for the content in each section of the
       site. Say we want to have a column run in all the major categories of
       our site. That is, we want a Music column, a Theater column, and a
       Gallery column. We want to collect the same data for each of these
       columns, but we want the data to look different when published to each
       of these categories. To do so, you can simply create a column element
       template in each of those categories.

       But note that a new template for every single category is not
       necessary.  The "DJ", "Classical" and "Rock" subcategories will all
       default to using the template associated with the "Music" category. If
       there is no need to change how the content is displayed between any
       category, you can simply create a template associated with the root
       category, and column stories in any category will use it. In fact, the
       vast majority of Bricolage installations have all element templates
       defined in the root category, with only the occasional element template
       defined in a subcategory on an as-needed basis.

   Templates And Output Channels
       Another attribute of a template is its association with an "Output
       Channel."  An output channel is a collection of templates designed to
       format stories in a common format. So it's not unusual to have several
       output channels, such as XHTML, RSS, or WML, each of which outputs the
       contents of stories in a specific format.

       Furthermore, output channels can include templates from other output
       channels. For example, an "Email" output channel might include
       templates from the XHTML output channel. Thus, when a story is
       published to the Email output channel, if the burner cannot find its
       templates in the Email output channel, it will look for them in the
       XHTML output channel. This approach to template sharing can be
       extremely useful for maintaining the consistency of formatting across
       output channels, as well as to facilitate code reuse.

   Bringing It All Together
       By now you might be asking, Where do all my templates go, how does the
       system know what categories have templates in them, and how are they
       used during a publish?

       Now, while there should be no need to manipulate templates directly on
       the Bricolage Server's file system (and it could cause the Bricolage
       system considerable confusion, anyway), let's briefly examine how the
       files are laid out. Hopefully, this exercise will make clear a few
       things about templates and publishing.

       Let's start with names. Element types are given key names when they are
       created, and the key names uniquely identify element types throughout
       Bricolage. In our examples above, we created a "Column" element type.
       When you create an element template and choose its associated element
       type, it automatically assumes the key name of that element type. So,
       if our element type is named "Column" and its key name is "column", our
       template is will also be named "Column" and its base file name will be
       "column".

       The template code may be written in one of four templating languages:
       Mason, Template Toolkit, PHP, or HTML::Template. Each output channel is
       associated with a templating language, so all templates in a single
       output channel (or any output channel it includes) will be written in
       the same templating language. The template file suffix varies depending
       on the templating language: ".mc" for Mason, ".tt" for Template
       Toolkit, ".php" for PHP, or ".pl" or ".tmpl" for HTML::Mason. (The
       examples in this tutorial will be in Mason, Template Toolkit, and PHP;
       See Bric::HTMLTemplate for a tutorial on HTML::Template templates,
       which are a bit different from the others.) So the file name for our
       Column element template would be either column.mc, column.tt,
       column.php, column.pl or column.tmpl.

       The category associated with a template determines the path of the
       template file. So for a template in the /music/rock/ category, the path
       to the template would be /music/rock/column.mc.

       Finally, the output channel is also used as a part of the path on the
       file system. Rather than take the output channel's name, its ID is
       used. Let's just say that the ID for primary channel output containing
       our Column element template is 1. So, our column template would live in
       oc_1/music/rock/column.mc.

       If we assume that our element root is $COMP_ROOT, the full path to our
       template is $COMP_ROOT/oc_1/music/rock/column.mc. In template code, you
       don't need to worry about the full path, however, just the relative
       path, /music/rock/column.mc or even just music/rock/column.mc. The
       individual templating architectures handle the searching for templates
       in the proper output channel directories using their own path searching
       algorithms.

   Publish Examples
       So, let's assume that we have three Column templates in a single Mason
       output channel: one associated with the root category, one associated
       with the Music category, and one associated with the Sculpture Gallery
       category. Their full path names would be:

         /column.mc
         /music/column.mc
         /gallery/sculpture/column.mc

       Now, say that somebody creates a new column. When creating a new story,
       the author has the opportunity to associate it with one or more
       categories. The table below illustrates which column.mc template would
       be used for a publish in a particular category.

           Category where Story Published       Template element Used
           -------------------------------      ----------------------------
           /music/rock/                         /music/column.mc
           /theater/broadway/                   /column.mc
           /gallery/                            /column.mc
           /gallery/art/                        /column.mc
           /gallery/sculpture/                  /gallery/sculpture/column.mc

       As you can see, a story published in a particular category will look up
       the category URI to find an element template to format it if it can't
       find it in the the story's own category. This functionality works
       identically for all supported templating architectures.

       Note that in the case of the stories published in "/music/rock/" and in
       "/gallery/sculpture/", templates were found before the root template at
       /column.mc. It's important to realize that element templates do not
       chain. That is, the story published to "/music/rock/" will not be
       formatted by both /music/column.mc and /column.mc. Once an element
       template is found, the search stops. Thus element templates in
       subcategories override element templates in parent categories.  Mason

   One Final Trick
       Although element templates do not chain, sometimes you might want
       formatting code to be inherited rather than overridden. If you're
       familiar with Mason you may have noticed the similarity between how
       element templates are handled and the Mason concept of "dhandlers". In
       fact in Mason output channels, story element templates are dhandlers.
       Subelement templates of course are not, but they do enjoy the same
       category URI lookup algorithm when the burner searches for them. The
       other category architectures use the same algorithm for all element
       templates.

       But there's another type of template that's useful for inheriting
       formatting behavior from parent categories. These templates are known
       as "category templates." A category template resides in a category, and
       wraps the execution of story element templates. In fact, in Mason
       output channels, category templates are implemented as Mason
       "autohandlers", while in Template Toolkit output channels, they're
       implemented as "wrappers". The PHP and HTML::Template burners emulate
       autohandlers and wrappers, as well. Their file names are autohandler in
       Mason, wrapper.tt in Template Toolkit, cat_tmpl in PHP, and category.pl
       or category.tmpl in HTML::Template. In any case, in Bricolage, these
       templates are all known as "category templates," regardless of the
       templating language in which they're implemented.

       Category templates enjoy a different lookup algorithm. Like Mason's
       autohandlers, category templates are executed from the root category
       "down" the category URI. Furthermore, unlike element templates, the
       search does not stop as soon as a category template is found. Rather,
       it continues down the category URI path, executing each category
       template it finds in a cascading execution pattern.

       For example, say that we have the following category templates defined
       in a Mason output channel:

         /autohandler
         /music/dj/autohandler
         /gallery/autohandler

       This table outlines how they would be executed for stories in a select
       number of categories:

           Category where Story Published       Category Templates Executed
           -------------------------------      ----------------------------
           /music/rock/                         /autohandler
           /music/dj/                           /autohandler, /music/dj/autohandler
           /theater/broadway/                   /autohandler
           /gallery/                            /autohandler, /gallery/autohandler
           /gallery/art/                        /autohandler, /gallery/autohandler

       Given a category URI, Bricolage searches for the first possible
       category template in that path, and then works its way down the path,
       executing any other autohandlers until it finally reaches the story's
       category. Then it starts searching for the story element template. In
       this way, category templates wrap the execution of story element
       templates for any type of story published in the output channel. This
       makes them ideal for the headers and footers that are common to all
       pages on a site (for a root-level category template), or category-
       specific headers/navigation, etc. (for subcategory category templates).

   Category Template Example
       What good are category templates? Let's continue with our running
       example of the arts and media site. Let's say that, regardless of what
       type of story is published, you want the same basic HTML header and
       footer. Whether the story is a "column" or a "review" or an
       "editorial," you want the same header and footer on every page. The
       easiest and most efficient way to do this is by creating a root-level
       category template.

       If we create a new category template in the root category of a Mason
       output channel (for this example, we'll assume an output channel with
       ID 1), then we'll get the file:

         $COMP_ROOT/oc_1/autohandler

       The code for this template might look like this:

         <html>
           <head><title>Arts n' Media</title></head>
           <body>

             <ul id="nav">
               <li><a href="/music">Music</a></li>
               <li><a href="/theater">Theater</a></li>
               <li><a href="/gallery">Gallery</a></li>
             </ul>

             <div id="content">
         % $burner->chain_next(@_);
             </div>

             <p id="foot">The contents of this site are licensed under a <a
             rel="license" href="http://creativecommons.org/licenses/by-nc/2.0/"
             title="Creative Commons Attribution-NonCommercial License">Creative
             Commons License</a>.</p>

           </body>
         </html>

       If you're familiar with Mason, most of this should look pretty normal.
       The only difference from your standard Mason autohandler is the call to
       "$burner->chain_next(@_)" rather than "$m->call_next". This is where
       Bricolage will set things up and call "$m->call_next" internally to
       execute the proper element template and output the story document
       content.  Given this category template, if we publish a column to the
       '/music/rock/' category, the following templates will be used in this
       order:

           $COMP_ROOT/oc_1/autohandler
           $COMP_ROOT/oc_1/music/rock/column.mc

       The content that column.mc outputs after being run will wrapped by the
       HTML in the category template. Furthermore, because the story element
       template is implemented as a dhandler, and the category template is
       implemented as an autohandler, Mason's inheritance methodology will
       work perfectly. If you declare a "<%method>" or "<%attr>" block in
       column.mc, then the category template can call it.

       If we create a new category template in the root category of a Template
       Toolkit output channel (for this example, we'll assume an output
       channel with ID 2), then we'll get the file:

         $COMP_ROOT/oc_2/wrapper.tt

       The code for this template might look like this:

         <html>
           <head><title>Arts n' Media</title></head>
           <body>

             <ul id="nav">
               <li><a href="/music">Music</a></li>
               <li><a href="/theater">Theater</a></li>
               <li><a href="/gallery">Gallery</a></li>
             </ul>

             <div id="content">
         [% CONTENT %]
             </div>

             <p id="foot">The contents of this site are licensed under a <a
             rel="license" href="http://creativecommons.org/licenses/by-nc/2.0/"
             title="Creative Commons Attribution-NonCommercial License">Creative
             Commons License</a>.</p>
           </body>
         </html>

       Here the behavior is identical to your standard Template Toolkit
       wrapper. Unlike the Mason autohandler, however, the execution order is
       reversed:

           $COMP_ROOT/oc_2/music/rock/column.tt
           $COMP_ROOT/oc_2/wrapper.tt

       The formatted content output by column.tt will be stored in the
       "CONTENT" variable in the Template Toolkit stash, and then the wrapper
       template will be executed.

       Any values stored in the stash by the element template are available to
       either wrapper template, and those stored by the "/music/" wrapper
       template would be available to the root wrapper template. This
       functionality roughly corresponds with Mason inheritance.

       As for PHP, its category template is, in fact, almost identical to the
       Template Toolkit category template:

         <html>
           <head><title>Arts n' Media</title></head>
           <body>

             <ul id="nav">
               <li><a href="/music">Music</a></li>
               <li><a href="/theater">Theater</a></li>
               <li><a href="/gallery">Gallery</a></li>
             </ul>

             <div id="content">
         <?= $content ?>
             </div>

             <p id="foot">The contents of this site are licensed under a <a
             rel="license" href="http://creativecommons.org/licenses/by-nc/2.0/"
             title="Creative Commons Attribution-NonCommercial License">Creative
             Commons License</a>.</p>
           </body>
         </html>

       As with Template Toolkit wrappers, the story element template executes
       first, and the formatted output of the element template is stored in
       the $content global variable for access by the category template.
       Furthermore, because the execution order is the same:

           $COMP_ROOT/oc_3/music/rock/column.php
           $COMP_ROOT/oc_3/cat_tmpl

       You can set up global variables (or better, a global associative array)
       in your element templates and have them available to the category
       template. This equates to Template Toolkit's stash and likewise
       corresponds to Mason's inheritance features.

       Subcategory Category Template Example

       As a last example of the chaining of category templates, let's say that
       we wanted some special HTML to appear just in the music section,
       regardless of what type of story we were publishing. Again, the best
       approach is to create a category template in the music category. The
       Mason version would live in the Music category directory:

           $COMP_ROOT/oc_1/music/autohandler

       The Mason code for this category template might look like this:

               <h1>Music</h1>
               <div class="music">
                 <img src="/ui/img/music_icon.png" alt="Air Guitar />
               % $burner->chain_next(@_);
               </div>

       So, given this category template, in combination with the original
       root-level category template, if we again publish a column to the
       '/music/rock/' category, the following templates will be executed in
       this order:

           $COMP_ROOT/oc_1/autohandler
           $COMP_ROOT/oc_1/music/autohandler
           $COMP_ROOT/oc_1/music/rock/column.mc

       After publishing this column, the final page output will look like this
       (for now, just assume that column.mc outputs the story content in "<p>"
       tags):

         <html>
           <head><title>Arts n' Media</title></head>
           <body>

             <ul id="nav">
               <li><a href="/music">Music</a></li>
               <li><a href="/theater">Theater</a></li>
               <li><a href="/gallery">Gallery</a></li>
             </ul>

             <div id="content">
               <h1>Music</h1>
               <div class="music">
                 <img src="/ui/img/music_icon.png" alt="Air Guitar />
                 <p>This is a test column.</p>
               </div>
             </div>

             <p id="foot">The contents of this site are licensed under a <a
             rel="license" href="http://creativecommons.org/licenses/by-nc/2.0/"
             title="Creative Commons Attribution-NonCommercial License">Creative
             Commons License</a>.</p>
           </body>
         </html>

Writing Templates
       The above sections should give you an idea of how to create a template
       -- what it means to associate a template with an element, a category,
       and an output channel. Now let's talk a little about actually writing
       template code.

       Writing template code is no different than writing Mason code. If
       you've written Mason code, you should have no problem writing
       templates. If you have not written Mason code before, I suggest you get
       familiar with it by reading HTML::Mason::Devel. A tutorial on Mason is
       beyond the scope of this document.

   Terminology
       Given that template code is just Mason, Template Toolkit, PHP, or
       HTML::Template code, the only thing you need to know is how to access
       the story data. So let's take a small break to discuss terminology for
       story objects.

       Stories are based on element types. Before you can create a new story,
       you must select an element type upon which your story will be based.
       Based on your selection, you will then be given a list of available
       fields for which you can enter content. If we use the "column" element
       type that we defined earlier, our fields will be:

       o   An author field

       o   A column topic field

       o   1 or more paragraph fields

       o   1 or more Music Blurbs

       Now, if you remember, the author field, column topic field, and
       paragraph fields are all just text fields, while the music blurb is a
       subelement of the column element. This gives us two varieties of
       elements that can be in a story: "Container Elements" and "Field
       Elements", also generally referred to as "Elements" and "Fields",
       respectively.

       In the interest of keeping things simple for the story authors, the
       Bricolage user interface uses a single term for both types of elements,
       "Element." Early user testing showed that authors didn't know or care
       about the difference between field elements and container elements. But
       this should have little bearing on your job as a template developer.
       You can simply think of them as "Container Elements" and "Field
       Elements," or, collectively, as "Elements".

       So our new story based on the column element type may contain the
       following elements:

       o   An author field element

       o   A topic field element

       o   A paragraph field element

       o   A music blurb container element

       Now that we know what a story can have and how to refer to them, let's
       look at the methods to access them.

   Available Objects and Methods
       First, there are three variables exported into the global space of each
       templating architecture for use in templates. These are:

       $story
           The story object

       $element
           The current element object

       $burner
           The burner object

       Story Object Methods

       The story object represents the story document being published. It is
       used to access all the metadata of a story. It can be used to
       indirectly access the actual content of the story, but there is a
       simpler way to do so, which we'll get to shortly. You can read the full
       list of methods callable on the story object by reading
       Bric::Biz::Asset::Business::Story, but let's highlight some of the most
       important and useful ones here:

       "$story->get_title"
           Retrieve the title of this story.

       "$story->get_description"
           Retrieve the description for this story.

       "$story->get_cover_date"
           Returns the story's cover date, which is an arbitrary date
           associated with the story.

       "$story->get_publish_date"
           The date when the story was most recently published; always
           available when publishing a story, but will be "undef" when
           previewing if the story has not been published.

       "$story->get_first_publish_date"
           The date when the story was first published; always available when
           publishing a story, but will be "undef" when previewing if the
           story has not been published.

       $story->get_primary_uri
           Retrieve the primary URI for the story, which is determined by its
           primary category and the URI format of its primary output channel.

       Element Object Methods

       The element object contains the content of a story. Since a story is
       based upon an element type, the field and container elements in the
       $element object are defined by its element type. so if the element type
       defined "author," "topic," and "paragraph," fields, you know that you
       can access those field elements via $element. Where $element really
       becomes interesting, however, is in its container elements.

       In our example, we had defined a "music_blurb" element element type as
       a subelement of the "column" element type. Because it is not a story
       type element, there can be no "music_blurb" story; it can only be part
       of a larger "column" story. However, "music_blurb", just like any other
       element type, needs to have a template that knows how to format it. So
       while burning our "column" story, we will at some point have to call
       out to the "music_blurb" template to format our "music_blurb" element.
       When the "music_blurb" template executes, $story will still contain our
       "column" story object, but $element will contain an instance of a
       "music_blurb" element, and will allow access to the field and container
       subelements defined by the "music_blurb" element type.

       Sound confusing? Well, you can read the full documentation for the
       interface of an element object in Bric::Biz::Element::Container, as
       well as its parent class in Bric::Biz::Element, but let's just go over
       some of the more significant methods callable on $element, and we'll
       get to an example soon enough.

       "$element->get_field($key_name, $num)"
           This method returns the field object with the key name given by the
           $key_name argument. For example, if the element object was a
           "column" element, you could use "author", "topic", or "paragraph"
           for the key name to get the corresponding field.

           The $num argument is optional. It is meant for fields that can
           occur more than once, such as "paragraph"s in our "column" example.
           If $num is not given then it defaults to "1", meaning that the the
           first instance of the field identified by $key_name will be
           returned. The ordering is determined by the content author (you
           want all your paragraphs to be in the correct order, right?).

       "$element->get_value($key_name, $num, $format)"
           This method is a convenient shortcut for

             $element->get_field($key_name, $num)->get_value($format);

           In other words, it returns the content associated with the field
           element given by $key_name. For example, if the element object was
           a "column" element, you could use "author", "topic", or "paragraph"
           for the key name to get the value stored for the corresponding
           field.

           The $format argument is optional, and may contain a "strftime"
           format string.  Naturally, this is useful only for date fields, and
           is ignored by all others.  If not specified, it defaults to the
           value stored in the "Date/Time Format" global preference. See
           DateTime for full documentation of the "strftime" format.

       "$element->get_fields(@key_names)"
           Returns a list or anonymous array of the field subelements of the
           element. If called with no arguments, it returns all of the field
           subelements, in the order specified by the content editor. They can
           and will be mixed. For example, for our "column" example, it might
           return two paragraphs, then a topic, then three more paragraphs,
           then an author, and then two more paragraphs.

           If you only want specific fields but to still get them in order,
           simply pass in a list of the key names of the fields you're
           interested in. For example, called like this:

             my @elems = $element->get_fields(qw(paragraph topic));

           only paragraph and topic fields will be returned, but still in the
           order specified by the content author.

       "$element->get_container($key_name, $num)"
           This method returns a container element object with the key name
           specified by the $key_name argument. This object is of the same
           type as $element. Usually you will just pass it to a method that
           will execute the correct template for you.

           As with "get_value()", the $num argument is optional, and is used
           to retrieve specific container elements that occur more than once
           in a given story. If $num is not given then it defaults to "1",
           meaning that the value for the first instance of the container
           element identified by $key_name will be returned. The ordering is
           determined by the content author.

       "$element->get_containers(@key_names)"
           This method corresponds to "get_fields()" but returns a list or
           anonymous array of the container subelements of the element. If
           called with no arguments, it returns all of the container
           subelements, in the order specified by the content editor. They can
           and will be mixed. If you only want specific fields but to still
           get them in order, simply pass in a list of the key names of the
           fields you're interested in.

       "$element->get_elements(@key_names"
           This method is perhaps the most used method on the $element object.
           It returns a list or anonymous array of both container and field
           element objects.  Again, pass in a list of field and/or container
           element type key names to get back only elements based on those
           element types. For example, called like this:

             my @elems = $element->get_fields(qw(paragraph topic music_blurb));

           only paragraph, topic, and music_blurb elements will be returned,
           but still in the order specified by the content author.

       "$element->get_place"
           Content authors have the opportunity to arrange the elements of
           their story in a particular order. This method returns a number
           giving this container element's place among all other subelements
           of $element (both data and container).

           If $element is the element object for the story itself (i.e. the
           "column" element of a "column" story) "get_place()" will return 1.

       "$element->get_object_order"
           For a container element that can occur more than once in a story,
           this method returns its place among container elements of the same
           type. For example a "column" story might contain several
           "music_blurb" container elements. If $element happens to be the
           second of three "music_blurb" container elements,
           "get_object_order()" will return 2.

           If $element is the element object for the story itself (i.e. the
           "column" element of a "column" story) "get_object_order()" will
           return 1.

       "$element->get_key_name"
           Return the key name of the container element.

       "$element->get_name"
           Return the name of the container element.

       Field Object Methods

       The "get_field()", "get_fields()", and "get_elements()" methods each
       can return field elements. These are represented by the
       Bric::Biz::Element::Field class, which like the container element
       class, inherits from Bric::Biz::Element. But we'll cover their most
       important methods here:

       "$field->get_value($format)"
           Returns the field's value; that is, the content. The "strftime"
           $format argument is optional, and only used for date fields. If not
           provided, it will default to the value stored in the "Date/Time
           Format" global preference. See DateTime for full documentation of
           the "strftime" format.

       "$field->get_place"
           Content authors have the opportunity to arrange the elements of
           their story in a particular order. This method returns a number
           giving the field's place relative to all of the other subelements
           of the field's parent element.

       "$field->get_object_order"
           For a field that can occur more than once in a story, this method
           returns its place among fields of the same type. For example a
           "column" story might contain several "paragraph" container
           elements. If a field happens to be the second of three "paragraph"
           field elements, "get_object_order()" will return 2.

       "$field->get_key_name"
           Returns the key name of this field element.

       "$field->get_name"
           Returns the name of this field element.

       And finally, both the field and container element classes have a single
       method to help you easily disambiguate containers from fields in your
       template code:

       "$element->is_container"
           Returns 1 if $element is a container element object and 0 if it is
           a field element.

       Burner Object Methods

       The burner object handles the burning of a story; that is, pushing it
       through templates and writing the resulting formatted content to disk.
       Each templating architecture has its own burner subclass, so there is
       some variation in its interface depending on what templating
       architecture you're using. You can read the documentation of the
       complete burner interface and the interfaces of its subclasses in:

       Bric::Util::Burner
           The burner base class, where most methods are defined.

       Bric::Util::Burner::Mason
           The Mason burner class.

       Bric::Util::Burner::TemplateToolkit
           The Template Toolkit burner class.

       Bric::Util::Burner::PHP
           The PHP burner class.

       Bric::Util::Burner::Template
           The HTML::Template burner class.

       But let's cover the most important methods here (HTML::Template users
       are encouraged to read Bric::HTMLTemplate, since its interface is
       pretty different from the other templating architectures).

       "$burner->display_element($element)"
           Outputs the content of the field or container element passed as its
           argument.  For field elements, this is synonymous with calling
           "$field->get_value".  For container elements, "display_element()"
           searches up the URI path of the category to which the story is
           currently being published for the relevant element template. If it
           finds it, it executes it, adds its output to the output buffer, and
           returns control to the calling template.

       "$burner->sdisplay_element($element)"
           This method is identical to "display_element()" except that it
           returns the output rather than adding it to the output buffer.

       "$burner->display_pages(\@key_names)"
           This method works like "display_element()", only it has some magic
           to format only one element at a time, output its contents, and
           write a file, then start the burn of the next page, until all pages
           specified by the array reference of key names have been burned to
           separate files to disk. All template code above and below the call
           to "display_pages()" will be executed for each page in the story.

       "$burner->chain_next"
           This is a Mason-specific method. From a category template, it
           executes the next category template or the specific story template.
           It should not be called from any other template.

       "$burner->get_mode"
           Returns a value indicating in what mode the burner is running. The
           value returned can be compared to three constants imported into the
           template name space: "PUBLISH_MODE", "PREVIEW_MODE", and (for
           completeness) "SYNTAX_MODE". Useful for when your template needs to
           have different behaviors between previews and publishes.

       "$burner->set_encoding($encoding)"
           Sets the character encoding output by the template. Defaults to
           "utf-8" in the Mason, Template Toolkit, and HTML::Template burners,
           and "raw" in the PHP burner. With the exception of the PHP burner,
           you should change the encoding if your template is converting its
           output from UTF-8 (which is how all content is stored in the
           database) to some other encoding so that the content gets properly
           written to disk.

       "$burner->get_oc"
           Returns the Bric::Biz::OutputChannel object through which the story
           is being burned. Useful when using output channel includes, where
           the template executing may be in an output channel included by the
           output channel through which the story is being burned.

       "$burner->get_cat"
           Returns the Bric::Biz::Category object to which the story is
           currently being burned. Useful for stories associated with multiple
           categories, as each category association triggers a separate burn.

       "$burner->best_uri($doc)"
           Returns a "URI|URI" object representing the best URI for the
           document passed.  Useful for multisite Bricolage installations,
           where one story might which to create a link to another story in a
           different site. In that case, it will provide the best URI to use,
           either to an alias in the same site as the current site, or to a
           fully qualified URL to the other site.

       "$burner->get_page"
           Returns the zero-indexed page number currently being burned. For
           multipage stories, each page may be output to a separate file. The
           first page will have the value "0", the second the value "1", and
           so on.

       "$burner->publish_another($doc, $pub_time)"
           If you want the publication of a story to trigger the publication
           of some other story or of an unrelated media document, you can look
           up the document and pass it to "publish_another()". By default, the
           story passed will be scheduled for publish at the same time as the
           current story is being published. Pass in an ISO-8601-formatted
           date string as the second argument to schedule the document for
           publication at a later date. During previews, this method simply
           returns without doing anything.

       "$burner->preview_another($doc, $oc_id)"
           Like "publish_another()", but triggers the preview of another
           document, rather than its publication. Useful in preview mode when
           you want to trigger another document for preview. The second
           argument, an output channel object ID, is optional. If not present,
           the document will be previewed in either the same output channel as
           is currently being previewed, or in its primary output channel. In
           publish mode, this method method simply retrains without doing
           anything.

       "$burner->blaze_another($doc)"
           This method can be called instead of "preview_another()" or
           "publish_another()", and will pass through to the proper method
           depending on the mode. Furthermore, in preview mode, it will burn
           the document to all associated output channels, rather than just
           the current or primary output channel as in "preview_another()".

   A Template Example
       Now let's take a look at some template code. For this example, we'll
       use the "column" element type included in a default Bricolage install
       for our story.  This "Column" is a little different than the one we've
       been discussing; here's the definition for this element type:

       Column
           Fields:

           deck

           Subelements:

           page
       Page
           Fields:

           paragraph
           pull_quote
           next
           previous

           Subelements:

           inset
       Inset
           Fields:

           copy

       Note that this story structure is three levels deep rather than the two
       levels we were discussing before. Furthermore, the "page" element type
       was created with a flag marking it as a paginated element type. We'll
       rely on its marking as a page to pass the key name "page" to
       "display_pages()" so as to output all of the "page" elements as
       separate files during the burn.

       Here is the Mason code for the "column" template:

         <html>
           <head>
             <title><% $story->get_title %></title>
           </head>
           <body>

         % $burner->display_pages('page');

           </body>
         </html>

       Here is the Template Toolkit version:

         <html>
           <head>
             <title>[% story.get_title %]</title>
           </head>
           <body>

         [%- burner.display_pages('page') -%]

           </body>
         </html>

       and the PHP:

         <html>
           <head>
             <title><?= $story->get_title() ?></title>
           </head>
           <body>

         <?php $burner->display_pages('page'); ?>

           </body>
         </html>

       Note that the code is essentially identical in all three templating
       architectures; only the templating syntax varies.

       The call to "display_pages()" simply iterates through each "page"
       container element in the "column" story and displays it. Remember that
       the page element was created with the 'paginated' flag and will start a
       new output file for each page. Also, note that we haven't output the
       contents of the "deck" field.  This field is meant for use as a teaser
       when another story creates a link to this story. (Formatting of related
       stories is covered in Bric::AdvTemplates.)

       Next let's look at some example code for the "page" element template.
       Here's the Mason version:

         % unless ($burner->get_page) {
         %   # Only output the title on the first page.
             <h1><% $story->get_title %></h1>
         % }

         <%perl>;
         foreach my $e ($element->get_elements(qw(paragraph pull_quote inset))) {
             my $key_name = $e->get_key_name;

             if ($key_name eq 'paragraph') {
                 $m->print('<p>', $e->get_value, "<p>\n");
             }

             elsif ($key_name eq 'pull_quote') {
                 $m->print('<blockquote>', $e->get_value, "<blockquote>\n");
             }

             else {
                 # It's an inset, which is a container element.
                 $burner->display_element($e);
             }
         }
         </%perl>

         <div id="pagenav">
         % if (my $prev_page = $burner->prev_page_file) {
             <a href="<% $prev_page %>">&lt; <%
                 $element->get_value('previous') || 'Back'
             %></a>
         % }
         % if (my $next_page = $burner->next_page_file) {
             <a href="<% $next_page %>"><%
                 $element->get_value('next') || 'Next'
             %> &gt;</a>
         % }
         </div>

       Here's the Template Toolkit version:

         [%- UNLESS $burner.get_page %]
             [% # Only output the title on the first page. -%]
             <h1>[% story.get_title %]</h1>
         [% END -%]

         [% FOREACH e = element.get_elements('paragraph', 'pull_quote', 'inset') -%]
             [% SWITCH e.get_key_name -%]

             [%- CASE 'paragraph' -%]
                 <p>[% e.get_value %]</p>

             [%- CASE 'pull_quote' -%]
                 <blockquote>[% e.get_value %]</blockquote>

             [%- CASE -%]
                 [%- burner.display_element(e) -%]
             [%- END -%]
         [% END -%]

         <div id="pagenav">
         [%- IF (prev_page = burner.prev_page_file) %]
             <a href="[% prev_page %]">&lt; [%
                 element.get_value('previous') || 'Back'
             %]</a>
         [% END -%]
         [%- IF (next_page = burner.next_page_file) %]
             <a href="[% next_page %]">[%
                 element.get_value('next') || 'Next'
             %] &gt;</a>
         [% END -%]
         </div>

       And finally, the PHP version:

         <?php
         if (!$burner->get_page()) {
             # Only output the title on the first page.
             echo '<h1>', $story->get_title(), "</h1>\n";
         }

         foreach ($element->get_elements('paragraph', 'pull_quote', 'inset') as $e) {
             switch ($e->get_key_name()) {

                 case 'paragraph':
                     echo '<p>', $e->get_value(), "</p>\n";
                     break;

                 case 'pull_quote':
                     echo '<blockquote>', $e->get_value(), "</blockquote>\n";
                     break;

                 default:
                     # It's an inset, which is a container element.
                     $burner->display_element($e);
             }
         }

         echo '<div id="pagenav">', "\n";

         if ($prev_page = $burner->prev_page_file()) {
             $label = $element->get_value('previous') or 'Back';
             echo '<a href="', $prev_page, '">&lt; ', $label, "</a>\n";
         }

         if ($next_page = $burner->next_page_file()) {
             $label = $element->get_value('next') or 'Next';
             echo '<a href="', $next_page, '">', $label, " &gt;</a>\n";
         }
         echo "</div>\n";
         ?>

       Again, the various architectures use the same programming logic and
       output the same content (modulo white space issues). In each case, the
       code outputs a header for the first page of the column only, and then
       the story page content.  Note how we've passed element key names to
       "get_elements()" to retrieve only the elements we want to be ordered.
       Next, links to a previous page and a next page are output, but only if
       those pages exist. The "next_page_file()" method returns a file name
       only if there will be a next page, and the "prev_page_file()" method
       returns a file name for all pages but the first page.

       It is important to realize that there are no restrictions against
       having a container and a field element with the same name. While this
       is unlikely to happen (you're doing the element type design and not
       doing that, right?), if it were true you'd have to check the
       "is_container()" method to tell them apart.

       And finally, We have the code for the "inset" container element
       template.  Here's the Mason version:

         <div class="inset">
           <p><% $element->get_value('copy') %></p>
         </div>

       Here's the Template Toolkit version:

         <div class="inset">
           <p>[% element.get_value('copy') %]</p>
         </div>

       And the PHP version:

         <div class="inset">
           <p><?= $element->get_value('copy') ?></p>
         </div>

       That's about it. If you create and deploy new templates for these three
       element types, and paste in the above code examples, you should then be
       able to create and preview a new "Column" story. Make sure that you
       create your templates in the root category to ensure you can publish a
       story to any category.

Appendix
   Class Names
           Object Type             Associated Perl Class
           ---------------------   ---------------------------------
           Element Type            Bric::Biz::ElementType
           Container Element Type  Bric::Biz::ElementType::Container
           Field Element Type      Bric::Biz::ElementType::Field
           Template                Bric::Biz::Asset::Template
           Story                   Bric::Biz::Asset::Business::Story
           Element                 Bric::Biz::Element
           Field Element           Bric::Biz::Element::Field
           Container Element       Bric::Biz::Element::Container
           Burner                  Bric::Util::Burner

   Glossary
       Category Template
           A template associated with a category that wraps the execution of
           all story element type templates in that category and its
           subcategories. Corresponds to Mason's "autohandlers" and Template
           Toolkits "wrappers".

       Burner
           The Bricolage object responsible for pushing a story through
           templates and writing the resulting output to files.

       Category
           Categories are hierarchical organizing objects used to categorize
           Bricolage documents. The URI path of a category is used to form
           part of each document's URI and is used to organize templates.

       Element Type
           The definition of the structure of a document or the subelement of
           a document.

       Element
           A part of a document, either a container element or a field
           element.

       Container Element
           An element containing structured content based on an Element Type.

       Field element
           An element that represents textual content.

       dhandler
           A Mason concept. In Mason output channels, story element type
           templates are implemented as dhandlers.

       Mason
           A popular Perl-based templating architecture.

       Template Toolkit
           Another popular Perl-based templating architecture.

       HTML::Template
           Yet another popular Perl-based templating architecture.

       PHP A popular server-based Web programming language, ideal for
           templating.

       Output Channel
           A collection of templates based on a single templating
           architecture, designed to output content in a single format (such
           as XHTML, RSS, PDF, etc.).

       Story
           A content document.

       Template
           A file containing template code to format part of a story for
           output.

Authors
       David Wheeler <david@kineticode.com>

       Garth Webb <garth@perijove.com>

See Also
       Bric::AdvTemplates
       Bric::Biz::ElementType
       Bric::Biz::Asset::Template
       Bric::Biz::Asset::Business::Story
       Bric::Biz::Element
       Bric::Biz::Element::Field
       Bric::Biz::Element::Container
       Bric::Util::Burner
       Bric::Util::Burner::Mason
       Bric::Util::Burner::TemplateToolkit
       Bric::Util::Burner::Template
       Bric::Util::Burner::PHP



perl v5.12.2                      2005-12-03               Bric::Templates(3p)
