Commit 2160a804 authored by Jean-Paul Smets's avatar Jean-Paul Smets

Pass method variables to workflow history. This change may be good or not. I...

Pass method variables to workflow history. This change may be good or not. I do not know yet. Reviewing this code and patches is required.

git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@13171 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent e6aaba56
...@@ -16,7 +16,8 @@ ...@@ -16,7 +16,8 @@
from Globals import DTMLFile from Globals import DTMLFile
from Products.ERP5Type import _dtmldir from Products.ERP5Type import _dtmldir
from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition, StateChangeInfo, ObjectMoved, createExprContext, aq_parent, aq_inner from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition, StateChangeInfo, createExprContext
from Products.DCWorkflow.DCWorkflow import ObjectDeleted, ObjectMoved, aq_parent, aq_inner
from Products.DCWorkflow import DCWorkflow from Products.DCWorkflow import DCWorkflow
from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD, TransitionDefinition from Products.DCWorkflow.Transitions import TRIGGER_WORKFLOW_METHOD, TransitionDefinition
from AccessControl import getSecurityManager, ClassSecurityInfo, ModuleSecurityInfo from AccessControl import getSecurityManager, ClassSecurityInfo, ModuleSecurityInfo
...@@ -30,8 +31,6 @@ from Products.ERP5Type.Utils import convertToMixedCase ...@@ -30,8 +31,6 @@ from Products.ERP5Type.Utils import convertToMixedCase
from string import join from string import join
from zLOG import LOG from zLOG import LOG
# Patch WorkflowUIMixin to add description on workflows # Patch WorkflowUIMixin to add description on workflows
from Products.DCWorkflow.WorkflowUIMixin import WorkflowUIMixin as WorkflowUIMixin_class from Products.DCWorkflow.WorkflowUIMixin import WorkflowUIMixin as WorkflowUIMixin_class
from Products.DCWorkflow.Guard import Guard from Products.DCWorkflow.Guard import Guard
...@@ -57,7 +56,6 @@ WorkflowUIMixin_class.setProperties = WorkflowUIMixin_setProperties ...@@ -57,7 +56,6 @@ WorkflowUIMixin_class.setProperties = WorkflowUIMixin_setProperties
WorkflowUIMixin_class.manage_properties = DTMLFile('workflow_properties', _dtmldir) WorkflowUIMixin_class.manage_properties = DTMLFile('workflow_properties', _dtmldir)
def DCWorkflowDefinition_listGlobalActions(self, info): def DCWorkflowDefinition_listGlobalActions(self, info):
''' '''
Allows this workflow to Allows this workflow to
...@@ -144,7 +142,6 @@ DCWorkflow.ValidationFailed = ValidationFailed ...@@ -144,7 +142,6 @@ DCWorkflow.ValidationFailed = ValidationFailed
ModuleSecurityInfo('Products.DCWorkflow.DCWorkflow').declarePublic('ValidationFailed') ModuleSecurityInfo('Products.DCWorkflow.DCWorkflow').declarePublic('ValidationFailed')
# Patch excecuteTransition from DCWorkflowDefinition, to put ValidationFailed # Patch excecuteTransition from DCWorkflowDefinition, to put ValidationFailed
# error messages in workflow history. # error messages in workflow history.
def DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None): def DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None):
...@@ -271,10 +268,41 @@ def DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None): ...@@ -271,10 +268,41 @@ def DCWorkflowDefinition_executeTransition(self, ob, tdef=None, kwargs=None):
else: else:
return new_sdef return new_sdef
DCWorkflowDefinition._executeTransition = DCWorkflowDefinition_executeTransition DCWorkflowDefinition._executeTransition = DCWorkflowDefinition_executeTransition
from Products.DCWorkflow.utils import modifyRolesForPermission from Products.DCWorkflow.utils import modifyRolesForPermission
def DCWorkflowDefinition_wrapWorkflowMethod(self, ob, method_id, func, args, kw):
'''
Allows the user to request a workflow action. This method
must perform its own security checks.
'''
sdef = self._getWorkflowStateOf(ob)
if sdef is None:
raise WorkflowException, 'Object is in an undefined state'
if method_id not in sdef.transitions:
raise Unauthorized(method_id)
tdef = self.transitions.get(method_id, None)
if tdef is None or tdef.trigger_type != TRIGGER_WORKFLOW_METHOD:
raise WorkflowException, (
'Transition %s is not triggered by a workflow method'
% method_id)
if not self._checkTransitionGuard(tdef, ob):
raise Unauthorized(method_id)
res = func(*args, **kw)
try:
self._changeStateOf(ob, tdef, kw)
except ObjectDeleted:
# Re-raise with a different result.
raise ObjectDeleted(res)
except ObjectMoved, ex:
# Re-raise with a different result.
raise ObjectMoved(ex.getNewObject(), res)
return res
DCWorkflowDefinition.wrapWorkflowMethod = DCWorkflowDefinition_wrapWorkflowMethod
# Patch updateRoleMappingsFor so that if 2 workflows define security, then we # Patch updateRoleMappingsFor so that if 2 workflows define security, then we
# should do an AND operation between each permission # should do an AND operation between each permission
def updateRoleMappingsFor(self, ob): def updateRoleMappingsFor(self, ob):
...@@ -454,5 +482,3 @@ def createERP5Workflow(id): ...@@ -454,5 +482,3 @@ def createERP5Workflow(id):
addWorkflowFactory(createERP5Workflow, addWorkflowFactory(createERP5Workflow,
id='erp5_workflow', id='erp5_workflow',
title='ERP5-style empty workflow') title='ERP5-style empty workflow')
\ No newline at end of file
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
# #
############################################################################## ##############################################################################
from zLOG import LOG
# Make sure Interaction Workflows are called even if method not wrapped # Make sure Interaction Workflows are called even if method not wrapped
from Products.CMFCore.WorkflowTool import WorkflowTool from Products.CMFCore.WorkflowTool import WorkflowTool
...@@ -25,24 +27,25 @@ def WorkflowTool_wrapWorkflowMethod(self, ob, method_id, func, args, kw): ...@@ -25,24 +27,25 @@ def WorkflowTool_wrapWorkflowMethod(self, ob, method_id, func, args, kw):
By default, the workflow tool takes the first workflow wich By default, the workflow tool takes the first workflow wich
support the method_id. In ERP5, with Interaction Worfklows, we support the method_id. In ERP5, with Interaction Worfklows, we
may have many workflows wich can support a worfklow method, may have many workflows wich can support a worfklow method,
that's why we need this patch that's why we need this patch.
Current implementation supports:
- at most 1 DCWorkflow per portal type per method_id
- as many Interaction workflows as needed per portal type
NOTE: automatic transitions are invoked through
_findAutomaticTransition in DC Workflows.
We should have 1 or 0 classic workflow (ie a DCWorkflow), and TODO: make it possible to have multiple DC Workflow
0 or many Interaction workflows. We should take care that the per portal type per method_id
method will be called once
""" """
# Check workflow containing the workflow method # Check workflow containing the workflow method
wf_list = [] wf_list = []
wfs = self.getWorkflowsFor(ob) wfs = self.getWorkflowsFor(ob)
if wfs: if wfs:
for w in wfs: for w in wfs:
# LOG('ERP5WorkflowTool.wrapWorkflowMethod, is wfMSupported', 0,
# repr((w.isWorkflowMethodSupported(ob, method_id),
# w.getId(), ob, method_id )))
if (hasattr(w, 'isWorkflowMethodSupported') if (hasattr(w, 'isWorkflowMethodSupported')
and w.isWorkflowMethodSupported(ob, method_id)): and w.isWorkflowMethodSupported(ob, method_id)):
#wf = w
#break
wf_list.append(w) wf_list.append(w)
else: else:
wfs = () wfs = ()
...@@ -58,6 +61,13 @@ def WorkflowTool_wrapWorkflowMethod(self, ob, method_id, func, args, kw): ...@@ -58,6 +61,13 @@ def WorkflowTool_wrapWorkflowMethod(self, ob, method_id, func, args, kw):
for w in wf_list: for w in wf_list:
if w.__class__.__name__ != 'InteractionWorkflowDefinition': if w.__class__.__name__ != 'InteractionWorkflowDefinition':
only_interaction_defined = 0 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( result = self._invokeWithNotification(
[], ob, method_id, w.wrapWorkflowMethod, [], ob, method_id, w.wrapWorkflowMethod,
(ob, method_id, func, args, kw), {}) (ob, method_id, func, args, kw), {})
......
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