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
statefrom each workflow in its chain.The
statein which an object is currently located controls whattransitionsare 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
statesandtransitionsare availableWhich
permissionswill be managed (permissions not managed are left untouched from their current value by the workflow)Which
groupswill be managed (seestatesbelow for more about this)Which
variableswill be tracked by the workflow (values are set and stored every time a transition occurs)What
worklistswill be generated (you can return lists of content matching values tracked byvariablesWhat
scriptsare available to be used in conjunction withtransitionsThese are basic python scripts, and are not used much anymore now that
eventsare available
States Control#
What transitions are available out
What
permissionsare assigned to whichroleslocally to the objectWhat
groupsare assigned to whichroleslocally to the objectThis is probably the least-used aspect of workflow
It can be spectacularly useful
Transitions Control#
What
statethey will end inWhat conditions or
guardsare required for the transition to be availableThese can be
permissionsof the user,rolesa user has,groupsto which the user belongs, or even the boolean value of 'TALES' expressions
What
scriptswill 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
stateand 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
workflowawareTypes 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_workflowis 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_workflowis 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
statefor each workflow in it's chain.
When you initiate a transition, it is instantaneous.
What happens when this occurs?
The
BeforeTransitionEventis notified, and any subscribers to that event are executedAny
before scriptregistered for the transition are executed.The
transitiontakes place
values are set for the variables registered by the workflow
the new
stateof 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 scriptregistered for the transition is executedThe
AfterTransitionEventis 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
...