Creating custom content types
In this section, we create a new content type based on an existing one, via the Zope Management Interface. We add and customise a workflow for the new type, and change the Plone UI to accommodate it.
Our current way of doing press releases have a number of drawbacks. They lack a capsule bio of the company, and they act identically to news items, e.g. sharing the same workflow (while press releases might need to be reviewed by someone from the press office instead of a line manager). In order to refine our press releases, we should create a new content type to accommodate them.
For a case such as this, where the new type has a lot in common with an existing one, it's easiest to create it by starting from the existing type. Plone provides two ways of doing this TTW.
As the manager user, go to the Plone Setup page, and from there to the ZMI. Information about the content types available in a Plone instance is controlled by the portal_types tool, so go there. You'll see a list of the existing content types, which you can browse to configure and learn more about each type. From this tool's Add dropdown, you can also create new content types.
An FTI instance closely mimics an existing type, piggy-backing on the same product and factory methods. Create a new one called "Press Release", selecting "CMFDefault: News Item" as default type information.
On the new type's Properties page you'll find the following properties:
Press Release FTI Properties
Short documentation explaining the purpose of the type, appearing to the end-user in the Plone UI, e.g.
The icon image associated with objects of this type. The image is found by acquisition. The natural place for it is in a layer of the portal_skins tool.
- Product meta type
The class name of instances of this type. Instances are cataloged under this name, so change it to "Press Release" in order to distinguish our new type.
- Product name
This is the name of product that constructs instances of this type. We're using an existing product for our type, so don't change this.
- Product factory method
This one goes hand in hand with the former, identifying the method of the abovementioned product to be used. Leave as is.
- Inititial view name
The template used as the default view of instances of our type. metadata_edit_form is generic, so leave as is for now.
- Implicitly addable
This controls whether the new type is offered for adding in a member's Add dropdown.
- Filter content types?
This property and the next one belongs together. If our new type is folderish (e.g. if we based it on the Folder type), we can optionally filter the types it offers to add inside it.
- Allowed content types
If we choose filtering, this list defines the filter. For press releases, these properties are irrelevant.
- Allow Discussion?
Most Plone content types can support threaded conversations managed by the portal_discussion tool. Whether this functionality is offered can be configured globally, but it can also be configured per type. This setting determines the default value for this type.
Once we're done, the properties look like this:
Members can now start adding press releases, using forms and views borrowed from news items, but these will contain text referring to news, which is confusing. To change this, we'll have to provide custom templates for our new type.
When encountering the Plone UI, we took note of the various categories of actions offered to the Plone user, and noted that they come from the portal_actions tool. While this tool defines a number of global actions, it also has a list of action providers from which to fetch actions. Together, the global actions and the actions drawn together from all the action providers form the total range of actions available to the Plone user. All Plone content types are action providers, and our Press Release is no exception. The view and edit templates are actions in the object category.
We configure the templates on the Actions tab of our type. Change the view and edit actions to refer to pressrelease_view and pressrelease_edit_form respectively:
These templates don't exist yet, so at this point attempts to add press releases will be frustrated by 404 (not found) errors. Practically all aspects of the Plone UI is provided by the portal_skins tool, so that's where we need to supply these templates. Since the press release templates differ from those of news items only in wording, we can derive our templates from those. Here's what we do:
find the news item templates (look on the filesystem, or use the ZMI Find tab at .../plone/manage_main) (don't miss plone_form_scripts/newsitem_edit!),
browse to the original templates in the ZMI and click on the Customize button (accepting the default destination custom),
rename the copies:
edit them to remove references to news. The newsitem_view template has no user-visible references to news, but we can add the company information. Adding the information to the template has a couple of advantages: it doesn't get indexed as content, it isn't stored once per instance, and it only needs to be updated in one place.
Here are just the differences in the form (I'll leave the script to you):
Before: <p i18n:translate="description_edit_news_item"> A news item is a small piece of news that is published on the front page. Add the relevant details below, and press 'Save'. </p> After: <p i18n:translate="description_edit_pressrelease_item"> A press release is a statement released to the media. All releases are available on a dedicated page. Add the relevant details below, and press 'Save'. </p> Before: <legend i18n:translate="legend_newsitem_details">News Item Details</legend> After: <legend i18n:translate="legend_pressrelease_details">Press Release Details</legend> Before: <div class="formHelp" i18n:translate="help_description_news"> Displayed on the news page along with the headline. After: <div class="formHelp" i18n:translate="help_description_pressrelease"> Displayed on the press page along with the headline.
Besides the descriptive text, the i18n:translate attributes have also changed. These values are the message ids used to look up translations from the internationalisation catalogs (we'll come to them later). If no translation is found, the text supplied in the template will be used.
How did I find newsitem_edit?
Either by doing find Product/CMFPlone -name "newsitem*" on the filesystem, or by presciently doing an advanced find, like this:
That takes care of the textual changes. There's more to the form and the script, though. You may have noticed that they aren't a regular Page Template and Script pair: they are a Controller Page Template and a Controller Python Script, both with two tabs --- Validation and Actions --- that regular templates and scripts don't have, and that integrate them with Plone's form submission machinery. Update these tabs, with the original forms' settings as example (unfortunately the original settings don't come along when the objects are copied to the custom folder. Apparently this has been fixed in CVS in the meantime).
In order to put press releases through a different approval process than news items, we need to change workflow accommodate this. Designing a good workflow that is as simple as possible and fits the business process is a bit of an art, and there are various possible approaches. In the example that follows, we'll create a new workflow for press releases. An alternative approach would be to add states and transitions to the default Plone workflow. I also split the responsibility for reviewing between the Reviewer role and a new PressReviewer role which has sole responsibility for reviewing press releases. Alternatively, one could require that a press release undergoes the review from the press office in addition to the current review.
All the approaches have their pros and cons. It's worth trying out different ones and getting a feel for how they work in practice. Plone's workflow component perhaps looks deceptively simple: it can play a huge role in application design.
We'll take the default workflow as starting point, so let's start by copying it:
On the Workflows tab, make sure that Press Release is associated with the new workflow:
The only change that we'll make to the workflow, is to add the requirement of the PressReviewer role, and to reflect this requirement in the titles of the states and transitions:
Don't forget to add the role guard to the worklists:
In parallel with this, we should change plone_workflow to require the Reviewer role in addition to the Review portal content permission, since the role is what distinguishes the press reviewers from other reviewers.
We should add the PressReviewer role. As the Groups Overview in the Plone Setup area states: "if you want to add a new role, you must use the Zope Management Interface, as adding roles is considered a development task." If we were adding a new content type as a Python product we could define new permissions for press releases, but as we're working through the web, add a new role (on the Security tab of the Plone site) and assign it all the same permissions as the Reviewer role.
To make use of the new role in Plone, add a group with the new role, and create a member for this group:
The new workflow is now ready for use. Members can add and submit both news and press releases to be approved for publication by different groups. As news and press releases are now distinct types, they don't share the same page anymore.
To provide a page on the site for press releases, let's add a Press Releases tab and customize the news template.
Find the news template at plone/portal_skins/plone_templates/news, customize it to custom, and, once there, rename it to press. I'm changing only two things. The catalog query changes:
tal:define="results python:container.portal_catalog( portal_type='Press Release', sort_on='Date', sort_order='reverse', review_state='published');
And the text (including the message id) for the absence of press releases changes:
<p tal:condition="not: results" i18n:translate="no_new_pressreleases"> No press releases have been posted. </p>
Browse to the portal_actions tool in the ZMI and follow the example of the News tab:
In order to position the new action right after News, select all the actions between it and news, and Move down.
Now the new tab is available: