[CMF-checkins] CVS: CMF - DCWorkflow.py:1.4 Expression.py:1.3

shane@digicool.com shane@digicool.com
Tue, 12 Jun 2001 22:06:21 -0400 (EDT)


Update of /cvs-repository/CMF/DCWorkflow
In directory korak.digicool.com:/tmp/cvs-serv3181

Modified Files:
	DCWorkflow.py Expression.py 
Log Message:
- Role mappings were being updated before the state changed.  Fixed.

- DCWorkflow is now aware of ObjectDeleted and ObjectMoved messages.

- getObjectContainer() added to expressions.

- What is passed to scripts is now an object whose attributes are from
  the expression namespace.



--- Updated File DCWorkflow.py in package CMF --
--- DCWorkflow.py	2001/06/11 20:36:35	1.3
+++ DCWorkflow.py	2001/06/13 02:06:20	1.4
@@ -105,7 +105,8 @@
 from DocumentTemplate.DT_Util import TemplateDict
 
 # CMFCore
-from Products.CMFCore.WorkflowCore import WorkflowException
+from Products.CMFCore.WorkflowCore import WorkflowException, \
+     ObjectDeleted, ObjectMoved
 from Products.CMFCore.WorkflowTool import addWorkflowFactory
 from Products.CMFCore.CMFCorePermissions import ManagePortal
 from Products.CMFCore.utils import getToolByName
@@ -125,7 +126,19 @@
         raise ValueError, 'Illegal ID'
     return 1
 
+class NamespaceAccessor:
+    __allow_access_to_unprotected_subobjects__ = 1
+    def __init__(self, md):
+        self._getitem = md.getitem
+    def __getattr__(self, name):
+        try:
+            return self._getitem(name, 0)
+        except KeyError:
+            raise AttributeError, name
+    def __getitem__(self, name):
+        return self._getitem(name, 0)
 
+
 class DCWorkflowDefinition (WorkflowUIMixin, Folder):
     '''
     This class is the workflow engine and the container for the
@@ -378,7 +391,15 @@
         if not self._checkTransitionGuard(tdef, ob):
             raise Unauthorized
         res = apply(func, args, kw)
-        self._changeStateOf(ob, tdef)
+        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('isInfoSupported')
     def isInfoSupported(self, ob, name):
@@ -423,7 +444,11 @@
         Notifies this workflow after an object has been created
         and put in its new place.
         '''
-        self._changeStateOf(ob, None)
+        try:
+            self._changeStateOf(ob, None)
+        except ObjectDeleted, ObjectMoved:
+            # Swallow.
+            pass
 
     security.declarePrivate('notifyBefore')
     def notifyBefore(self, ob, action):
@@ -501,6 +526,7 @@
         Private method.
         Puts object in a new state.
         '''
+        moved = 0
         if tdef is None:
             state = self.initial_state
             former_status = {}
@@ -518,7 +544,12 @@
                 # Pass lots of info to the script in a single parameter.
                 md = exprNamespace(ob, self, former_status,
                                    action, state, kwargs)
-                script(md)  # May throw an exception.
+                accessor = NamespaceAccessor(md)
+                try:
+                    script(accessor)  # May throw an exception.
+                except ObjectMoved, ex:
+                    ob = ex.getNewObject()
+                    moved = 1
         sdef = self.states.get(state, None)
         if sdef is None:
             raise WorkflowException, 'Destination state undefined: ' + state
@@ -547,12 +578,16 @@
             status[id] = value
         # Update state.
         status[self.state_var] = state
+        tool = aq_parent(aq_inner(self))
+        tool.setStatusOf(self.id, ob, status)
         # Update role to permission assignments.
         self.updateRoleMappingsFor(ob)
 
-        tool = aq_parent(aq_inner(self))
-        tool.setStatusOf(self.id, ob, status)
-        return sdef
+        if moved:
+            # Re-raise.
+            raise ObjectMoved(ob)
+        else:
+            return sdef
 
 
 Globals.InitializeClass(DCWorkflowDefinition)

--- Updated File Expression.py in package CMF --
--- Expression.py	2001/06/11 20:18:14	1.2
+++ Expression.py	2001/06/13 02:06:20	1.3
@@ -94,6 +94,8 @@
 from AccessControl import getSecurityManager, ClassSecurityInfo
 from DocumentTemplate.DT_Util import TemplateDict, InstanceDict, Eval
 
+from Products.CMFCore.WorkflowCore import ObjectDeleted, ObjectMoved
+
 try:
     # Zope 2.3.x
     from DocumentTemplate.DT_Util import expr_globals
@@ -175,6 +177,8 @@
     '''
     Provides names that are more expensive to compute.
     '''
+    ObjectDeleted = ObjectDeleted
+    ObjectMoved = ObjectMoved
 
     def __init__(self, ob, wf):
         self._ob = ob
@@ -200,3 +204,6 @@
         while ob is not None and not getattr(ob, '_isPortalRoot', 0):
             ob = aq_parent(aq_inner(ob))
         return ob
+
+    def getObjectContainer(self):
+        return aq_parent(aq_inner(self._ob))