collective.subtractiveworkflow on Plone 4
Do you remember the DCWorkflow's hidden gems?
I updated collective.subtractiveworkflow from Martin Aspeli to work on Plone 4.
With DCWorkflow, you can have several workflows on a content type, and with collective.subtractiveworkflow, you can have the second workflow to be subtractive of the first one. The state_variable of the second workflow needs to be different from the first one of course.
I used it on a project. I have a Procedure content type that is confidential by default. In my case, confidential means that users with only the Member role can't see the content. The authenticated user can only see the content if he has one of the following roles: Reader, Editor, Contributor, Manager, Owner.
The workflow chain for Procedure is set to: quality_workflow, confidential_workflow
In the quality_workflow, with state_variable="review_state", the View permission is set to: (not acquire) Reader, Editor, Contributor, Manager, Owner, Member
And in the confidential_workflow, a "Subtractive Workflow", with state_variable="confidential_state", the View permission is set to: (not acquire) Member
So quality_workflow - confidential_workflow equals: (not acquire) Reader, Editor, Contributor, Manager, Owner
Creating the workflows with ArchGenXML
I added the meta_type and state_var tagged-values to archgenxml 2.5 I released some days ago. So if you want to model a subtractive workflow you set on your states-transitions diagram meta_type="Subtractive Workflow" and state_var="confidential_state". But you have to model the two workflows on a abstract class, and don't set the use_workflow tagged-value on the concrete class. You have to define the binding manually in profiles/default/workflows.xml like this:
<object name="portal_workflow" meta_type="Plone Workflow Tool"> <object name="quality_workflow" meta_type="Workflow"/> <object name="confidential_workflow" meta_type="Subtractive Workflow"/> <bindings> <!-- ##code-section workflowbindings --> <type type_id="Procedure"> <bound-workflow workflow_id="quality_workflow" /> <bound-workflow workflow_id="confidential_workflow" /> </type> <!-- ##/code-section workflowbindings --> </bindings> </object>
Show both states in Plone UI
By default on Plone UI, you only see the state of the first workflow and see the transitions of both workflows. To show both states, you can customize the workflow menu by registering a more specific WorkflowSubMenuItem, i.e. register it for IDefaultBrowserLayer for example. I develop with five.grok, so here an example on how to customize the workflow menu to show both states separated with comma:
from five import grok from plone.app.contentmenu import menu, interfaces from plone.memoize.instance import memoize from zope.i18n import translate from zope.interface import Interface from zope.publisher.interfaces.browser import IDefaultBrowserLayer class WorkflowSubMenuItem(grok.MultiAdapter, menu.WorkflowSubMenuItem): grok.adapts(Interface, IDefaultBrowserLayer) grok.name('plone.contentmenu.workflow') grok.provides(interfaces.IContentMenuItem) @memoize def _currentStateTitle(self): wtool = self.tools.workflow() workflows = wtool.getWorkflowsFor(self.context) titles =  if workflows: for w in workflows: state = wtool.getInfoFor(self.context, w.state_var, None) if state in w.states: title = w.states[state].title or state titles.append(translate(title, domain="plone", context=self.request)) return u", ".join(titles)