[CMF-checkins] CVS: CMF - PortalContent.py:1.12 WorkflowCore.py:1.5 WorkflowTool.py:1.7 __init__.py:1.5
shane@digicool.com
shane@digicool.com
Tue, 22 May 2001 16:33:43 -0400 (EDT)
Update of /cvs-repository/CMF/CMFCore
In directory korak.digicool.com:/tmp/cvs-serv7982
Modified Files:
PortalContent.py WorkflowCore.py WorkflowTool.py __init__.py
Log Message:
- Refined the concept of workflow methods by allowing workflows to
manage the invocation of workflow methods.
- Removed the necessity of invoking afterCreate() by putting the logic
in PortalContent.manage_afterAdd() instead. Also reduces catalog
hits.
- Fixed a bug that made workflow type registration act strangely.
- Added WorkflowTool._invokeWithNotification() to streamline the
workflow event notification mechanism.
--- Updated File PortalContent.py in package CMF --
--- PortalContent.py 2001/05/11 04:34:28 1.11
+++ PortalContent.py 2001/05/22 20:33:42 1.12
@@ -159,8 +159,11 @@
catalog.reindexObject(self)
def manage_afterAdd(self, item, container):
- "Add self to the catalog."
+ "Add self to the workflow and catalog."
if aq_base(item) is aq_base(self):
+ wf = getToolByName(self, 'portal_workflow', None)
+ if wf is not None:
+ wf.notifyCreated(self)
self.indexObject()
def manage_beforeDelete(self, item, container):
--- Updated File WorkflowCore.py in package CMF --
--- WorkflowCore.py 2001/05/07 15:27:07 1.4
+++ WorkflowCore.py 2001/05/22 20:33:42 1.5
@@ -99,48 +99,36 @@
'''
-class WorkflowAction (Method):
+class WorkflowMethod (Method):
'''
Wraps a method to workflow-enable it.
'''
_need__name__=1
- def __init__(self, method, action=None, reindex=1):
+ def __init__(self, method, id=None, reindex=1):
self._m = method
- if action is None:
- action = method.__name__
- self._a = action
- self._reindex = reindex
+ if id is None:
+ id = method.__name__
+ self._id = id
+ # reindex ignored since workflows now perform the reindexing.
def __call__(self, instance, *args, **kw):
'''
Invokes the method.
'''
wf = getToolByName(instance, 'portal_workflow', None)
- if wf is None:
+ if wf is None or not hasattr(wf, 'wrapWorkflowMethod'):
# No workflow found.
- return apply(self._m, (instance,) + args, kw)
+ res = apply(self._m, (instance,) + args, kw)
else:
- action = self._a
- wf.notifyBefore(instance, action) # Can throw an exception.
- try:
- res = apply(self._m, (instance,) + args, kw)
- except:
- wf.notifyException(instance, action, sys.exc_info())
- raise
- else:
- wf.notifySuccess(instance, action, res)
- if self._reindex:
- catalog = getToolByName(instance, 'portal_catalog', None)
- if catalog is not None:
- catalog.reindexObject(instance)
- return res
+ res = wf.wrapWorkflowMethod(instance, self._id, self._m,
+ (instance,) + args, kw)
+ return res
+# Backward compatibility.
+WorkflowAction = WorkflowMethod
+
def afterCreate(ob):
- wf = getToolByName(ob, 'portal_workflow', None)
- if wf is not None:
- wf.notifyCreated(ob)
- catalog = getToolByName(ob, 'portal_catalog', None)
- if catalog is not None:
- catalog.reindexObject(ob)
+ # This functionality is now in PortalContent.py.
+ pass
--- Updated File WorkflowTool.py in package CMF --
--- WorkflowTool.py 2001/05/11 03:38:28 1.6
+++ WorkflowTool.py 2001/05/22 20:33:42 1.7
@@ -376,6 +376,30 @@
actions.extend(a)
return actions
+ def _invokeWithNotification(self, wfs, ob, action, func, args, kw):
+ '''
+ Private utility method.
+ '''
+ for w in wfs:
+ w.notifyBefore(ob, action)
+ try:
+ res = apply(func, args, kw)
+ except:
+ exc = sys.exc_info()
+ try:
+ for w in wfs:
+ w.notifyException(ob, action, exc)
+ raise exc[0], exc[1], exc[2]
+ finally:
+ exc = None
+ else:
+ for w in wfs:
+ w.notifySuccess(ob, action, res)
+ catalog = getToolByName(ob, 'portal_catalog', None)
+ if catalog is not None:
+ catalog.reindexObject(ob)
+ return res
+
security.declarePublic('doActionFor')
def doActionFor(self, ob, action, wf_id=None, *args, **kw):
'''
@@ -383,9 +407,11 @@
Allows the user to request a workflow action. The workflow object
must perform its own security checks.
'''
+ wfs = self.getWorkflowsFor(ob)
+ if wfs is None:
+ wfs = ()
if wf_id is None:
- wfs = self.getWorkflowsFor(ob)
- if wfs is None:
+ if not wfs:
raise WorkflowException('No workflows found.')
found = 0
for wf in wfs:
@@ -400,7 +426,31 @@
if wf is None:
raise WorkflowException(
'Requested workflow definition not found.')
- return apply(wf.doActionFor, (ob, action) + args, kw)
+ return self._invokeWithNotification(
+ wfs, ob, action, wf.doActionFor, (ob, action) + args, kw)
+
+ security.declarePrivate('wrapWorkflowMethod')
+ def wrapWorkflowMethod(self, ob, method_id, func, args, kw):
+ '''
+ To be invoked only by WorkflowCore.
+ Allows a workflow definition to wrap a WorkflowMethod.
+ '''
+ wf = None
+ wfs = self.getWorkflowsFor(ob)
+ if wfs:
+ for w in wfs:
+ if (hasattr(w, 'isWorkflowMethodSupported')
+ and w.isWorkflowMethodSupported(ob, method_id)):
+ wf = w
+ break
+ else:
+ wfs = ()
+ if wf is None:
+ # No workflow wraps this method.
+ return apply(func, args, kw)
+ return self._invokeWithNotification(
+ wfs, ob, method_id, wf.wrapWorkflowMethod,
+ (ob, method_id, func, args, kw), {})
security.declarePublic('getInfoFor')
def getInfoFor(self, ob, name, default=_marker, wf_id=None, *args, **kw):
@@ -531,4 +581,5 @@
def addWorkflowClass(klass):
# klass is expected to have id, title, and meta_type attributes.
# Its constructor should take one argument, id.
- _workflow_classes[klass.meta_type] = klass
+ id = getattr(klass, 'id', None) or klass.meta_type
+ _workflow_classes[id] = klass
--- Updated File __init__.py in package CMF --
--- __init__.py 2001/04/07 22:59:53 1.4
+++ __init__.py 2001/05/22 20:33:42 1.5
@@ -176,3 +176,4 @@
, extra_constructors=(
PortalFolder.manage_addPortalFolder, )
).initialize( context )
+