=pod

=head1 Name

Bric::Templates - Producing Templates on the Bricolage System

=head1 Version

$LastChangedRevision$

=head1 Date

$LastChangedDate: 2005-12-03 18:19:49 -0800 (Sat, 03 Dec 2005) $

=head1 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:

=over

=item * Element Types

=item * Elements

=item * Templates

=item * Fields

=back

A quick word about each of these elements.

=head2 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.

=head2 Elements

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

=head2 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.

=head2 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.

=head1 Template Overview

=head2 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:

=over

=item * An author field

=item * A column topic field

=item * One or more paragraph fields

=back

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:

=over

=item * Artist name

=item * Album name

=item * Label name

=item * Summary

=back

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

=over

=item * An author field

=item * A column topic field

=item * One or more paragraph fields

=item * Any number of Music Blurb subelements

=back

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!

=head2  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.

=head2 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:

=over

=item * music

=item * theater

=item * gallery

=back

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

=over

=item * music

=item * music/dj

=item * music/classical

=item * music/rock

=item * theater

=item * theater/broadway

=item * theater/community

=item * gallery

=item * gallery/painting

=item * gallery/sculpture

=back

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 "/":

=over

=item * /

=item * /music/

=item * /music/dj/

=item * /music/clasical/

=item * /music/rock/

=item * ...

=back

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 I<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 I<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.

=head2 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 I<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.

=head2 Bringing It All Together

By now you might be asking, I<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 L<Bric::HTMLTemplate|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
F<column.mc>, F<column.tt>, F<column.php>, F<column.pl> or F<column.tmpl>.

The category associated with a template determines the path of the template
file. So for a template in the F</music/rock/> category, the path to the
template would be F</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
F<oc_1/music/rock/column.mc>.

If we assume that our element root is $COMP_ROOT, the full path to our
template is F<$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,
F</music/rock/column.mc> or even just F<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.

=head2 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 F<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 I<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
F</column.mc>. It's important to realize that element templates do not
I<chain>. That is, the story published to "/music/rock/" will I<not> be
formatted by both F</music/column.mc> I<and> F</column.mc>. Once an element
template is found, the search stops. Thus element templates in subcategories
I<override> element templates in parent categories.
Mason

=head2 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 I<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
F<autohandler> in Mason, F<wrapper.tt> in Template Toolkit, F<cat_tmpl> in
PHP, and F<category.pl> or F<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 C<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).

=head2 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 C<<
$burner->chain_next(@_) >> rather than C<< $m->call_next >>. This is where
Bricolage will set things up and call C<< $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 F<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 C<< <%method> >> or C<< <%attr> >> block in F<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 F<column.tt> will be stored in the C<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 C<$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.

=head3 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 F<column.mc> outputs the story content in C<< <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>

=head1 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
L<HTML::Mason::Devel>. A tutorial on Mason is beyond the scope of this document.

=head2 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:

=over

=item *

An author field

=item *

A column topic field

=item *

1 or more paragraph fields

=item *

1 or more Music Blurbs

=back

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:

=over

=item *

An author field element

=item *

A topic field element

=item *

A paragraph field element

=item *

A music blurb container element

=back

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

=head2 Available Objects and Methods

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

=over

=item $story

The story object

=item $element

The current element object

=item $burner

The burner object

=back

=head3 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
L<Bric::Biz::Asset::Business::Story|Bric::Biz::Asset::Business::Story>, but
let's highlight some of the most important and useful ones here:

=over

=item C<< $story->get_title >>

Retrieve the title of this story.

=item C<< $story->get_description >>

Retrieve the description for this story.

=item C<< $story->get_cover_date >>

Returns the story's cover date, which is an arbitrary date associated with
the story.

=item C<< $story->get_publish_date >>

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

=item C<< $story->get_first_publish_date >>

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

=item $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.

=back

=head3 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
L<Bric::Biz::Element::Container|Bric::Biz::Element::Container>, as well as its
parent class in L<Bric::Biz::Element|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.

=over

=item C<< $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?).

=item C<< $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 C<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 L<DateTime|DateTime> for full documentation of the
C<strftime> format.

=item C<< $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.

=item C<< $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 C<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.

=item C<< $element->get_containers(@key_names) >>

This method corresponds to C<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.

=item C<< $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 I<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.

=item C<< $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) C<get_place()> will return 1.

=item C<< $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,
C<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) C<get_object_order()> will return 1.

=item C<< $element->get_key_name >>

Return the key name of the container element.

=item C<< $element->get_name >>

Return the name of the container element.

=back

=head3 Field Object Methods

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

=over

=item C<< $field->get_value($format) >>

Returns the field's value; that is, the content. The C<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
L<DateTime|DateTime> for full documentation of the C<strftime> format.

=item C<< $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.


=item C<< $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, C<get_object_order()> will return
2.

=item C<< $field->get_key_name >>

Returns the key name of this field element.

=item C<< $field->get_name >>

Returns the name of this field element.

=back

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:

=over

=item C<< $element->is_container >>

Returns 1 if $element is a container element object and 0 if it is a field
element.

=back

=head3 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:

=over

=item L<Bric::Util::Burner|Bric::Util::Burner>

The burner base class, where most methods are defined.

=item L<Bric::Util::Burner::Mason|Bric::Util::Burner::Mason>

The Mason burner class.

=item L<Bric::Util::Burner::TemplateToolkit|Bric::Util::Burner::TemplateToolkit>

The Template Toolkit burner class.

=item L<Bric::Util::Burner::PHP|Bric::Util::Burner::PHP>

The PHP burner class.

=item L<Bric::Util::Burner::Template|Bric::Util::Burner::Template>

The HTML::Template burner class.

=back

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

=over

=item C<< $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 C<< $field->get_value >>.
For container elements, C<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.

=item C<< $burner->sdisplay_element($element) >>

This method is identical to C<display_element()> except that it returns the
output rather than adding it to the output buffer.

=item C<< $burner->display_pages(\@key_names) >>

This method works like C<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 C<display_pages()> will be executed for each page in the
story.

=item C<< $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.

=item C<< $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: C<PUBLISH_MODE>, C<PREVIEW_MODE>, and (for completeness)
C<SYNTAX_MODE>. Useful for when your template needs to have different
behaviors between previews and publishes.

=item C<< $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.

=item C<< $burner->get_oc >>

Returns the L<Bric::Biz::OutputChannel|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.

=item C<< $burner->get_cat >>

Returns the L<Bric::Biz::Category|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.

=item C<< $burner->best_uri($doc) >>

Returns a C<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.

=item C<< $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.

=item C<< $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 C<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.

=item C<< $burner->preview_another($doc, $oc_id) >>

Like C<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.

=item C<< $burner->blaze_another($doc) >>

This method can be called instead of C<preview_another()> or
C<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 C<preview_another()>.

=back

=head2 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:

=over

=item Column

Fields:

=over

=item deck

=back

Subelements:

=over

=item page

=back

=item Page

Fields:

=over

=item paragraph

=item pull_quote

=item next

=item previous

=back

Subelements:

=over

=item inset

=back

=item Inset

Fields:

=over

=item copy

=back

=back

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 C<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 C<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
L<Bric::AdvTemplates|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 C<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 C<next_page_file()> method
returns a file name only if there will be a next page, and the
C<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 C<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.

=head1 Appendix

=head2 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

=head2 Glossary

=over

=item 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".

=item Burner

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

=item 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.

=item Element Type

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

=item Element

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

=item Container Element

An element containing structured content based on an Element Type.

=item Field element

An element that represents textual content.

=item dhandler

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

=item Mason

A popular Perl-based templating architecture.

=item Template Toolkit

Another popular Perl-based templating architecture.

=item HTML::Template

Yet another popular Perl-based templating architecture.

=item PHP

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

=item 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.).

=item Story

A content document.

=item Template

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

=back

=head1 Authors

David Wheeler <david@kineticode.com>

Garth Webb <garth@perijove.com>

=head1 See Also

=over

=item L<Bric::AdvTemplates|Bric::AdvTemplates>

=item L<Bric::Biz::ElementType|Bric::Biz::ElementType>

=item L<Bric::Biz::Asset::Template|Bric::Biz::Asset::Template>

=item L<Bric::Biz::Asset::Business::Story|Bric::Biz::Asset::Business::Story>

=item L<Bric::Biz::Element|Bric::Biz::Element>

=item L<Bric::Biz::Element::Field|Bric::Biz::Element::Field>

=item L<Bric::Biz::Element::Container|Bric::Biz::Element::Container>

=item L<Bric::Util::Burner|Bric::Util::Burner>

=item L<Bric::Util::Burner::Mason|Bric::Util::Burner::Mason>

=item L<Bric::Util::Burner::TemplateToolkit|Bric::Util::Burner::TemplateToolkit>

=item L<Bric::Util::Burner::Template|Bric::Util::Burner::Template>

=item L<Bric::Util::Burner::PHP|Bric::Util::Burner::PHP>

=back

=cut
