Writing Template Datasources
Templates Tutorial : Writing Template Datasources
Overview
A template consists of two parts: the ADP page and the TCL executable file.
The purpose of the TCL file is to generate the datasources used by the ADP
page, and to run other setup code. In particular, the TCL file may perform
any of the following tasks:
- Retrieve the attributes of the current item
- Run and document database queries
- Create and process forms
Retrieving attributes of the current item
When an item is accessed (either by being viewed in the browser or by being
published), the template assigned to the item receives an implicit refrence
to the item's attributes. The TCL file may call
content::get_content
in order to access the item's attributes. The attributes will be placed in
a onerow datasource (i.e., a TCL array) called content; the live
revision for the item is used to look up the attributes. For convenience,
the TCL file may call
template::util::array_to_vars content
in order to convert the datasource to local variables, which may be used
as onevalue datasources by the ADP file.
The content datasource is guaranteed to contain the following
fields:
- item_id - The id of the item
- revision_id - The id of the live revision
for the item
- content_type - The content type of the item
- name - The filename of the item, without
any extension
- parent_id - The id of the container for this item
- title - The title of the item, which may be blank
- description - The description of the item,
which may also be blank. The maximum size for the description is
4000 characters.
- mime_type - The mime-type of the item,
such as "text/html" or "image/jpeg"
- text - The content blob of the item, in text format.
Be careful when using this attribute - if the content
blob of the item is in fact binary data, the TCL script may crash
- context_id, security_inherit_p,
creation_user, creation_ip,
last_modified, modifying_user,
modifying_ip - The properties of the item's live
revision in acs_objects
In addition, any extra attributes defined by the item's content type will
be present in the datasource. For example, if the current item has the
press_release content type, which defines a company_name
attribute, the content datasource will contain a company_name
field.
Content API Pitfalls
The content API may lead to some unexpected behavior if used incorrectly;
some common errors are outlined below.
Updating revisions
The attributes of each revision are cached, in order to improve performance.
This may lead to unexpected behavior. Consider the following scenario:
- The my_press_release item (item_id = 1) has a live
revision, whose revision_id is 4
- The item is served in the browser, and the attributes for the revision
#4 are used. The title of the revision is "My Press Release"; this
title is cached along with other attributes
- Some TCL script executes an update statement on the cr_revisions
table, changing the title of revision #4 to
"The Care and Feeding of Manatees"
- The item's page is refreshed in the browser. Since the attributes for
the revision #4 are cached, the title shows up as "My Press Release",
even though the title column in the database is set to
"The Care and Feeding of Manatees"
To avoid this behavior, TCL and PL/SQL scripts should never update the
cr_revisions table. Instead, the scripts should create a new
revision for the item.
Using connection-specific calls
Sometimes, the item's template may need to retrieve the URL of the current
item, the package key of the active package, etc. Standalone TCL scripts
and templates may use ns_conn or ad_conn in order to
retrieve this information. However, when the item is being published (i.e.,
written to the filesystem), the current URL is the URL of the publishing
script (typically, cms/modules/items/publish.tcl), not the URL
of the item itself. Similarly, the data in the ad_conn fields
will pertain to the CMS package. Thus, content items will render correctly
when being previewed in CMS or served directly from the database, but
will not render correctly when published to the filesystem.
To remedy this situation, the TCL file for the item's template should
avoid using [ns_conn url] and other connection-specific calls.
Instead, the TCL file may call content::get_content in order
to retrieve the item_id of the item, and then call
set current_url [item::get_url $content(item_id)]
Once the item's ID and URL are known, the TCL file may retrieve other
information about the current page by using standard APIs. Note:
This situation could be remedied, but the solution would
involve some nontrivial coding. However, CMS-TCL is frozen, and so no
solution exists at this time.
Manually querying the database
In addition to the item::get_url call mentioned above, the
item namespace provides other procs which retrieve miscellaneous
data about the item. For example, item::get_extended_url can be
used to compute the full URL of the item (including the file extension).
Most of the queries performed by the item procs are cached for
efficiency. In addition, the item procs are more flexible than
hardcoded SQL queries; when the CMS implementation changes (to support
subsites, for example), the implementation of the procs will change, but
the interface will remain the same.
For more information, see the auto-generated
documentation on the item
namespace.
Querying the database
The TCL file may query the database in order to create datasources which the
ADP page will use to render the page. In order to simplify the SQL queries, the
Content Repository provides an "x" view along with each content type. The
view joins together all the attributes of the content type, and contains
all revisions for each content item with the given content type.
For example, consider an index page whose purpose is to serve press releases for
a company. Each press release has the content type press_release
Thus, a SQL query such as
select
title, topic, content_item.get_path(item_id) as press_url
from
press_releasesx
will select all revisions of all press releases in the system. In order to select
only the live revisions, the TCL file may join with the cr_items table:
select
x.title, x.topic, content_item.get_path(x.item_id) as press_url
from
press_releasesx x, cr_items i
where
i.live_revision = x.revision_id
This query, when executed through the ACS DB API or template::query,
will produce a multirow datasource which the ADP page may then use
to render a list of all available press releases. For example, the template
may use the following markup:
<ul>
<multiple name=press_releases>
<li>
<a href="@press_releases.press_url@">@press_releases.title@</a>
(@press_releases.topic@)
</li>
</multiple>
</ul>
resulting in a list of press releases:
Multirow datasources may also be created manually, by using the
template::multirow command. In addition, the template may create
onerow (TCL arrays) and onevalue (TCL variables) datasources;
see the templating system documentation for more information.
Documenting the Datasources
In addition to creating the datasources, the TCL file should document them,
so that the CMS Templates UI may describe them to the user in the
Datasources pane. The format for
datasource documentation is similar to Javadoc:
# @datasource datasource_name datasource_type datasource_comment
# @column column_name column_comment
# @column column_name column_comment
# ...
The fields are explained in greater detail below:
- datasource_name - The name of the datasource;
must be a valid TCL variable name
- datasource_type - Must be multirow,
onerow, onevalue, onelist,
multilist or any other valid datasource type as described in
the templating system documentation
- column_name, column_comment - if the
datasource type is multirow, these fields may be used
to describe the individual columns of the datasource. Otherwise, these
fields are ignored.
- datasource_comment - The comment describing the
datasource
For example, consider a fragment of the master-2 template, which
is installed by the CMS Demo:
# @datasource articles multirow
# @column location
# @column name
# @column title
# This datasource enumerates all articles across all locations
#
# @datasource location onevalue the user clicked location
#
# @datasource current_url onevalue
This documentation fragment describes three datasources: articles,
location and current_url. The articles datasource
is a multirow datasource with three columns, location, name
and title. The location and current_url are
both onevalue datasources.
These pseudo-Javadoc tags merely describe the datasources - they do not have
any impact on how the template is actually rendered. However, the tags help
clarify the purpose of the template. The CMS Templating UI will attempt to parse
the template if it detects no pseudo-Javadoc datasource comments;
however, the parsed results cannot compare in quality to human-generated
documentation.
Creating and Processing Forms
In addition to the forms API provided by the templating system, the CMS Forms API
provides various procs designed to automate the content item creation process.
The simplest way to create a new item is to perform the following TCL calls:
content::new_item_form -form_name form_name -contnent_type content_type
if { [template::form is_valid form_name] } {
content::new_item form_name
template::forward next_page_url
}
This snippet of code will execute the following steps:
- Construct a blank form for the creation of the new item. The form
is constructed based on form widgets registered to the content type in
the CMS Content Type UI
- Validate the form. If any required elements are missing, if any
user-entered values do not match the proper datatypes, or if any
other error occurs, the error will be reported to the user and the form
will not submit
- Process the form, creating a new content item and its first revision
based on the user-entered values
- Forward the user to the next page in page flow
The CMS Forms API also includes other, less powerful but more versatile
procs. For example, content::add_revision_form may be used to
generate a form for editing an existing content item. More help can be
found in the auto-generated documentation of the
content namespace, or
directly in the source code of form-procs.tcl.