Version 4 > Developer Guides > Content Model > Behaviour Inheritance

Behaviour Inheritance

In v4 there are multiple mechanisms for inheriting behaviours from related objects and classes.

Class Inheritance

Model (content behaviour)

Content classes should inherit from the base class, ExSite::Content, to get all standard v4 content model behaviours. You can alternatively inherit from higher-level classes; for instance If the new class is page-like, it can optionally inherit from the Page class instead.

The base behaviour is fairly flexible, and is controlled by a few parameters in the content_type table:

  • Publish As (publish_as) - how the content publishes itself
    • file (eg. foo.html)
    • directory (eg. foo/)
    • never if the content does not publish
  • Publish Method (publish) - the default publish rule for this type of content
    • static - content publishes to a static file
    • dynamic - content is always rendered at the time of page view
    • hourly, daily, weekly - static, but republished on intervals
  • Navigation Type (navtype) - how the content is linked in site navigation
    • page (object shows in menus)
    • item (object shows in indexes/listings)
    • none (object cannot be navigated to)
  • Display Type (displaytype) - what the object looks like when viewed directly
    • raw (object is displayed directly)
    • formatted (object is built using a format with merge codes)
    • template (object is used as a complete HTML document template)
    • none (object is not displayed)

These behaviours can be configured without even needing a special model class, in principle.

The model is extensible using metadata and flags, which can be defined in your configuration files, using settings like:

content.metadata.TYPE.METANAME.datatype = string

content.metadata.TYPE.METANAME.help = some tooltip text

content.flags.TYPE += flag_name

View (content appearance)

The public view of the content is generated by the class' show() method. Overload this if you need specialized views.

If necessary, you can define alternative admin views using a preview() method.

Most views can be auto-generated using formats, which are template-like snippets of HTML with merge codes. Set the display type to formatted, and define a format with the content type name in the configurations under content.format... For example, content.format.article will automatically be used to format article views, if defined. Summary views (eg. for indexes) will automatically be formatted in a similar way if a format like article_summary is found (replace article with the appropriate content type).

Formats can include other formats to share/inherit common formats or layouts. The following merge codes will pull in other formats:

[ [.foo] ] - find and insert $config{content}{format}{foo}

[ [>foo] ] - find and insert a format named "foo" using ExSite::Content::find (will find foo in a template or library)

[ [>>foo] ] - find and insert a format named "foo" using ExSite::Content::find_in_path (will inherit foo from a parent)

The last two methods allow you to manage your formats using the CMS.

Controller (content management)

The Modules::Content plugin provides a useful base class for content management controllers and plug-ins.  Use it instead of Modules::BaseDCD for plugins that manage content classes.

Modules::Content classes have a few standard query parameters that are assumed.

  • id - the ID of a content object
  • cmd - the control panel function being invoked. The following commands/functions are predefined: conf, edit, rollback, todo, img, price, contact, translate, publish, unpublish, copy, del.

Modules::Content provides the following methods for superclasses that inherit it:

  • write($id) - outputs content object $id. This provides a simple method for embedding or aliasing content in other parts of the site. Note that you do not normally need a special write() method for content, since the content’s show() method should automatically generate its own view. Plugin write() methods are used for irregular or aggregated views that are not normally generated by the object itself. For example, a blog automatically generates its own index and other views, but if you have several blogs on a system, you might need an aggregated view such as “recent articles” across all blogs. Similarly, you don’t normally need service pages for content, since every content object has its own natural URL.
  • pathbar($c,%opt) - output a PathBar widget to show where you are in admin control panels. $c is the object you are working on. $opt{section_id} suppresses the inclusion of ancestral objects above the specified section number. $opt{linktypes} provides a regular expression of the content subtypes that should be linked from the pathbar.
  • configure($c) - creates and processes a form to reconfigure the content object $c, including content parameters, metadata, and flags.
  • update($c) - creates and processes a form to revise the content object $c using the HTML editor.
  • rollback($c) - rolls the latest revision back, and republishes the content object $c.
  • delete($c) - unpublishes and deletes the content object $c.
  • copy($c) - copies the content object $c, and redirects the admin to the configuration screen for the new object.
  • pricing($c) - displays tools to manage the pricing of content object $c.
  • order($c) - displays tool to manage the sort order of the contents of $c.
  • translate($c) - displays tools to manage the translations of $c.
  • publish($c), unpublish($c), archive($c), approve($c), queue($c), unqueue($c), expire($c), reject($c) - change the workflow status of content $c

Ancestor Inheritance

In addition to class inheritance, objects can inherit definitions from their ancestors.

As noted above, formats can include sub-formats from their ancestors using merge codes like [[>>foo]].

Metadata definitions are normally common to all objects of a given type, but you can make them context specific (ie. inherited from ancestors) if desired. Allowed metadata are normally defined as follows:

content.metadata.product.option_color.datatype = string
content.metadata.product.option_size.datatype = string

This defines option_color and option_size as possible options for any product. Say that one particular category also has an additional option (option_hand, ie. left or right) but you don't want that option to appear under every product in the system, just in this one category. If the category ID is XXX, then you can add the context-specific option as follows:

content.metadata.XXX.product.option_hand.datatype = string

Then any product under content ID XXX will get that option as well. Because this can involve extra lookups, which impacts performance, enable contextual metadata with the config setting

content.contextual_metadata = 1

You can also use settings in a similar way, making them apply only within certain sections or container objects.