Commit e39727b8 authored by Jean-Paul Smets's avatar Jean-Paul Smets

New WorkflowMethod implementation. This new implementation solves most issues...

New WorkflowMethod implementation. This new implementation solves most issues which existed previously and related to multiple workflows for a single workflow method ID. It should also be faster but will require some more work so that changes in workflow definition are reflected automatically in workflow methods registration.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@15812 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 31dc012e
...@@ -16,80 +16,38 @@ from zLOG import LOG, WARNING ...@@ -16,80 +16,38 @@ from zLOG import LOG, WARNING
# Make sure Interaction Workflows are called even if method not wrapped # Make sure Interaction Workflows are called even if method not wrapped
from AccessControl import Unauthorized
from Products.CMFCore.WorkflowTool import WorkflowTool from Products.CMFCore.WorkflowTool import WorkflowTool
from Products.CMFCore.WorkflowCore import ObjectMoved, ObjectDeleted
from Products.CMFCore.WorkflowCore import WorkflowException
from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD
from Products.CMFCore.utils import getToolByName from Products.CMFCore.utils import getToolByName
from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery from Products.ZSQLCatalog.SQLCatalog import Query, ComplexQuery
from Products.CMFCore.utils import _getAuthenticatedUser from Products.CMFCore.utils import _getAuthenticatedUser
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
def WorkflowTool_wrapWorkflowMethod(self, ob, method_id, func, args, kw): def DCWorkflowDefinition_notifyWorkflowMethod(self, ob, method_id, args=None, kw=None, transition_list=None):
'''
""" To be invoked only by WorkflowCore. Allows the system to request a workflow action. This method
Allows a workflow definition to wrap a WorkflowMethod. must perform its own security checks.
'''
By default, the workflow tool takes the first workflow wich sdef = self._getWorkflowStateOf(ob)
support the method_id. In ERP5, with Interaction Worfklows, we if sdef is None:
may have many workflows wich can support a worfklow method, raise WorkflowException, 'Object is in an undefined state'
that's why we need this patch. if method_id not in sdef.transitions:
raise Unauthorized(method_id)
Current implementation supports: tdef = self.transitions.get(method_id, None)
- at most 1 DCWorkflow per portal type per method_id if tdef is None or tdef.trigger_type != TRIGGER_WORKFLOW_METHOD:
- as many Interaction workflows as needed per portal type raise WorkflowException, (
'Transition %s is not triggered by a workflow method'
NOTE: automatic transitions are invoked through % method_id)
_findAutomaticTransition in DC Workflows. if not self._checkTransitionGuard(tdef, ob):
raise Unauthorized(method_id)
TODO: make it possible to have multiple DC Workflow self._changeStateOf(ob, tdef)
per portal type per method_id (XXX). This could be useful
for example to make the edit WorkflowMethod trigger def DCWorkflowDefinition_notifyBefore(self, ob, action, args=None, kw=None, transition_list=None):
multiple automatic actions in different workflows.
More discussion needed on this.
"""
# Check workflow containing the workflow method
wf_list = []
wfs = self.getWorkflowsFor(ob)
if wfs:
for w in wfs:
if (hasattr(w, 'isWorkflowMethodSupported')
and w.isWorkflowMethodSupported(ob, method_id)):
wf_list.append(w)
else:
wfs = ()
# If no transition matched, simply call the method
# And return
if len(wf_list)==0:
return apply(func, args, kw)
# Call notifyBefore on each workflow
for w in wfs:
w.notifyBefore(ob, method_id, args=args, kw=kw)
# Call the method on matching workflows
only_interaction_defined = 1
for w in wf_list:
if w.__class__.__name__ != 'InteractionWorkflowDefinition':
only_interaction_defined = 0
# XXX - There is a problem here if the same workflow method
# is used by multiple workflows. Function "func" will be
# called multiple times. Patch or changes required to mak
# sure func is only called once.
# Solution consists in reimplementing _invokeWithNotification
# at the level of each workflow without notification
# (ex. _invokeWithoutNotification)
result = self._invokeWithNotification(
[], ob, method_id, w.wrapWorkflowMethod,
(ob, method_id, func, args, kw), {})
# If only interaction workflows are defined, we need to call the method
# manually
if only_interaction_defined:
result = apply(func, args, kw)
# Call notifySuccess on each workflow
for w in wfs:
w.notifySuccess(ob, method_id, result, args=args, kw=kw)
return result
WorkflowTool.wrapWorkflowMethod = WorkflowTool_wrapWorkflowMethod
def DCWorkflowDefinition_notifyBefore(self, ob, action, args=None, kw=None):
''' '''
Notifies this workflow of an action before it happens, Notifies this workflow of an action before it happens,
allowing veto by exception. Unless an exception is thrown, either allowing veto by exception. Unless an exception is thrown, either
...@@ -98,12 +56,13 @@ def DCWorkflowDefinition_notifyBefore(self, ob, action, args=None, kw=None): ...@@ -98,12 +56,13 @@ def DCWorkflowDefinition_notifyBefore(self, ob, action, args=None, kw=None):
''' '''
pass pass
def DCWorkflowDefinition_notifySuccess(self, ob, action, result, args=None, kw=None): def DCWorkflowDefinition_notifySuccess(self, ob, action, result, args=None, kw=None, transition_list=None):
''' '''
Notifies this workflow that an action has taken place. Notifies this workflow that an action has taken place.
''' '''
pass pass
DCWorkflowDefinition.notifyWorkflowMethod = DCWorkflowDefinition_notifyWorkflowMethod
DCWorkflowDefinition.notifyBefore = DCWorkflowDefinition_notifyBefore DCWorkflowDefinition.notifyBefore = DCWorkflowDefinition_notifyBefore
DCWorkflowDefinition.notifySuccess = DCWorkflowDefinition_notifySuccess DCWorkflowDefinition.notifySuccess = DCWorkflowDefinition_notifySuccess
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment