ContentBase.pm : generic content-management methods

This is the base class for the ExSite core content management framework. (Core content pertains to basic web page content such as HTML, images, stylesheets, etc.) The base class contains tools that can be used/inherited by all CMS data types (ie. sites, pages, content definitions, and content data), as well as tools that deal with the entire content stack at once.

NOTE: CMS objects can exist in two forms: (1) as data objects (a hash of attribute keys/values, equivalent to a DB record), or (2) as code objects. The names of the data objects correspond to the names of the DB tables used to store their attributes. The names of the code objects correspond to the Perl modules/classes that define them. These names are similar, but do not match exactly:

    +------------------------------+-----------------------------+
    |  DATA OBJECT                 |  CODE OBJECT                |
    +------------------------------+-----------------------------+
    |  section                     |  Section                    |
    |  page                        |  Page                       |
    |  content                     |  Content                    |
    |  content_data                |  ContentData                |
    +------------------------------+-----------------------------+

It can be considered a bug that we use both conventions when referring to object types, not always consistently.

new(%option) - generic constructor

This is a general-purpose constructor that is used by all CMS classes. As such, it is generally called via one of the other CMS classes (ie. ContentData, Content, Page, or Section). Usage is typically:

    my $page = new ExSite::Page(id=>$page_id);      # numeric ID
    my $page = new ExSite::Page(page=>$page_data);  # page datahash

where ``page'' can be replaced with ContentData, Content, or Section).


Context Handling

The ``context'' consists of the related elements in the content ``stack''. For instance, an image object will belong to a certain page, which will belong to a certain section; it will also have a current version among the known versions.

set_context($mode,$version) - find related content

The rules for identifying parents in the stack is simply to use the foreign key reference in the child record. The rules for identifying children in the stack are more complicated:

Setting the context consists of finding and loading the other objects in this stack. It is assumed that the current data object is already loaded.

$mode is none|all|parent|child, depending on whether one needs no context, full context, parent context, or child context only.

$version is not really used at this time, but can be used to identify non-current versions that you wish to select instead of the current version.

Many of the context-testing functions below will not return useful results if the context has not been set. However, we don't want to automatically set the context every time, because it is costly and many basic operations do not require it.

clear_context() - unset the context

Removes any context settings that have already been made.

reset_context($mode,$version) - set the context again

set_context() saves its results so that it will not execute again unnecessarily. reset_context() forces the context to be set over again. Parameters are the same as set_context()

is($type) - test if the current object is of a certain type.

$type can be one of ``Page'', ``Section'', ``Content'', or ``ContentData''.

Example - given a content object $x:


    if ($x->is("Page")) { # we are a Page object

has($type) - test if the context contains a $type

$type can be one of ``Page'', ``Section'', ``Content'', or ``ContentData''. has() returns true if the given type is found in the current object's context.

Example - given a content object $x:


    if ($x->has("Section")) { # we have our section data loaded into the context

has_content() - test if the object has any content

Returns false if the object's content is empty/undefined, true otherwise.

Example - given a content object $x:


    if ($x->has_content()) { # this content object contains real content

get($type,$attribute) - fetch a content attribute

$type can be one of ``Page'', ``Section'', ``Content'', or ``ContentData''. $attribute can be any attribute of the $type. If $attribute is not given, all attributes are returned in a datahash.

Example - given a content object called $img, get the filename of the page it is located in:


    my $filename = $img->get("page","filename");

id($type) - return numeric ID of $type

$type can be one of ``Page'', ``Section'', ``Content'', or ``ContentData'', which must be loaded into the context. If $type is not given, returns the numeric ID of the current object.

Example - given a content object called $img, get the ID of the page it is located in:


    my $id = $img->id();            # ID of the image
    my $page_id = $img->id("page"); # ID of the image's page


CMS Access Control

Access control in the ExSite CMS is normally handled on a section-by-section basis. Each section has its own set of managers, who can each have the following types of access to the section:

editorial
The manager can create, update, and delete editorial objects.

design
The manager can create, update, and delete design objects and templates.

administrator
The manager can create/delete pages.

Who has manager access to a section, and what types of access they have, is determined by their administrator keys to the section. An administrator key is a hash with the following keys/values:

member_id
The UID of the user whom this key belongs to.

section_id
The section ID the key is for.

priveleges
A plain text list of the types of access (above) that are granted by this key.

If you have a group of items that require different access priveleges from the rest of the section, consider placing these items into their own section and issuing a new set of keys for them.

get_keys()

Returns the key(s) that the current user has for the current section. They are returned in an array (or arrayref in scalar context), even if there is only one.

allow_update($type,$data) - can the user modify the $type?

$type can be one of ``page'', ``section'', ``content'', or ``content_data'', $data is the attribute datahash for the $type, if not using the one in the context. Returns true/false.

allow_insert($type,$data) - can the user create a new $type?

$type can be one of ``page'', ``section'', ``content'', or ``content_data'', $data is the attribute datahash for the $type. Returns true/false.

allow_delete($type,$data) - can the user delete the $type?

$type can be one of ``page'', ``section'', ``content'', or ``content_data'', $data is the attribute datahash for the $type, if not using the one in the context. Returns true/false.

owns() - does the user ``own'' the object?

The user owns the object if they have a key for the section that the object belongs to.


Content Searches

When building a page, ExSite encounters various tags that reference content objects such as images, HTML, etc. ExSite must search for matching objects to resolve these references, within the parameters of the current context. (For example, there could be many index.html pages in the system; which one is meant depends on where one begins looking for it.)

find($name,$mode) - locate related content objects

Locates a named content object, starting from the current context (which will be set automatically if not already set). The object is sought in the following locations:

    - in current page's content objects
    - in templates' content objects, including inherited templates
    - in content libraries for this section
    - in content libraries for ancestral sections

The first eligible match satisfies the algorithm, and searching will stop.

Returns the found object's attribute hash if $mode is ``data''. If $mode is ``object'', find() will return a new content object.

find_page($name,$section_id) - find a page

Returns the attribute hash for a page with filename $name. The $section_id may optionally be specified, if looking outside the current context.

find_content($name,$page_id) - find a content object

Returns the attribute hash for a content object named $name. The $page_id may optionally be specified, if looking outside the current context. This is used by the more powerful find() method to search individual pages, templates, and libraries for matching content.

find_content_data($type,$content_id) - find content data

Returns the attribute hash for the content data in the content object indicated by $content_id. $content_id is optional, and only needed in the case where the content object is different from that in the context. $type is not currently meaningful, and can be left undefined.


Page Building and Content Expansion tools

get_start_html($mode) - initialize the HTML for an object

page content objects are typically built starting from an HTML framework that comes out of a template. This template might be precompiled, which means that it resides on disk as a partially-processed HTML file. If not precompiled, then it resides in the database as raw HTML. This method identifies and returns the appropriate block of initial HTML to begin building the page from.

For non-page content objects, this simply returns an HTML representation of the object.

expand(%options) - expand/convert CMS tags

Expands the content in the current context, by replacing CMS tags with the URLs or the raw content that they represent. Returns the HTML for the content.

Options:

content
a hash of content names and values to use preferentially over those in the database

method
a combination of data, url, content, page, module, depending on which expansions you want to apply to this content. All are selected, by default. You can also specify dummy-content to substitute placeholder graphics instead of full content.

expand
template|design - this flag requests partial expansion of the content. Only template/design content is expanded; remaining tags are left in place. DCD tags are left unexpanded in both cases.

cms
if true, include CMS tools in the output, for interactive page editing.

mode
``dynamic'' (fetch everything from DB source) or ``static'' (default; fetches published and precompiled versions where possible)

The substitute() method is an old synonym for expand().

get_page_url($id) - return replacement text for a {{...}} CMS tag

Tags such as {{123}} or {{index.html}} will be replaced with the correct URL to the indicated page (referenced by a numeric page ID, or the page file name).

get_content_url($name,$option) - return replacement text for a [[...]] CMS tag

Tags such as [[image.gif]] will be replaced with the correct URL to the indicated content object. $name is the name of the content object. $option is a reference to an option hash; only one option is currently recognized:

mode
static|dynamic - force the URL to fetch the published or database versions of the content, respectively. This is optional; the system defaults to static, if it is available, dynamic otherwise.

get_content($name,$option) - return replacement HTML for a <!--content(...)--> CMS tag

This is similar to get_content_url(), except the full HTML is substituted instead of just the URL. Accepts the same options as expand(), and acts on the following:

content
This can point to a hash of predefined content definitions, which you can use to override the content database.

method
Same as the method item passed to expand(). The ``dummy-content'' method is the only one used in this method.

expand
``template'' if we are precompiling a template, and wish to leave page-specific data unexpanded.

cms
Inserts interactive page editing tools, if true.

get_dynamic_content($module,$args,$option) - return replacement text for a <!--&Module(...)--> CMS tag

Loads up the $module plug-in, and calls its write() method, passing the $args to it. Returns the output of the module. If the module fails to load/compile, a Perl error string will be returned.

$option is the same as is passed to expand(). If the ``expand'' option or ``dummy-method'' methods are selected, a placeholder image will be substutited instead of the module content.

get_dynamic_content($module,$args,$option) - return replacement text for a <!--&Module(...)--> CMS tag

Loads up the $module plug-in, and calls its write() method, passing the $args to it. Returns the output of the module. If the module fails to load/compile, a Perl error string will be returned.

$option is the same as is passed to expand(). If the ``expand'' option or ``dummy-method'' methods are selected, a placeholder image will be substutited instead of the module content.

get_dynamic_content_indirect() - AJAX version of get_dynamic_content()

This method returns replacement text for CMS tags of the form:

    <!--&&Module(...)-->    indirect substitution, direct re-links
    <!--&&&Module(...)-->   indirect substitution, indirect re-links

This fetches the DCD content using a separate server request, instead of inlining it directly.

The main advantage is that you can publish the main page to a static HTML file, yet keep some page elements dynamic. This is especially useful for index.html pages, which must be static, but may contain dynamic elements (eg. recent news, upcoming events, current specials, etc.). The solution is either continuous republishing of the index page (which may still be a better solution for heavily loaded sites) or using an indirect dynamic content fetch.

The disadvantage is that the full page is slower (although the base page may be much faster), and that JavaScript must be enabled to perform the secondary content fetches.

The '&&' variant does direct re-links, ie. links from the dynamic content point to full URLs that generate a new page. The '&&&' variant does indirect re-links, ie. links back to the same module in the same page only fetch the DCD content and inline it dynamically into the current page without generating a whole new page.


CMS Data Fetching Methods

These are wrappers for the DB data fetching methods. The only difference over the generic DB data fetching methods is that we use more aggressive caching, since we know the number of records returned will be relatively low.

The parameters are the same as the equivalent methods in ExSite::DB.

fetch()
fetch_child()
fetch_match()

Plug-in Fetching Methods

get_dcd_all()
Returns an array of installed DCD names.

get_dcd()
Returns an array of DCD names available to the current site.