THEMES MANAGEMENT

Author: Georges Racinet

Contents

This document explains how to make themes available to CPS (Storage section) and how to hook themes or pages in a given context (Negociation section).

1   Storage

A theme is pretty much a static website, the only difference being that html files are being written with special attributes to control inclusion of dynamical content.

As in a static web site, you may define several pages, typically toplevel html files, that will share the same resources (stylesheets, images, etc.)

1.1   Generalities about Theme Containers

The system is designed so that several options for themes storage and retrieval can be used. These are represented as Theme Container objects, that should in principle be configured in ZMI.

There is currently only one kind of theme container, the Filesystem Theme Containers, described below, and only one container object in a CPS portal : the .cps_themes object at the root of the portal.

The planned evolution of theme containers includes ZODB storage of themes and support for local theme containers, with local management rights, zip upload of themes or downloads from an external web site.

1.2   Filesystem Theme Containers

With this type of container, themes are simply directories on the server file system. These are in turn all placed in the same themes directory. The path to this themes directory can be configured in ZMI, on the Filesystem Them Container Object (currently, .cps_themes, at the root of portal). This path is relative to the Zope instance directory, for security reasons, but symbolic links are followed, so that the system administrator can actually put the themes directory anywhere and make a link in the Zope instance.

A good news is that Mercurial knows how to deal with symbolink links (on all systems, not just Unices) and it's thus very easy and practical to have in a product's theme container a symlink to the CPSDefault/themes/default theme.

If you have a ZEO setup, then the themes should be deployed on all clients machines. The themes directory can be shared among instances on the same server, e.g., by using symbolic links.

Naming conventions:

  • A theme name is the name of the corresponding directory on the file system.
  • A page name corresponds to a file in the theme directory, with the html extension.

Example: the Front page of the default theme shipping with CPSDefault is located in <THEMES_DIRECTORY>/cps3_4/Front.html

Default theme and page:

These can be configured in ZMI on the Filesystem Theme Container object. They get applied in case the negociation (see below) doesn't prescribe anything. See the example at the end of the Negociation section.

2   Negociation

Negociation is the process of deciding which theme and page should be applied on the current request.

In CPSDesignerThemes, the negociation is flexible and can be changed through the Zope Component architecture. See at the end of this section to learn how.

2.1   The standard (CPSSkins) negociator

We describe here shortly the standard negociator that ships with CPSDesignerThemes : the CPSSkins Theme Negociator. As the name suggests, this negociator is designed to be strictly compatible with the negociation logic implemented in CPSSkins, the theme engine that has been the standard system up to CPS 3.4.x series, except of course that theme and page names must be taken in the sense of CPSDesignerThemes : with the Filesystem Themes Container (currently the only available option), themes are toplevel file system folders inside the area specified in the root container object (.cps_themes at the root of your portal).

TODO EXPAND CPSSkins part from CPSSkins doc.

Note: for local bindings, the official property or script name
for this negociator is .cps_themes_bindings instead of CPSSkins' .cpsskins_theme. However the latter is recognized if and only if the former is not present.

Besides reimplementing the logic described in CPSSkins documentation, this negociator adds the possibility to specify local method themes. These bind the method used for publication (e.g, index_html, folder_view, folder_contents...) to the theme and page, as in:

folver_view:0-3:default+Front

This means "if the current method is folder_view, from this folder and down to 3 levels below (inclusive), apply the Front page of default themes.

This is in particular how CPSSkins' global method themes are to be translated into CPSDesigner ones. There's an upgrade step for that.

2.2   Example: CPSDefault setup

The .cps_themes_bindings property has exactly one rule:

index_html:0-0:default+Front

Here's the root container object (.cps_themes) configuration:

path:
Products/CPSDefault/themes
default theme:
default
default page:
index

On the portal front page, which is internally equivalent to <portal_url>/index_html, the negociation rule says to use the Front page of default theme, ie, Products/CPSDefault/themes/default/Front.html.

In all other cases, the negociator doesn't prescribe anything, therefor the index page of default theme is used, and this is resolved as Products/CPSDefault/themes/default/index.html by the container object.

2.3   The Cherry Picking negociator

This negociator is deprecated. It had been introduced mainly to support local method themes. Although deprecated, it is currently the only builtin negociator that can bind a theme or page to a non-folderish document.

Check the docstring of Products.CPSDesignerThemes.negociator for more detail.

2.4   Changing the negociator

Negociators are actually adapters in the sense of the Zope Component Architecture. They adapt context and request to a theme engine. For instance, to use the Cherry Picking negociator, put the following in your Product's overrides.zcml:

<adapter
    provides="Products.CPSDesignerThemes.interfaces.IThemeEngine"
    for="OFS.interfaces.IObjectManager
         zope.publisher.interfaces.http.IHTTPRequest"
    factory="Products.CPSDesignerThemes.negociator.CherryPickingCPSSkinsThemeNegociator"
    />

You can of course use the same principle to hook your own custom negociator, or one that's been written by a third party.

2.5   Writing a custom negociator

Assuming using the root themes container only is enough for you, we strongly suggest to subclass Products.CPSDesignerThemes.negociator.EngineAdapter and override the getThemeAndPageName method.