CPSWorkflow
How to set up workflows using CPSWorkflow


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Date

15/06/2005

Version

0.1

Authors

Anahide TCHERTCHIAN, software developer <at@nuxeo.com> Florent Guillaume <fg@nuxeo.com>

Contributors Julien Anguenot <ja@nuxeo.com> Summary This is a technical document describing how to setup workflows using CPSWorkflow. Nuxeo

Company

Email

contact@nuxeo.com

Web

http://www.nuxeo.com

Rights

Copyright © 2005 Nuxeo This book is free. You may use the information in this book for any purpose, commercial or otherwise, without fee or obligation of any kind. Furthermore, permission is granted to copy, distribute, and/or modify this book under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation (http://www.gnu.org/copyleft/fdl.html); with Front Cover Text «CPSWorkflow HowTo», with Back Cover Text « You have the right to copy and/or modify this book, like for all free software and free documentation produced by the Nuxeo company » and with Invariant Section « Links, references and contacts ».

Licence

Nuxeo © 2005

2/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Table of Contents
1 Introduction.....................................................................................................................................5 2 Workflow concepts.........................................................................................................................6
What is a workflow?.....................................................................................................................................6 The CPSWorkflow concept..........................................................................................................................6 Workflow Items............................................................................................................................................6
Workflow definition..................................................................................................................................................7 States.......................................................................................................................................................................7 Transitions...............................................................................................................................................................7 Variables..................................................................................................................................................................8 Scripts......................................................................................................................................................................8 Stacks......................................................................................................................................................................9

Placeful workflow configuration...................................................................................................................9

3 Workflow sample..........................................................................................................................10
Introduction to a publication workflow.......................................................................................................10 Basic publication workflow.........................................................................................................................11
Creating a new workflow in the Zope Management Interface (ZMI).....................................................................11 Adding states.........................................................................................................................................................13 Adding transitions..................................................................................................................................................13

Templates and scripts................................................................................................................................16 Complete workflow with collaborative validation.......................................................................................17
Introduction to the collaborative process..............................................................................................................17 Adding a local role.................................................................................................................................................18 Adding a stack definition to a state.......................................................................................................................18 Adding transitions to manipulate the stack...........................................................................................................20

Using the newly created workflow.............................................................................................................23
Create a new portal type or use an existing one..................................................................................................23 Set up the appropriate workflow chain in sections................................................................................................23 Try out the new workflow.......................................................................................................................................23

4 Appendix......................................................................................................................................25
Workflow tool..............................................................................................................................................25 Workflow definition.....................................................................................................................................25
Workflow installer..................................................................................................................................................25 Placeful workflow configuration.............................................................................................................................25

State definition...........................................................................................................................................26
State behaviours....................................................................................................................................................26

Transition definition....................................................................................................................................26
Transition behaviours............................................................................................................................................26

Workflow expressions................................................................................................................................27
The available namespace.....................................................................................................................................27 The state change object........................................................................................................................................27

Stacks related definitions...........................................................................................................................28
Stack definition......................................................................................................................................................28 Stack......................................................................................................................................................................28 Stack element........................................................................................................................................................29

Defining new stacks...................................................................................................................................29
Stack definition registry.........................................................................................................................................29 Stack registry.........................................................................................................................................................29 Stack element registry...........................................................................................................................................30

Nuxeo © 2005

3/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

5 Links, references and contacts....................................................................................................31
About CPS.................................................................................................................................................31 About Nuxeo..............................................................................................................................................31 About Zope.................................................................................................................................................31

Nuxeo © 2005

4/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

1 Introduction
The purpose of this documentation is to explain how to setup workflows using CPSWorkflow. CPSWorkflow is an extension of the DCWorkflow product, providing some additional features that will be explained in this document. CPSWorkflow is a CPS core component that can be used as well within a CMF or CMFPlone instance, even if some features are not available outside of CPS. Concepts and terms used about workflows will be presented in the first chapter, and a sample workflow will be detailed in the second chapter. The appendix gives additional technical information about workflows implementation. This documentation comes with a Zope product called CPSWorkflowHowTo, available at: http://svn.nuxeo.org/trac/pub/browser/CPSWorkflowHowTo

Nuxeo © 2005

5/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

2 Workflow concepts
What is a workflow?
A workflow is useful to manage business processes: it allows to define and follow the flow of actions performed by users or other entities. This is a generic definition. When applied to content management applications, other words can light up this definition: a document follows a process, users perform actions they are authorized to perform on this document, and all these actions are tracked in the document workflow history.

The CPSWorkflow concept
The CPSWorkflow product follows the DCWorkflow assumptions: workflows are assigned to document types, not to some given documents. In CPSWorkflow, local workflow chains are placeful. a single document in the system represents the process followed. workflow actors are identified by the roles/permissions they owe. These assumptions put constraints on the way workflows can be defined and customized, even if you can sometimes circumvent these rules. Every document in CPS workspaces and sections follows a workflow, except configuration files. Workflows control all the operations of a site, and all the security checks.

Workflow Items
Workflows are mainly defined by their states and transitions. From this point of view, they can be seen as a deterministic finite-state automata. A document moves from a state to another executing transitions. Some transitions do not have any initial state (initial transitions), they are used at creation time. Some transitions do not have any destination state, they are used as "remain in state" transitions: when executed, the document remains in the state it was already in. Several transitions can have the same initial state, and several transitions can also have the same destination state. By convention, state names are nouns, and transition names are verbs. The set of states and transitions is usually used to represent the document life cycle. Other items, variables, are used to keep track of additional information, like the date and the actor of the last transition. Furthermore, some scripts can be executed just before or after a transition to perform additional actions. Finally, stacks holding users/groups can be defined on states, and manipulated through workflow transitions, allowing to set local roles dynamically on the document. The following sections give an overview about each of these items.

Nuxeo © 2005

6/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Workflow definition
A workflow is mainly characterized by its set of states and transitions, its variables, and the list of permissions managed. Scripts are involved in transitions, and stacks are involved in states and transitions, so they will be introduced later on. Worklists and groups are DCWorkflow features that are not used in CPS workflows even if they are fully functional.

States
States are mainly defined by the list of transitions that can be performed when the document is in that state, and a mapping of permissions to roles for that state. This is static information: when the document is in that state, the given configuration will apply. For instance, if the "View" permission is only mapped to the "Manager" role, only users who are managers will be able to see the document. The state can only define mappings for permissions controlled by the workflow, and defined at the workflow level. The state does not handle permissions/roles applying to its transitions, it only gives the list of transitions that make sense from that state. Each transition will then control who can perform it. Additional information about variables, and groups can be given. Variables are defined at the workflow level, but when moving to a given state, they can be updated using a particular value. Groups are not used in CPS workflows. Stack definitions and state behaviours referring to stacks can also be set up on a state. This will be detailed in the stacks section.

Transitions
Transitions are mainly defined by their destination state, the transition type, and the guard used to filter users that will be able to perform the transition. Workflow scripts can be executed just before or after the transition, and an associated action to display on the site is also defined on the transition. Variables are defined at the workflow level, but when performing a given transition, they can be updated using a particular value. Additional features are provided with CPSWorkflow transition flags.

The destination state is either one of the states of the workflow, either a loop over the state ("remain in state" transition). In the second case, the same transition can be used on different states. More generally, it is possible to reuse the same transition on different parts of the workflow, since the source state is not defined in the transition but managed by the state.

Nuxeo © 2005

7/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

The default transition type is "Initiated by user action": the transition execution is requested by the user, usually via a script in skins. Other options are "Automatic" and "Initiated by Workflow Method". The former is executed when a document moves to a state listing that automatic transition. The latter is never used in CPS workflows. The guard used to control in what situation the transition can be executed is a set of properties: permissions, roles, groups and a TALES expression can be used. In CPS workflows, roles are usually defined and groups are never used. These properties complete each other: for instance, if a transition guard sets roles and an expression, user will have to meet the two conditions to be able to perform the transition. Workflow scripts can be executed just before or after the transition. Most of the time, they are used to perform specific actions that cannot be taken by transitions with special flags. An optional action associated to the transition can be defined. Sometimes we do not want to display any message in an action box to make the transition possible, but most of the time we do. The action name, URL and category can then be defined. The action will not be displayed in the actions box if the transition guard fails for the authenticated user. Transition flags have three major purposes: Find special transitions: for instance it is helpful to look for transitions flagged as initial transitions, to know if a document with a given type can be created. Control subobjects allowed behaviours: a container is responsible of globally allowing certain behaviours for its subobjects. This covers creation, deletion, moving into the container, etc... Once a container allows certain operation, the workflow for the portal type itself will have to allow the operation too. Perform specific actions while executing the transition, for instance: freeze or delete the document, add users to a given stack, etc...

Variables
Variables are used to store information related to the workflow but that do not justify a state. Workflows usually use variables to store status history details (last transition performed, person who performed it and when, attached comments, etc...). Variables are defined thanks to their default expression, the way they're updated, access guards... Most of workflows will not need to change variables defined in default CPS workflows. Please note that stacks are stored as workflow variables: when a stack definition is added to a state, the corresponding variable is created.

Scripts
Scripts are useful to perform miscellaneous actions extending the workflow features. They are usually used in transitions, as before/after actions to be executed, and take an object called state_change as first parameter. state_change keeps information about the object current status and can also be used in transitions and stack guard expressions.

Nuxeo © 2005

8/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Stacks
Stacks can be seen as high-level variables. Stacks can store any kind of objects, but we usually use them to store members or groups since their main purpose is to provide dynamic, workflow-driven local roles distribution on the document. Imagine you would like to involve a set of users in a document process, controlling the permissions according to the document state, and other users actions/duties on the document. Stacks allow you to set local roles dynamically, using a set of parameters as: the document state, the document itself, the user's location in the stack, etc... Two basic kind of stacks are implemented in CPSWorkflow, but it is easy to define new kinds of stacks. These basic stacks are a simple stack, and a hierarchical stack. A simple stack is a list while a hierarchical stack has a level notion to take care of the hierarchy between users/groups held in the stack. The stack definition is given at the state level, it is used when creating and manipulating the actual stack object, by providing high-level accessors or mutators on it. The state allows the existence and manipulation of a stack, and defines what actions can be performed on a given stack (for instance: add users, remove users, reset the stack, change the current level in the case of a hierarchical stack,...). Transitions are also involved because actions on stacks can only be performed executing transitions that allow them. A different definition of a stack can be given for another state of the workflow. A state can hold several stacks, and can make the distinction between actions that are allowed for a given stack, and forbidden for others. A transition can also make the difference between several stacks, allowing to add users only to a given stack, for instance.

Placeful workflow configuration
Workflow configuration is placeful in CPS: we can decide that for a given subtree, a given portal type will follow a given workflow. A placeful (local) workflow is used for instance to have a subtree dedicated to public content where objects must pass through a reviewing process (sections), and another subtree where the objects can be created and worked upon easily by the members (workspaces).

Nuxeo © 2005

9/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

3 Workflow sample
Maybe you would appreciate a workflow sample to light up all these definitions. Default CPS workflows already give examples of complex publication processes. We will create a new workflow, adapting the default publication workflow, and turning it into a collaborative validation workflow. You can follow the steps involved in the creation of this workflow in the following sections, or install the CPSWorkflowHowTo product, execute its installer, and look at the workflow definition while reading the documentation. You can also take example on this product to see how to create properly new workflows.

Introduction to a publication workflow
Defining a workflow always starts by drawing a picture. Here is the picture of our simple workflow, representing its states and transitions.

Let's describe this workflow usage from a CPS point of view. This is a publication workflow, happening in sections in CPS. The document exists, it has been created in a workspace and follows a workspaces specific workflow. When trying to publish the document, a new document (actually, a new revision of the document) is created in a selected section. This document follows a sections specific workflow. If the authenticated user has enough rights in the given section to publish the document, it is directly published. If he/she does not have enough rights, the new document moves to a pending state, where it will be approved or rejected by reviewers who have sufficient rights in the section to do so. Let's describe it from a more technical point of view. Two states and five transitions are involved in this process. The pending state ("Waiting for reviewer") and the published state ("Public") can be accessed via different transitions. The "None" state represented in a circle is not a real state, it is here to represent the virtual source state of initial transitions. There are two initial transitions, "Member request publishing" and "Member publishes directly". There is one transition to move from the pending state to the published state ("Reviewer accepts publishing") and two "remain in state" transitions, when validation fails or

Nuxeo © 2005

10/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

when publication is cancelled: "Reviewer rejects publishing" and "Reviewer removes content from publication". This is a simple workflow, although there are things to understand that do not appear clearly on the graph: When the new document is created, it is created from another existing document, following another workflow in workspaces. When publication is rejected, or when document is unpublished, document is actually deleted. Usually, you would define only one initial transition, flagged as an initial transition for creation of the document. When invoking the creation of the document, the workflow tool is queried and finds out what transition applies by looking for workflow(s) defined for the given document type in the given place (remember workflows are placeful) and looking for initial transitions for creation in the found workflow(s) ­ usually only one workflow, and only one initial transition for creation apply. Here we have two initial transitions, leading to two different states. They're not initial transitions for creation, but initial transitions for publication. The right transition will be executed according to the user's rights in the chosen section. It is possible to submit the document for publication because it follows a workspaces specific workflow that allows object "cloning" into other folders.

Basic publication workflow
Creating a new workflow in the Zope Management Interface (ZMI)
The easiest way to start defining this workflow is to copy/paste an existing workflow, so that variables are already set (standard variables will be used in this workflow). In the ZMI, go to portal_workflow, and click on the "Contents" tab to display the list of existing workflows. Our workflow is very similar to "section_content_wf", so you can copy/paste it and rename it "cps_validation_wf". Click on this new workflow, you will see a page looking like this:

Nuxeo © 2005

11/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

The "States" tab will display the available states in that workflow. You can click on it and delete all the states, we will recreate new ones later. You can do the same with transitions. Variables have to be kept, and we do not need any scripts neither. The permissions tab tells that four permissions are managed by this workflow: "Modify portal content", "View", "WebDAV Lock items" and "WebDAV Unlock items". You can delete WebDAV related permissions because we will not deal with them in the new workflow. Here is the list of existing variables, visible in the "Variables" tab:

All these variables are standard ones ; you can click on each of them to get more details about the way they are updated, for instance. You can see that most of involved expressions use the state_change object. This object is created when changing the document status, and stores information about changes in progress. You can see that comments and destination container are information passed as keywords when executing the transition. Let's add the missing states and transitions to this workflow.

Nuxeo © 2005

12/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Adding states
Go to the "States" tab, and add new states with ids "pending" and "published":

Click on the "pending" state, and add a title like "Waiting for reviewer". It is not possible to set transitions available from this state for the time being, because no transitions have been defined for this workflow yet (well, if you did delete them after copying). In the permissions tab, you will see the two permissions managed by the workflow. By default, permissions are inherited. We will define specific permissions for our pending state: unselect the permissions acquisition, and associate permissions to the following roles: View: Manager, SectionManager, SectionReviewer Modify portal content: Manager, SectionManager, SectionReviewer The role SectionReader is not involved here because we do not want section readers to see or edit documents that have not been validated by section reviewers. Click on the "published" state, and add a title like "Public". In the permissions tab, unselect the permissions acquisition, and associate them to roles as described below: View: Manager, SectionManager, SectionReviewer, SectionReader Modify portal content: Manager So section readers will be able to see published documents, and nobody's supposed to edit them: only a Manager of the site can modify them, but this is just a "rescue" permission setting.

Adding transitions
Now that states have been created, let's add the missing transitions. Go back to the workflow definition, and click on the "Transitions" tab.

Nuxeo © 2005

13/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Add a transition with id "publish", and then click on it. You can then set its title to "Member publishes directly", select the "published" state as destination state and keep the "initiated by user action" transition type set by default. Only the roles property of the transition guard will be used ; set it to "Manager; SectionManager; SectionReviewer": only people having one of these roles in the given section will be able to publish directly. Some transition flags are needed too: select "Initial transition for publishing", "Freeze object" and "Merge object with existing in same state". "Initial transition for publishing" will be helpful when looking for available transitions on submit. "Freeze object" and "Merge object with existing in same state" are needed to handle revisions of the document. Some knowledge about proxies and document repository is needed to understand what actually happens. The submission process consists of freezing the current revision of the document and creating a proxy to that revision in the section. Freezing the submitted revision is needed to ensure the submitted/published document could not be modified afterwards. If the working document happens to be modified, a new revision to work on will be automatically created. In other kinds of workflows, this wouldn't be needed. "Freeze object" freezes the revision as well as all the revisions pointed by the proxy (but usually only one revision is involved). This means that the document revision will not be modifiable again, and ensures that this revision is marked as to be lazily copied for any future modification. For instance, if the working copy in workspaces is modified, a new revision is created, and the published revision is not modified. "Merge object with existing in same state" is used so that there is only one published revision of a document. If the working copy of the document is edited (thus creating a new revision) and re-submitted, the published revision and the pending (newly created) revision are merged into the already-published proxy. A list of transition flags is given in the appendix, please refer to it to know what flags are needed and when.

Add the "submit" transition, with title "Member requests publishing" and destination state "pending". The guard role will be "Manager; Member" for this one, since everybody can submit a document in a section. NB: the list of sections where a document can be submitted is filtered so that user only sees sections where he/she has local roles (at least SectionReader): the situation where a document is submitted in an unreachable section will not happen in practice. Transition flags needed here are only "Initial transition for publishing" and "Freeze object". The "accept" transition takes "Reviewer accepts publishing" as title, "published" as destination state, "Manager; SectionManager; SectionReviewer" as guard roles, and the transition flag "Merge object with existing in same state". This transition will display an action in the actions box, with name "action_accept", URL "%(content_url)s/content_accept_form" and category "workflow". We will talk about templates involved in workflows in the next section.

Nuxeo © 2005

14/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

The "reject" transition takes "Reviewer rejects publishing" as title, does not have any destination state (this is a "remain in state" transition), "Manager; SectionManager; SectionReviewer" as guard roles, and the transition flag "Delete object": this revision of the document will be deleted if publication is rejected. The action displayed in the actions box is named "action_reject", its URL is "%(content_url)s/content_reject_form" and its category "workflow". The "unpublish" transition takes "Reviewer removes content from publication" as title, does not have any destination state (this is a "remain in state" transition), "Manager; SectionManager; SectionReviewer" as guard roles, and the transition flag "Delete object": this revision of the document will be deleted if publication is undone. The action displayed in the actions box is named "action_un_publish", its URL is "%(content_url)s/content_unpublish_form" and its category "workflow".

When all these transitions are created and configured, you should have the following transitions in your workflow:

Now that transitions have been created, it is possible to configure possible transitions in the states: select "accept" and "reject" for the "pending" state, and the "unpublish" transition for the "published" state.
Nuxeo © 2005 15/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

This new workflow is in fact very similar to the default "section_content_wf" workflow, but with fewer features: in particular, everything related to subobjects behaviours has been cleared out. It is fully functional because it reuses existing scripts and templates, already set up for CPS default workflows.

Templates and scripts
Let's have a look at the user-visible part of a workflow. While everything that is accepted by the workflow has been configured, it is time to take care of what users attempt to do. The workflow is invoked when creating documents and when executing transitions. The creation process can be seen as a special transition to execute since special queries are made to the workflow tool. These queries are made via ZPT templates and Python scripts. Please note that the scripts we are talking about in this section are skin scripts, not workflow scripts. There is usually no reason to change the way documents are created: the workflow tool is queried to get the list of creatable items in a given place of the site and detects if workflow followed by these content types has a transition flagged as an initial transition for creation. This transition is executed while invoking the document creation. Some transitions do not have any action to display in the actions box. This is true for initial transitions, but also for transitions allowing special behaviours, like subobjects behaviours: the workflow tool will ensure that a transition allows this behaviour before performing it. Transitions with actions in the action box are meant to be invoked by users. User clicks on the action in it actions box, a page is presented, giving some information, and asking for other information needed to perform the transition (typically, the actual transition to perform, comments attached to the state change, section(s) chosen for submission,...). Then user submits the form, and transition is executed in the script that is called. Note that if an action does not appear in the users actions box but if the user can see the document, it is still possible to display the transition form by typing it in the URL. But when submitting the form, the workflow will check that the user can perform the transition, and raise an exception if not. Although various templates are used in default CPS workflows, most of transitions are executed using the script: CPSDefault/skins/cps_default/content_status_modify.py. The important line in this script is:
wftool.doActionFor(context, workflow_action, **kw)

The workflow tool is asked to perform the "workflow_action" transition on the "context" object, using miscellaneous keywords (comments or relative path towards the submission section for instance).

Nuxeo © 2005

16/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

While executing this action, security checks will be performed, and before/after workflow scripts defined for this transition will also be executed. Any other automatic transition defined for the new state will be executed too. This script is the action given in all the forms we used to define the new workflow (content_accept_for, content_reject_form, etc...). The addition of the collaborative validation process in this workflow will lead us to define new scripts to perform some new transitions.

Complete workflow with collaborative validation
Introduction to the collaborative process
Let's spice up the reviewing process involving a collaborative validation process when document is in the pending state. When a document is submitted for publication, a section manager or a section reviewer decides not to accept or reject the document, but to make it go through a collaborative validation process: users/groups are added to a hierarchical stack, giving local roles dynamically. Section managers and section reviewers can still accept or reject publication. Users and/or groups at current level of the stack can: reject publication add/remove users and groups to the stack change the current level by moving it down or up Users and/or groups on top of the stack can accept publication if this level is also the current level. Section managers, section reviewers and users in the stack can still view and edit the document while it's in the pending state. Here is the graph corresponding to this process:

Nuxeo © 2005

17/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

There are three new transitions: "Manage delegatees" is used to add or remove users to the stack; "Move up delegatees" is used to move up the stack current level, and "Move down delegatees" is used to move it down. Users in the stack will be assigned a local role. This role has to be different from the existing ones so that we can set up permissions properly: while section reviewers can view, edit and accept/reject publication, we would like to have an intermediate role between reviewer and reader, so that users in the stack can view and edit the document, but not always accept or reject publication.

Adding a local role
Let's add a new local role to the portal, it will be used in the workflow definition. In the ZMI, go to the CPS root and click on the "Security" tab. Then click on the "Manage permissions" link on this page, and scroll down to the end of the page. You will have a form saying "User defined role": type "SectionIntermediateReviewer" and add it.

Adding a stack definition to a state
The stack we would like to use is a basic hierarchical stack, and we would like to use it in the pending state. Let's add the corresponding stack definition to the pending state: in the ZMI, come back to your workflow and go to the "pending" state. Click on the "Workflow stacks" tab, and add a hierarchical stack definition, with a hierarchical stack; type "Reviewers" for the stack definition name, it will be used to create the corresponding workflow variable.

Here is the variable that has been added to your workflow variables:

Nuxeo © 2005

18/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Once the stack definition has been added, in the previous "Workflow stacks" tab, you can click on it to configure it. We are going to set the empty stack guard, to tell who can manage the stack when it's empty: set the roles to "Manager; SectionManager; SectionReviewer". Section intermediate reviewers will not be able to initiate a collaborative validation process.

NB: "Manage the stack" means add, delete users/groups to the stack, and change the stack current level. Then set the dynamic roles configuration by adding the two roles that are managed by this stack: SectionReviewer: we will set this role to users/groups on top of the stack. The corresponding expression is "python:stack.getAllLevels() and level == stack.getAllLevels()[1] and level == stack.getCurrentLevel()". The stack has levels, its last level has to be the level where the stack element is, and it has to be the current level too. SectionIntermediateReviewer: this role will be given to other users/groups in the stack. The corresponding guard expression is: "python:stack.getAllLevels() and level < stack.getAllLevels()[-1] or level != stack.getCurrentLevel()". Here is a screen shot of the configuration page:

Nuxeo © 2005

19/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

The stack definition is configured. Let's add permission mappings for the SectionIntermediateReviewer role in the pending state. Go back to the state definition, and click on the "Permissions" tab. Now that the new role has been declared in the portal, it's available in the list of existing roles. Select it for both permissions, "Modify portal content" and "View": intermediate reviewers will now be able to edit and view the document. Now let's configure the state so that it allows different operations on the stack. Come back to the state configuration, and select the following state behaviour flags, always indicating the workflow variable "Reviewers": Push delegatees, on workflow variable "Reviewers" Pop delegatees, on workflow variables "Reviewers" Increase workflow level, on workflow variables "Reviewers" Decrease workflow level, on workflow variables "Reviewers" These operations are now allowed if document is in the pending state. We are going to add transitions that will allow to execute the corresponding operations on the stack.

Adding transitions to manipulate the stack
Go back to the workflow definition, and click on the "Transitions" tab. Add a transition with id "manage_delegatees", and then click on it. You can then set its title to "Manage delegatees", set it as a "Remain in state" transition, and keep the "initiated by user action" transition type set by default.

Nuxeo © 2005

20/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Only the roles property of the transition guard will be used ; set it to "Manager; SectionManager; SectionReviewer; SectionIntermediateReviewer". Some workflow stack transition flags are needed: select "Push delegatees, on workflow variable", and fill the form with "Reviewers", and select "Pop delegatees, on workflow variables", and fill the form with "Reviewers". These flags tell that this transition will be used to add/remove users/groups to the stack. This transition will also display an action in the actions box: set the action name to "manage_delegatees", the URL to "%(content_url)s/content_manage_delegatees_form", and the category to "workflow". "content_manage_delegatees_form" is a new template that you can find in the CPSWorkflowHowTo product. Note that the guard of this transition also takes care of the stack guard: if the stack definition says that the authenticated user cannot manage the stack (because he/she's not at current level, for instance), executing this transition will not be possible.

Now lets add the two transitions that will be used to change the current level. Add a transition with id "move_up_delegatees", set its title to "Move up delegatees", and set it as a "Remain in state" transition. The transition guard roles have to be set to "Manager; SectionManager; SectionReviewer; SectionIntermediateReviewer". Select the workflow stack transition behaviour "Increase workflow level, on workflow variables" and specify the workflow variable "Reviewers". Set the action name to "move_up_delegatees", and its URL to "%(content_url)s/content_move_up_delegatees_form?current_var_id=Reviewers". "content_move_up_delegatees_form" is also a new template in the CPSWorkflowHowTo product. Variable is passed as a parameter because templates are as generic as possible, and we could imagine another stack definition exists in the same state: we have to specify on which stack the current level has to be moved. The last transition is quite similar: you can set the same configuration for the transition with id "move_down_delegatees", turning every "up" word with "down" :) The transition flag to select is "Decrease the workflow level, on workflow variable" this time. Note that, whatever the transition guard says, the action to move up or move down the current level will not be displayed if it's not possible to do so (if level above current level is empty, for instance).

Now you can come back to the pending state configuration, and select the three new transitions as possible transitions:

Nuxeo © 2005

21/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Note that templates used in these new transitions do not call the "content_status_modify" script to execute the transition, because special keywords have to be sent as parameters of the doActionFor method: information about the stack workflow variable involved, about the chosen level, chosen delegatees, etc... There is one detail missing: right now, only users with local role "Manager", "SectionManager" or "SectionReviewer" can reject the document. We would like to let users/groups at current level take care of a rejection (e.g., users with role "SectionIntermediateReviewer" who are at current level in the stack). So we are going to add the SectionIntermediateReviewer role in the "reject" transition guard roles, and set the following expression in the guard expression: "python:user.has_role(('Manager', 'SectionManager', 'SectionReviewer'), here) or user.has_role(('SectionIntermediateReviewer',), here) and here.portal_workflow.canManageStack(here, 'Reviewers')". Remember that the guard fails if guard roles fails OR if guard expression fails. This expression means that users with roles SectionIntermediateReviewer will be able to reject the document only if they can manage the stack, as a basic hierarchical stack is configured to allow only users at current level to do it.

Nuxeo © 2005

22/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Using the newly created workflow
Create a new portal type or use an existing one
Now the workflow has been configured. I recommend you run the CPSWorkflowHowTo installer if you want a new document type, Schedule, to be created and installed. This document type will be used to test the new workflow, and it has a special layout so that the stack is displayed on its view page. Note that changes you would have made to the new workflow will be erased when launching the installer. If you want to test you workflow on an existing document type, without having to run the product installer, you can set up workflow chain configurations as described below. Note that you will still need to get and register in skins the CPSWorkflowHowTo product skin files.

Set up the appropriate workflow chain in sections
CPS workflows are placeful: it is possible to indicate that a given portal type follows different workflows according to its location on the site. We usually make a distinction between CPS sections and workspaces: a workflow chains configuration file exists in both roots. In the ZMI, go to the sections folder, and click on the "cps_configuration" file: here you can change the mapping between allowed portal types and the workflow they have to follow in sections. If you have executed the CPSWorkflowHowTo installer, the Schedule portal type should be mapped to the "cps_validation_wf" workflow.

Try out the new workflow
The Schedule document type has to be created in workspaces. When document is waiting for reviewers approval, a reviewer can manage delegatees to set up a collaborative validation process. Here is a screen shot presenting how delegatees can be assigned to the workflow:

Nuxeo © 2005

23/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

The Schedule document presents users/groups who are in the stack. You can see that the authenticated user, "Test2", can manage delegatees and change the current level, reject the document publication, but cannot accept it. If current level is moved to the top level, then the user called "test" will be able to accept publication. Here Test2 and the group called SpecialGroup are at current level:

Nuxeo © 2005

24/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

4 Appendix
This appendix gives technical details about workflow configuration and implementation. This is subject to changes and might not be kept up to date very quickly

Workflow tool
The workflow tool is used to manage workflow related operations. There are two main methods that are invoked via user interface code: doActionFor: this methods executes a workflow action (transition) on the given document.
doActionFor(self, ob, action, wf_id=None, *args, **kw)

Sample code to execute a transition:
context.portal_workflow.doActionFor(context, 'accept', comments="this doc rocks")

getInfoFor: this method returns a given workflow-specific property for an object. It is

usually used to get information about some workflow variable.
getInfoFor(self, ob, name, default=_marker, wf_id=None, *args, **kw)

Sample code to get the document current state:
context.portal_workflow.getInfoFor(context, 'review_state', None)

Workflow definition
Workflow installer
CPSInstaller has workflow related methods used to setup new workflows.
verifyWfStates(self, workflow, states) verifyWfTransitions(self, workflow, transitions) verifyWfScripts(self, workflow, scripts) verifyWfVariables(self, workflow, variables, state_var=None) verifyWorkflow(self, wfvariables={}) wfdef={}, wfstates={}, wftransitions={}, wfscripts={},

Sample usage is given in the CPSWorkflowHowTo product installer.

Placeful workflow configuration
To create a placeful workflow configuration, a 'CPS Workflow Configuration' object must be created in the ZMI. It's then possible to define for each portal type what workflow it has to follow.

Nuxeo © 2005

25/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

When a workflow is configured in a folder, it applies to the folder itself and all its subobjects, recursively. Sometimes we want to configure a workflow for all the subobjects of a folder but not for the folder itself. This can be done using a "Below workflow chain". The corresponding CPSInstaller method is:
verifyLocalWorkflowChains(self, object, wfchains, destructive=0, under_sub_add=None)

Sample code to setup a mapping in sections:
self.verifyLocalWorkflowChains(self.portal.sections,{'Section': 'section_folder_wf'})

State definition
State behaviours
Existing state behaviours are related to stacks management: Push delegatees: allow pushing elements in given stacks in that state Pop delegatees: allow popping elements from given stacks in that state Increase workflow level: allow moving up the current level for given stacks (only useful for hierarchical-like stacks) in that state Decrease workflow level: allow moving down the current level for given stacks (only useful for hierarchical-like stacks) in that state Reset workflow: allow emptying given stacks in that state

Transition definition
Transition behaviours
A number of transition flags have been added to DCWorkflow. These flags govern some special CPS behaviours for the transition. They can be subdivided in several categories.

Allowing subobject behaviour
A container has responsibility for globally allowing certain behaviours for its subobjects. This covers creation, deletion, moving into the container, copying into the container, publishing into the container, checkout into the container. Once a container allows certain operation, the workflow for the portal type itself will have to allow the operation too. Some of these behaviours are checked by the manage_CPScopyObjects, manage_CPScutObjects and manage_CPSpasteObjects methods.

Initial transitions
An initial transition is a transition followed when an object is created (or published, checked out, etc.) in a container. It does not have an initial state, but the destination state is the one the object will have after creation. When asking for the creation portal types,

Nuxeo © 2005

26/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

only those that have a suitable initial transition will be allowed. The standard "initial state" of DCWorkflow is not used. "Transition for checkin" is logically grouped together with those. It's a transition an object will follow when it is on the receiving end of a checkin (i.e., when it is the reference object into which a modification is checked back in).

Specific behaviours
"Freeze object" is used by all transitions going to a state where the object should not

be modified anymore. "Publishing, with initial transitions" is used as a mechanism for publishing an object into another container. "Checkout, with initial transitions" is used to checkout an object into another containe r. "Checkin, with allowed transitions" is used to checkin an object back into its original version. "Merge object with existing in same state" is used when in the destination state there should be only one docid in a state, e.g. only one published revision while several ones are pending.

Stacks related behaviours
Push delegatees: allow pushing elements in given stacks executing this transition Pop delegatees: allow popping elements from given stacks executing this transition Increase workflow level: allow moving up the current level for given stacks (only use-

ful for hierarchical-like stacks) executing this transition Decrease workflow level: allow moving down the current level for given stacks (only useful for hierarchical-like stacks) executing this transition Reset workflow: allow emptying given stacks executing this transition Note that some of these behaviours are incompatible: for instance, if a transition is flagged with both behaviours "increase workflow level" and "decrease workflow level" on the same workflow variable, executing this transition will have no effect on the stack current level.

Workflow expressions
Workflow expressions are used in transition guards and in stack definition guards. TODO: make the difference between DCWorkflow/CMFCore definitions and CPSWorkflow ones (some guards have been redefined to provide an extended namespace)

The available namespace
TODO

The state change object
TODO

Nuxeo © 2005

27/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

Stacks related definitions
Stack definition
A stack definition is an object stored within a state definition object implementing an abstraction layer on a stack object instance. It holds the basic configuration for a stack. A stack definition is defined by: the stack type the stack definition will be able to manage the id of the workflow variable where the stack instance will be stored the managed roles, e.g. roles that the stack definition can cope with. Roles have an associated tales expression evaluated within the stack definition context, defining the policy for the given role. A stack definition: defines high level accessors and mutators on the stack object. defines the policy of roles distributions for the stack elements stored within the stack using managed roles expressions. It includes as well a specific guard while the stack object doesn't contain elements yet. defines the default policy for viewing and editing stack elements using guards. (note that a stack element do have its own guard that may override the default behaviour from the stack definition). It may be used as well without any roles policy if the purpose of the stack is not to distribute local roles (for instance: adding a stack of tasks hooked on a given state). It is possible to know if a stack can be managed by the authenticated user by querying the workflow tool:
context.portal_workflow.canManageStack(context, 'Reviewers')

Stack
A stack is the actual object storing elements. A stack has a render method linked to a given template in skins ; it is used to represent the stack in different situations (view, edit, insert,...)
stack.render(context, mode='view')

A stack knows how to construct a stack element checking the element prefix. A stack can be accessed asking the corresponding workflow variable to the workflow tool.

Nuxeo © 2005

28/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw
stack = context.portal_workflow.getInfoFor(context, 'Reviewers', None)

Stack element
A stack element is stored within a stack. For instance, users and groups added to a stack are instances of different stack element types (user stack element and group stack element). A stack element is mainly defined by the prefix used to identify the element type (prefixes for basic stack elements are 'user' and 'group'). A stack element has its own guard that may override the default behaviour from the stack definition. If a stack element is protected, the stack will turn it into an instance of a corresponding hidden stack element type, defining what information is available.

Defining new stacks
A system of registries is available to let you register your own stack definition, stack and stack element types. You need to implement the corresponding interfaces.

Stack definition registry
To be able to register your own class within the WorkflowStackDefRegistry you need to subclass the bare definition or subclass one of the basic definitions, and implement the IWorkflowStackDefinition interface. You may use it like this:
from Products.CPSWorkflow.stackregistries import WorkflowStackDefRegsitry from Products.CPSWorkflow.stackdefinition import StackDefinition

class MyStackDefinition(StackDefinition): # Here implementation .... WorkflowStackDefRegistry.register(MyStackDefinition)

Stack registry
To be able to register your own class within the WorkflowStackRegistry you need to subclass the bare stack class or subclass one of the basic stacks, and implement the IWorkflowStack interface. You may use it like this:

Nuxeo © 2005

29/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw
from Products.CPSWorkflow.stackregistries import WorkflowStackRegistry from Products.CPSWorkflow.basicstacks import HierarchicalStack

class MyHierarchicalStack(HierarchicalStack): # Here implementation

WorkflowStackRegistry.register(MyHierarchicalStack)

Stack element registry
To be able to register your own class within the WorkflowStackElementRegistry you need to subclass the base stack element class or subclass one of the basic stack elements, and implement the IStackElement interface. You may use it like this:
from Products.CPSWorkflow.stackregistries import WorkflowStackElementRegistry from Products.CPSWorkflow.stackelement import StackElement

class MyUserStackElement(StackElement): meta_type = 'My Stack Element' prefix = 'my_user' # Here implementation

WorkflowStackElementRegistry.register(MyStackElement)

Do not forget to use a new prefix, so that the stack element type to use is detected properly when inserting a new element in the stack.

Nuxeo © 2005

30/31


CPSWorkflow HowTo CPSWorkflowHowTo.sxw

5 Links, references and contacts
About CPS
Community site: CPS Project User guide (currently only in French): CPS User guide Developer guide (currently only in French): CPS 3 Book HowTo « develop for CPS 3 » (currently only in French): HowTo CPS3 Development API: CPS 3 API SVN repository (source code and bug tracker): http://svn.nuxeo.org Mailing-lists: French speaking users: cps-users-fr English speaking users: cps-users Development (English only): cps-devel

About Nuxeo
Nuxeo is the European leader of services surrounding the open source platform Zope. Nuxeo develops and markets collaborative web content management systems, as well as associated services such as training, consulting and hosting. Nuxeo's customers have at their disposal a highly competent team with high technical qualifications and who use the best of free software. Nuxeo supports the open source software effort by publishing software components under a free license (GPL) and by contributing as a core developer to the development of the Zope platform. Nuxeo supports the action of the EuroLinux Alliance in favour of software innovation and free software, and against software patents, harmful for competition and innovation. Links: Commercial web site: www.nuxeo.com/en Email: contact@nuxeo.com

About Zope
Community site: zope.org Development recipes: Zope Labs

Nuxeo © 2005

31/31