You are not logged in Log in Join
You are here: Home » Download Zope Products » Content Management Framework » CMF Documentation » Developing for CMF » Taming the Wild Types Tool » View Document

Log in
Name

Password

 

Taming the Wild Types Tool

A fairly young addition to the PTK / CMF architecture, the 'portal_types' tool plays several important roles. Understanding these roles is a key piece of zen for CMF developers and site builders.

Taming the Wild Types Tool

Overview

A fairly young addition to the PTK / CMF architecture, the portal_types tool plays several important roles. Understanding these roles is a key piece of zen for CMF developers and site builders.

Roles of the Types Tool and TypeInformationObjects

Object Construction

Initially, the types tool was conceived as a simplified replacement for the "Wizards" folder of the "classic" PTK. Wizards were typically multi-page forms, which collected metadata and content from the user in order to construct a content object, or a folder. Separating the logic for constructing an object (into a Wizard, distinct from the object's class) from the logic used to edit it (typically, in the class itself), made for poor maintainability. In addition, the Wizards had to be distributed as through-the-web objects, which made updates to PTK/CMF-based sites quite painful.

The original versions of the type information objects stored in the types tool contained little more than the properties needed to construct an instance through a simple, polymorphic interface.

Having created a registry of "addable content types" for a CMF Site, other roles began quickly to accrete.

Skinning Content UI

Having successfully "skinned" the portal-wide UI components via the creation of the portal_skins tool, we wanted very much to allow site builders and application developers to customize the UI components for specific content objects, as well. The type information objects turned out to be logical containers for the mappings between logical "actions" and the skin methods which enact them.

Holding Site-Specific Policies

Embedding policy decisions about content objects in their classes makes such content objects hard to reuse; sites whose policies (discussability, for instance, or allowed contents) are forced to subclass to override such policies, and may not be successful, at that. Type information objects make excellent "policy configuration points" for such choices.

Customizing Content Behavior in Instance Space

Because more than one type information object can "point" to the same underlying class, while imparting different construction semantics, UI, and policy settings, type information objects allow the site builder to leverage CMF content objects for multiple purposes.

Interfaces

portal_types Interface

Objects implementing this interface serve as the central registry for content type information in a CMF site.

API:

        # getType__roles__ = None  # Public
        def getTypeInfo( self, contentType ):
            """
                Return an instance which implements the
                ContentTypeInformation interface, corresponding
                to the specified 'contentType'.
            """

        # listTypeInfo__roles__ = None  # Public
        def listTypeInfo( self, container=None ):
            """
                Return a sequence of instances which implement
                the ContentTypeInformation interface, one for
                each content type regisetered in the portal.  If
                the container is specified, the list will be
                filtered according to the user's permissions.
            """

        def constructContent( self, contentType, container, id ):
            """
                Build an instance of the appropriate content
                class in 'container', using 'id'.
            """

ContentTypeInformation Interface

Objects implementing this interface function as factories and configuration points for the classes they wrap.

API:

          def Metatype( self ):
              """
                  Return the Zope 'meta_type' for this content
                  object.
              """

          def Type( self ):
              """
                  Return the "human readable" type name (note
                  that it may not map exactly to the 'meta_type',
                  e.g., for l10n/i18n or where a single content
                  class is being used twice, under different
                  names.
              """

          def Description( self ):
              """
                  Textual description of the class of objects
                  (intended for display in a "constructor list").
              """

          def isConstructionAllowed( self, container ):
              """
                  Does the user have the permission to construct
                  an instance of this type in 'container'?
              """

          def allowType( self, contentType ):
              """
                  Can objects of 'contentType' be added to
                  containers whose type object we are?
              """

          def constructInstance( self, container, id ):
              """
                  Build a "bare" instance of the appropriate type
                  in 'container', using 'id' as its id.  Return
                  the URL of its "immediate" view (typically the
                  metadata form).
              """

          def allowDiscussion( self ):
              """
                  Can this type of object support discussion?
              """

          def getActionById( self, id ):
              """
                  Return the URL of the action whose ID is id.
              """

          def getIcon(self):
              """
                  Returns the portal-relative icon for this type.
              """

Implementations

TypesTool

In addition to implementing the portal_types interface, instances of this type are ObjectManagers: they hold type information objects, as well as "helper" objects (e.g. Python Scripts). They provide a UI for adding new type information objects, and support for populating these objects with default values registered by Zope products (see "Implementing the factory_type_information Protocol", below).

TypeInformation (base class)

This class implements a shared portion of the ContentTypeInformation interface (those portions not dealing with object construction):

  • Action list bindings and UI
  • Policy configuration
  • Metadata about the type itself.

TypeInformation objects have several shared properties:

  • title Human-readable "type name".
  • description Fuller description, used in selection UIs.
  • content_meta_type What is the underlying Zope meta_type for objects of this type?
  • icon What icon should we show for objects of this type?
  • immediate_view -- After construction, what method should we show first?
  • filter_content_types/allowed_content_types -- If folderish, do objects of this type limit their contents to specific types?
  • allow_discussion -- Do objects of this type allow discussion?

FactoryTypeInformation (FTI)

This class implements the object construction portion of the ContentTypeInformation interface by invoking Zope's product-dispatcher/factory-dispatcher mechanism directly. These type objects are simplest to configure, and provide the easiest path to integrating content objects supplied "directly" by Zope products.

FTI objects have two unique properties:

product
the name of the Zope product which holds the class and factory methods for the objects of this type.
factory
the name of the factory method (not the Zope "factory object" created for ZClasses!) which creates instances of the class. Notes:
  • This should be a "direct" method, not a form.
  • The user must have permission to invoke the method in the current location, according to the Zope security policy.
  • The method will be called, effectively as though invoked so:
                  manage_addProduct[ product ].factory( id )
    

Note that additional positional and keyword arguments might be passed, if the invoking method supplies them.

ScriptableTypeInformation (STI)

This class implements the object construction portion of the ContentTypeInformation interface by invoking a user-supplied method (typically a PythonScript). Somewhat more difficult to set up than FTI objects, these type objects provide for more flexible object creation, e.g.:

  • Populate default metadata for the type.
  • Supply default content for the type.
  • Configure multiple objects, e.g., a folder with one or more content objects.

STI objects have two unique properties:

permission
the permission which protects their constructor method / script.
constructor_path
a traversable path to the method or script to be called to construct an instance. This method must accept at least two arguments (container and id), and must return an instance, already added to container, and wrapped in it.

See also How-to: Using Scriptable Type Information type objects

Usage Scenarios

This section describes several kinds of customizations which the types tool facilitates.

Adding / Removing Content Types

Unlike Zope products, whose factories show up "automagically" in the "Add..." list after product installation, CMF sites require explicit configuration to enable new product types. Likewise, a particular CMF site may suppress the creation of certain content types, merely by removing its type information object.

Creating "News-Only" Folders

Suppose you need to restrict the items created under your site's /news folder to be only NewsItems? Create a new type object, using CMFDefault/Folder as your starting point, and then check the 'Filter content types?" checkbox and select only "NewsItem" in the Allowed content types list.

Internationalizing Action URLs

Change the Name property of each action on a type object's Actions tab to internationalize the label which shows up in the 'actions_box'; change the Action property to select an internationalized skin method.

Binding Customized UI

Create custom skin methods for your objects, and bind them using the Actions tab (skin methods which reuse the names of the objects' existing actions don't need any re-binding).

TBD

Developer Docs

  • factory_type_information protocol
  • Using ZClasses as content

Futures

  • Type objects + contained methods --> "local" ZClasses?