Commit 6dc2151f authored by Jean-Paul Smets's avatar Jean-Paul Smets

*** empty log message ***


git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@1182 20353a03-c40f-0410-a6d1-a30d3c3de9de
parent 7cca32e1
......@@ -34,14 +34,10 @@ from Products.CMFCore.CMFCorePermissions import ManagePortal
from Products.DCWorkflow.ContainerTab import ContainerTab
from Products.DCWorkflow.Guard import Guard
from Products.DCWorkflow.Expression import Expression
from Products.DCWorkflow.Transitions import TRIGGER_AUTOMATIC, TRIGGER_WORKFLOW_METHOD
from Products.ERP5 import _dtmldir
TRIGGER_AUTOMATIC = 0
TRIGGER_USER_ACTION = 1 # useless for interaction
TRIGGER_WORKFLOW_METHOD = 2
class InteractionDefinition (SimpleItem):
meta_type = 'Workflow Interaction'
......@@ -51,14 +47,16 @@ class InteractionDefinition (SimpleItem):
title = ''
description = ''
new_state_id = ''
trigger_type = TRIGGER_USER_ACTION
trigger_type = TRIGGER_WORKFLOW_METHOD
guard = None
actbox_name = ''
actbox_url = ''
actbox_category = 'workflow'
var_exprs = None # A mapping.
script_name = None # Executed before transition
after_script_name = None # Executed after transition
script_name = () # Executed before transition
after_script_name = () # Executed after transition
activate_script_name = () # Executed as activity
method_id = None
manage_options = (
{'label': 'Properties', 'action': 'manage_properties'},
......@@ -115,20 +113,29 @@ class InteractionDefinition (SimpleItem):
manage_tabs_message=manage_tabs_message,
)
def setProperties(self, title, new_state_id,
trigger_type=TRIGGER_USER_ACTION, script_name='',
after_script_name='',
def setProperties(self, title,
portal_type_filter=None,
trigger_type=TRIGGER_AUTOMATIC,
script_name=(),
after_script_name=(),
activate_script_name=(),
actbox_name='', actbox_url='',
actbox_category='workflow',
method_id=None,
props=None, REQUEST=None, description=''):
'''
Update transition properties
XXX - then make sure that method_id is WorkflowMethod for portal_type_filter
XXX - this will likely require dynamic
'''
self.method_id = method_id
self.portal_type_filter = portal_type_filter
self.title = str(title)
self.description = str(description)
self.new_state_id = str(new_state_id)
self.trigger_type = int(trigger_type)
self.script_name = str(script_name)
self.after_script_name = str(after_script_name)
self.script_name = map(lambda x: str(x), script_name)
self.after_script_name = map(lambda x: str(x), after_script_name)
self.activate_script_name = map(lambda x: str(x), activate_script_name)
g = Guard()
if g.changeFromProperties(props or REQUEST):
self.guard = g
......
......@@ -18,16 +18,21 @@
import Globals
import App
from AccessControl import ClassSecurityInfo
from AccessControl import getSecurityManager, ClassSecurityInfo
from Products.CMFCore.utils import getToolByName, _getAuthenticatedUser
from Products.ERP5Type import Permissions, PropertySheet, Constraint, Interface
from Acquisition import aq_base, aq_parent, aq_inner, aq_acquire
from Products.DCWorkflow.DCWorkflow import DCWorkflowDefinition
from Products.DCWorkflow.Transitions import TRIGGER_AUTOMATIC, TRIGGER_WORKFLOW_METHOD
from Products.CMFCore.WorkflowCore import WorkflowException, \
ObjectDeleted, ObjectMoved
from Products.DCWorkflow.Expression import StateChangeInfo, createExprContext
from Products.CMFCore.WorkflowTool import addWorkflowFactory
from Products.CMFActivity.ActiveObject import ActiveObject
from zLOG import LOG
class InteractionWorkflowDefinition (DCWorkflowDefinition):
class InteractionWorkflowDefinition (DCWorkflowDefinition, ActiveObject):
"""
The InteractionTool implements portal object
interaction policies.
......@@ -95,7 +100,6 @@ class InteractionWorkflowDefinition (DCWorkflowDefinition):
{'label': 'Interactions', 'action': 'interactions/manage_main'},
{'label': 'Variables', 'action': 'variables/manage_main'},
{'label': 'Scripts', 'action': 'scripts/manage_main'},
{'label': 'Permissions', 'action': 'manage_permissions'},
) + App.Undo.UndoSupport.manage_options
def __init__(self, id):
......@@ -109,6 +113,313 @@ class InteractionWorkflowDefinition (DCWorkflowDefinition):
from Products.DCWorkflow.Scripts import Scripts
self._addObject(Scripts('scripts'))
def _executeTransition(self, ob, tdef=None, kwargs=None):
'''
Private method.
Puts object in a new state.
'''
sci = None
econtext = None
moved_exc = None
# Figure out the old and new states.
old_sdef = self._getWorkflowStateOf(ob)
old_state = old_sdef.getId()
if tdef is None:
new_state = self.initial_state
former_status = {}
else:
new_state = tdef.new_state_id
if not new_state:
# Stay in same state.
new_state = old_state
former_status = self._getStatusOf(ob)
new_sdef = self.states.get(new_state, None)
if new_sdef is None:
raise WorkflowException, (
'Destination state undefined: ' + new_state)
# Execute the "before" script.
if tdef is not None:
for script_name in tdef.script_name:
script = self.scripts[script_name]
# Pass lots of info to the script in a single parameter.
sci = StateChangeInfo(
ob, self, former_status, tdef, old_sdef, new_sdef, kwargs)
try:
script(sci) # May throw an exception.
except ObjectMoved, moved_exc:
ob = moved_exc.getNewObject()
# Re-raise after transition
# Update variables.
state_values = new_sdef.var_values
if state_values is None: state_values = {}
tdef_exprs = None
if tdef is not None: tdef_exprs = tdef.var_exprs
if tdef_exprs is None: tdef_exprs = {}
status = {}
for id, vdef in self.variables.items():
if not vdef.for_status:
continue
expr = None
if state_values.has_key(id):
value = state_values[id]
elif tdef_exprs.has_key(id):
expr = tdef_exprs[id]
elif not vdef.update_always and former_status.has_key(id):
# Preserve former value
value = former_status[id]
else:
if vdef.default_expr is not None:
expr = vdef.default_expr
else:
value = vdef.default_value
if expr is not None:
# Evaluate an expression.
if econtext is None:
# Lazily create the expression context.
if sci is None:
sci = StateChangeInfo(
ob, self, former_status, tdef,
old_sdef, new_sdef, kwargs)
econtext = createExprContext(sci)
value = expr(econtext)
status[id] = value
# Update state.
status[self.state_var] = new_state
tool = aq_parent(aq_inner(self))
tool.setStatusOf(self.id, ob, status)
# Update role to permission assignments.
self.updateRoleMappingsFor(ob)
# Execute the "after" script.
if tdef is not None:
for after_script_name in tdef.after_script_name:
script = self.scripts[after_script_name]
# Pass lots of info to the script in a single parameter.
sci = StateChangeInfo(
ob, self, status, tdef, old_sdef, new_sdef, kwargs)
script(sci) # May throw an exception.
# Execute the "activate" script.
if tdef is not None:
for after_script_name in tdef.activate_script_name:
script = self.scripts[after_script_name]
# Pass lots of info to the script in a single parameter.
sci = StateChangeInfo(
ob.activate(activity='SQLQueue'), None, status, tdef, old_sdef, new_sdef, kwargs)
script(sci) # May throw an exception.
# Return the new state object.
if moved_exc is not None:
# Propagate the notification that the object has moved.
raise moved_exc
else:
return new_sdef
security.declarePrivate('listObjectActions')
def listObjectActions(self, info):
return []
security.declarePrivate('isInfoSupported')
def isInfoSupported(self, ob, name):
'''
Returns a true value if the given info name is supported.
'''
vdef = self.variables.get(name, None)
if vdef is None:
return 0
return 1
security.declarePrivate('getInfoFor')
def getInfoFor(self, ob, name, default):
'''
Allows the user to request information provided by the
workflow. This method must perform its own security checks.
'''
vdef = self.variables[name]
if vdef.info_guard is not None and not vdef.info_guard.check(
getSecurityManager(), self, ob):
return default
status = self._getStatusOf(ob)
if status is not None and status.has_key(name):
value = status[name]
# Not set yet. Use a default.
elif vdef.default_expr is not None:
ec = createExprContext(StateChangeInfo(ob, self, status))
value = vdef.default_expr(ec)
else:
value = vdef.default_value
return value
security.declarePrivate('isWorkflowMethodSupported')
def isWorkflowMethodSupported(self, ob, method_id):
'''
Returns a true value if the given workflow is
automatic with the propper method_id
'''
return 0
for t in self.interactions.values():
if t.trigger_type == TRIGGER_WORKFLOW_METHOD:
if t.method_id == method_id:
if t.portal_type_filter is None:
return 1
elif ob.getPortalType() in t.portal_type_filter:
return 1
return 0
security.declarePrivate('wrapWorkflowMethod')
def wrapWorkflowMethod(self, ob, method_id, func, args, kw):
'''
Allows the user to request a workflow action. This method
must perform its own security checks.
'''
for t in self.interactions.values():
tdef = None
if t.trigger_type == TRIGGER_WORKFLOW_METHOD:
if t.method_id == method_id:
if t.portal_type_filter is None:
tdef = t
elif ob.getPortalType() in t.portal_type_filter:
tdef = t
if tdef is not None:
# Only execute if guard OK
if self._checkTransitionGuard(tdef, ob):
res = apply(func, args, kw)
try:
self._changeStateOf(ob, tdef)
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
security.declarePrivate('notifyBefore')
def notifyBefore(self, ob, action, args=None, kw=None):
'''
Notifies this workflow of an action before it happens,
allowing veto by exception. Unless an exception is thrown, either
a notifySuccess() or notifyException() can be expected later on.
The action usually corresponds to a method name.
'''
for t in self.interactions.values():
tdef = None
if t.trigger_type == TRIGGER_AUTOMATIC:
if t.portal_type_filter is None:
tdef = t
elif ob.getPortalType() in t.portal_type_filter:
tdef = t
elif t.trigger_type == TRIGGER_WORKFLOW_METHOD:
if t.method_id == action:
if t.portal_type_filter is None:
tdef = t
elif ob.getPortalType() in t.portal_type_filter:
tdef = t
if tdef is not None:
former_status = self._getStatusOf(ob)
# Execute the "before" script.
for script_name in tdef.script_name:
script = self.scripts[script_name]
# Pass lots of info to the script in a single parameter.
sci = StateChangeInfo(
ob, self, former_status, tdef, None, None, None)
try:
script(sci) # May throw an exception.
except ObjectMoved, moved_exc:
ob = moved_exc.getNewObject()
# Re-raise after transition
return
security.declarePrivate('notifySuccess')
def notifySuccess(self, ob, action, result, args=None, kw=None):
'''
Notifies this workflow that an action has taken place.
'''
for t in self.interactions.values():
tdef = None
if t.trigger_type == TRIGGER_AUTOMATIC:
if t.portal_type_filter is None:
tdef = t
elif ob.getPortalType() in t.portal_type_filter:
tdef = t
elif t.trigger_type == TRIGGER_WORKFLOW_METHOD:
if t.method_id == action:
if t.portal_type_filter is None:
tdef = t
elif ob.getPortalType() in t.portal_type_filter:
tdef = t
if tdef is not None:
# Update variables.
former_status = self._getStatusOf(ob)
tdef_exprs = tdef.var_exprs
if tdef_exprs is None: tdef_exprs = {}
status = {}
for id, vdef in self.variables.items():
if not vdef.for_status:
continue
expr = None
if tdef_exprs.has_key(id):
expr = tdef_exprs[id]
elif not vdef.update_always and former_status.has_key(id):
# Preserve former value
value = former_status[id]
else:
if vdef.default_expr is not None:
expr = vdef.default_expr
else:
value = vdef.default_value
if expr is not None:
# Evaluate an expression.
if econtext is None:
# Lazily create the expression context.
if sci is None:
sci = StateChangeInfo(
ob, self, former_status, tdef,
None, None, None)
econtext = createExprContext(sci)
value = expr(econtext)
status[id] = value
# Update state.
tool = aq_parent(aq_inner(self))
tool.setStatusOf(self.id, ob, status)
# Execute the "after" script.
for script_name in tdef.after_script_name:
script = self.scripts[script_name]
# Pass lots of info to the script in a single parameter.
sci = StateChangeInfo(
ob, self, status, tdef, None, None, None)
try:
script(sci) # May throw an exception.
except ObjectMoved, moved_exc:
ob = moved_exc.getNewObject()
# Re-raise after transition
# Execute the "after" script.
for script_name in tdef.activate_script_name:
self.activate(activity='SQLQueue').activeScript(script_name, ob.getRelativeUrl(), status, tdef.id)
return
security.declarePrivate('activeScript')
def activeScript(self, script_name, ob_url, status, tdef_id):
script = self.scripts[script_name]
ob = self.restrictedTraverse(ob_url)
tdef = self.interactions.get(tdef_id)
sci = StateChangeInfo(
ob, self, status, tdef, None, None, None)
script(sci)
Globals.InitializeClass(InteractionWorkflowDefinition)
addWorkflowFactory(InteractionWorkflowDefinition, id='interaction_workflow',
......
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