In v4 there are multiple mechanisms for inheriting behaviours from related objects and classes.
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:
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
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.
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.
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 $cIn 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.