Introduction To Workflows#
What Is A Workflow?#
Workflow is the series of interactions that should happen to complete a task. Business organizations have many kinds of workflow.
For example, insurance companies process claims, delivery companies track shipments, and schools accept applications for admission.
All these tasks involve several people, sometimes take a long time, and vary significantly from organization to organization.
The goal of workflow software is to streamline and track workflow activity. Since different organizations have different workflow processes, workflow software must be flexible and easy to customize.
The workflow system inside of Plone is an example of a State Machine.
From Wikipedia:
A finite-state machine (FSM) or finite-state automaton (plural: automata), or simply a state machine, is a behavioral model used to design computer programs. It is composed of a finite number of states associated to transitions. A transition is a set of actions that starts from one state and ends in another (or the same) state. A transition is started by a trigger, and a trigger can be an event or a condition.
Any object controlled by workflow is always in precisely one
state
from each workflow in its chain.The
state
in which an object is currently located controls whattransitions
are available to it- Any workflow can be diagrammed, showing the available states and the transitions between them
Diagrams like this can be of enormous help in understanding your workflow
You should always sketch up a diagram when you start figuring out the workflow you want
What's In a Workflow?#
Workflows Control#
What
states
andtransitions
are availableWhich
permissions
will be managed (permissions not managed are left untouched from their current value by the workflow)Which
groups
will be managed (seestates
below for more about this)Which
variables
will be tracked by the workflow (values are set and stored every time a transition occurs)What
worklists
will be generated (you can return lists of content matching values tracked byvariables
What
scripts
are available to be used in conjunction withtransitions
These are basic python scripts, and are not used much anymore now that
events
are available
States Control#
What transitions are available out
What
permissions
are assigned to whichroles
locally to the objectWhat
groups
are assigned to whichroles
locally to the objectThis is probably the least-used aspect of workflow
It can be spectacularly useful
Transitions Control#
What
state
they will end inWhat conditions or
guards
are required for the transition to be availableThese can be
permissions
of the user,roles
a user has,groups
to which the user belongs, or even the boolean value of 'TALES' expressions
What
scripts
will be executed before and after the transition occurs (again, not used much now that we haveevents
)How the transition is triggered
This can be user-initiated or automatic
Automatic transitions happen when an object lands in a state from which they are a valid exit, and that object fulfills all conditions for the transition to be available.
If the conditions for the automated transition are not met, then the transition doesn't happen
Updating the object to meet the conditions will not kick it off
You'll have to back it out of the current
state
and re-do the transition that should have kicked it off
How Does Workflow Work In Plone?#
The tool in Plone that handles all workflow is called portal_workflow
Types must be
workflow
awareTypes in Plone are made WorkflowAware by a base content mixin from CMFCore
WorkflowAware
(inCMFCatalogAware
Workflow is assigned by type
Each type gets a chain
A chain can have more than one workflow in it
portal_workflow
is responsible for keeping track of all information about the workflow state of an objectA particular content object knows nothing about it's own workflow state
queries about the workflow of an object must be addressed to portal_workflow
>>> from plone import api
>>> fpage = api.content.get("/front-page")
>>> fpage.review_state
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: review_state
>>> api.content.get_state(fpage)
'published'
>>> wft = api.portal.get_tool('portal_workflow')
>>> wft.getChainFor(fpage)
('simple_publication_workflow',)
>>> wft.getTransitionsFor(fpage)
({'description': 'If you submitted the item by mistake or want to perform additional edits, this will take it back.', 'title': 'Member retracts submission', 'url': 'http://nohost/Plone/front-page/content_status_modify?workflow_action=retract', 'id': 'retract', 'title_or_id': 'Member retracts submission', 'name': 'Retract'}, {'description': 'Sending the item back will return the item to the original author instead of publishing it. You should preferably include a reason for why it was not published.', 'title': 'Reviewer sends content back for re-drafting', 'url': 'http://nohost/Plone/front-page/content_status_modify?workflow_action=reject', 'id': 'reject', 'title_or_id': 'Reviewer sends content back for re-drafting', 'name': 'Send back'})
>>> with api.env.adopt_user('content'):
... contrib-page = api.content.create(container=api.portal.get(), type="Document", title="Content Contrib Page")
... [i['id'] for i in wft.getTransitionsFor(api.content.get("/content-contrib-page")]
...
['submit']
>>> with api.env.adopt_roles(roles=['Manager',]):
... [i['id'] for i in wft.getTransitionsFor(contrib-page)]
...
['submit', 'publish']
portal_workflow
is security conscious, for all aspects of workflow it respects and validates the access levels of the current userUsers can only access the workflow information for which they have permissions
>>> with api.env.adopt_user('site-admin'):
... wft.getTransitionsFor(fpage)
...
>>> from pprint import pprint
>>> pprint(wft.getTransitionsFor(fpage))
({'description': 'If you submitted the item by mistake or want to perform
additional edits, this will take it back.',
'id': 'retract',
'name': 'Retract',
'title': 'Member retracts submission',
'title_or_id': 'Member retracts submission',
'url': 'Plone/front-page/content_status_modify?workflow_action=retract'},
{'description': 'Sending the item back will return the item to the original
author instead of publishing it. You should preferably include
a reason for why it was not published.',
'id': 'reject',
'name': 'Send back',
'title': 'Reviewer send content back for re-drafting',
'title_or_id': 'Reviewer send content back for re-drafting',
'url': 'Plone/front-page/content_status_modify?workflow_action=reject'})
Moving Content Through Workflows#
As stated above, any object with workflow is always in exactly one
state
for each workflow in it's chain.
When you initiate a transition, it is instantaneous.
What happens when this occurs?
The
BeforeTransitionEvent
is notified, and any subscribers to that event are executedAny
before script
registered for the transition are executed.The
transition
takes place
values are set for the variables registered by the workflow
the new
state
of the object is setthe new set of permissions values for roles and groups are calculated and updated
first permissions are remapped
then group -> role mappings are changed
the object is re-indexed for all security related indexes.
Any
after script
registered for the transition is executedThe
AfterTransitionEvent
is notified, and any subscribers to that event are executedIn general, transitions are triggered by user action. This takes place when a user clicks on the state menu in the Plone UI and selects an available transition, or when the user presses save from the Change State dialog found in the folder listing view.
As stated above, automatic transitions are found as a result of undergoing manual transitions.
Step 3 above can actually be executed multiple times when a user triggers a
transition
.Events and scripts are executed for each transition that happens
For this reason, when subscribing to workflow events, it's a good idea to check which transition just happened before taking any actions in your handler:
def handleWorkflowTransition(ob, event):
""" a handler meant to be used after a 'publish' transition """
if event.transition != 'publish':
return
...