[Checkins] SVN: Products.CMFCore/trunk/Products/CMFCore/ - moved notifyWorkflowCreated and indexObject calls to IObjectAddedEvent handler

Yvo Schubbe y.2008 at wcm-solutions.de
Tue Jan 8 15:27:39 EST 2008


Log message for revision 82763:
  - moved notifyWorkflowCreated and indexObject calls to IObjectAddedEvent handler

Changed:
  U   Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
  U   Products.CMFCore/trunk/Products/CMFCore/CMFBTreeFolder.py
  U   Products.CMFCore/trunk/Products/CMFCore/CMFCatalogAware.py
  U   Products.CMFCore/trunk/Products/CMFCore/PortalFolder.py
  U   Products.CMFCore/trunk/Products/CMFCore/TypesTool.py
  U   Products.CMFCore/trunk/Products/CMFCore/tests/base/dummy.py
  U   Products.CMFCore/trunk/Products/CMFCore/tests/test_TypesTool.py

-=-
Modified: Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/CHANGES.txt	2008-01-08 20:27:39 UTC (rev 82763)
@@ -2,6 +2,12 @@
 
   Products.CMFCore 2.2.0 (unreleased)
 
+    - TypesTool: Refactored content creation.
+      Moved notifyWorkflowCreated and indexObject calls to IObjectAddedEvent
+      handler. Please make sure all oldstyle content factory methods use
+      _setObject with suppress_events=True. CMF factory methods don't finish
+      object creation, so they should not send the IObjectAddedEvent.
+
     - interfaces: Added ICatalogAware for CMFCatalogAware methods.
 
     - setup handlers: All import and export steps are now registered globally.

Modified: Products.CMFCore/trunk/Products/CMFCore/CMFBTreeFolder.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CMFBTreeFolder.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/CMFBTreeFolder.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -32,7 +32,7 @@
     id = str(id)
     ob = CMFBTreeFolder(id)
     ob.title = str(title)
-    dispatcher._setObject(id, ob)
+    dispatcher._setObject(id, ob, suppress_events=True)
     ob = dispatcher._getOb(id)
     if REQUEST is not None:
         REQUEST['RESPONSE'].redirect(ob.absolute_url() + '/manage_main' )
@@ -58,7 +58,7 @@
         """Add a new PortalFolder object with id *id*.
         """
         ob = PortalFolder(id, title)
-        self._setObject(id, ob)
+        self._setObject(id, ob, suppress_events=True)
         if REQUEST is not None:
             return self.folder_contents( # XXX: ick!
                 self, REQUEST, portal_status_message="Folder added")

Modified: Products.CMFCore/trunk/Products/CMFCore/CMFCatalogAware.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/CMFCatalogAware.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/CMFCatalogAware.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -229,11 +229,8 @@
     """ Event subscriber for (IContentish, IObjectEvent) events.
     """
     if IObjectAddedEvent.providedBy(event):
-        if event.newParent is not None:
-            ob.indexObject()
-
-    elif IObjectClonedEvent.providedBy(event):
         ob.notifyWorkflowCreated()
+        ob.indexObject()
 
     elif IObjectMovedEvent.providedBy(event):
         if event.newParent is not None:

Modified: Products.CMFCore/trunk/Products/CMFCore/PortalFolder.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/PortalFolder.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/PortalFolder.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -491,7 +491,7 @@
         """Add a new PortalFolder object with id *id*.
         """
         ob = PortalFolder(id, title)
-        self._setObject(id, ob)
+        self._setObject(id, ob, suppress_events=True)
         if REQUEST is not None:
             return self.folder_contents( # XXX: ick!
                 self, REQUEST, portal_status_message="Folder added")

Modified: Products.CMFCore/trunk/Products/CMFCore/TypesTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/TypesTool.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/TypesTool.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -28,9 +28,12 @@
 from OFS.Folder import Folder
 from OFS.ObjectManager import IFAwareObjectManager
 from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from zope.app.container.contained import ObjectAddedEvent
+from zope.app.container.contained import notifyContainerModified
 from zope.component import getUtility
 from zope.component import queryUtility
 from zope.component.interfaces import IFactory
+from zope.event import notify
 from zope.i18nmessageid import Message
 from zope.interface import implements
 
@@ -270,25 +273,8 @@
         if not self.isConstructionAllowed(container):
             raise AccessControl_Unauthorized('Cannot create %s' % self.getId())
 
-        ob = self._constructInstance(container, id, *args, **kw)
+        return self._constructInstance(container, id, *args, **kw)
 
-        return self._finishConstruction(ob)
-
-    security.declarePrivate('_finishConstruction')
-    def _finishConstruction(self, ob):
-        """
-            Finish the construction of a content object.
-            Set its portal_type, insert it into the workflows.
-        """
-        if hasattr(ob, '_setPortalTypeName'):
-            ob._setPortalTypeName(self.getId())
-
-        if hasattr(aq_base(ob), 'notifyWorkflowCreated'):
-            ob.notifyWorkflowCreated()
-
-        ob.reindexObject()
-        return ob
-
     security.declareProtected(ManagePortal, 'getMethodAliases')
     def getMethodAliases(self):
         """ Get method aliases dict.
@@ -428,8 +414,6 @@
         """Build a bare instance of the appropriate type.
 
         Does not do any security checks.
-
-        Returns the object without calling _finishConstruction().
         """
         # XXX: this method violates the rules for tools/utilities:
         # it depends on self.REQUEST
@@ -446,15 +430,23 @@
                 newid = m(id, *args, **kw)
             # allow factory to munge ID
             newid = newid or id
+            obj = container._getOb(newid)
+            if hasattr(obj, '_setPortalTypeName'):
+                obj._setPortalTypeName(self.getId())
+            notify(ObjectAddedEvent(obj, container, newid))
+            notifyContainerModified(container)
 
         else:
             # newstyle factory
             factory = getUtility(IFactory, self.factory)
             obj = factory(id, *args, **kw)
+            if hasattr(obj, '_setPortalTypeName'):
+                obj._setPortalTypeName(self.getId())
             rval = container._setObject(id, obj)
             newid = isinstance(rval, basestring) and rval or id
+            obj = container._getOb(newid)
 
-        return container._getOb(newid)
+        return obj
 
 InitializeClass(FactoryTypeInformation)
 
@@ -497,8 +489,6 @@
         """Build a bare instance of the appropriate type.
 
         Does not do any security checks.
-
-        Returns the object without calling _finishConstruction().
         """
         constructor = self.restrictedTraverse( self.constructor_path )
 
@@ -509,8 +499,14 @@
         constructor = aq_base(constructor).__of__( container )
 
         id = str(id)
-        return constructor(container, id, *args, **kw)
+        obj = constructor(container, id, *args, **kw)
+        if hasattr(obj, '_setPortalTypeName'):
+            obj._setPortalTypeName(self.getId())
+        notify(ObjectAddedEvent(obj, container, obj.getId()))
+        notifyContainerModified(container)
+        return obj
 
+
 InitializeClass(ScriptableTypeInformation)
 
 

Modified: Products.CMFCore/trunk/Products/CMFCore/tests/base/dummy.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/base/dummy.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/base/dummy.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -194,7 +194,7 @@
         if getattr(self._folder, '_prefix', None):
             id = '%s_%s' % ( self._folder._prefix, id )
         foo = DummyContent(id, *args, **kw)
-        self._folder._setObject(id, foo)
+        self._folder._setObject(id, foo, suppress_events=True)
         if getattr(self._folder, '_prefix', None):
             return id
 
@@ -225,14 +225,16 @@
     def _getOb( self, id ):
         return getattr(self, id)
 
-    def _setObject(self, id, object):
-        notify(ObjectWillBeAddedEvent(object, self, id))
+    def _setObject(self, id, object, suppress_events=False):
+        if not suppress_events:
+            notify(ObjectWillBeAddedEvent(object, self, id))
         self._setOb(id, object)
         object = self._getOb(id)
         if hasattr(aq_base(object), 'manage_afterAdd'):
             object.manage_afterAdd(object, self)
-        notify(ObjectAddedEvent(object, self, id))
-        notifyContainerModified(self)
+        if not suppress_events:
+            notify(ObjectAddedEvent(object, self, id))
+            notifyContainerModified(self)
         return object
 
     def _delObject(self, id):

Modified: Products.CMFCore/trunk/Products/CMFCore/tests/test_TypesTool.py
===================================================================
--- Products.CMFCore/trunk/Products/CMFCore/tests/test_TypesTool.py	2008-01-08 20:23:05 UTC (rev 82762)
+++ Products.CMFCore/trunk/Products/CMFCore/tests/test_TypesTool.py	2008-01-08 20:27:39 UTC (rev 82763)
@@ -23,15 +23,22 @@
 from AccessControl.SecurityManagement import noSecurityManager
 from AccessControl.SecurityManager import setSecurityPolicy
 from Acquisition import aq_base
+from OFS.interfaces import IObjectWillBeAddedEvent
 from Products.PythonScripts.PythonScript import PythonScript
 from Products.PythonScripts.standard import html_quote
 from webdav.NullResource import NullResource
+from zope.app.container.interfaces import IContainerModifiedEvent
+from zope.app.container.interfaces import IObjectAddedEvent
+from zope.component import adapter
 from zope.component import getSiteManager
+from zope.component import provideHandler
 from zope.component.interfaces import IFactory
+from zope.interface import implements
 from zope.interface.verify import verifyClass
 from zope.testing.cleanup import cleanUp
 
 from Products.CMFCore.ActionInformation import ActionInformation
+from Products.CMFCore.interfaces import ITypeInformation
 from Products.CMFCore.PortalFolder import PortalFolder
 from Products.CMFCore.testing import FunctionalZCMLLayer
 from Products.CMFCore.tests.base.dummy import DummyFactory
@@ -49,8 +56,6 @@
 from Products.CMFCore.tests.base.tidata import FTIDATA_DUMMY
 from Products.CMFCore.tests.base.tidata import STI_SCRIPT
 
-from zope.interface import implements
-from Products.CMFCore.interfaces import ITypeInformation
 
 class ActionTesterTypeInfo:
 
@@ -63,6 +68,7 @@
         self._action_obj = obj
         return ()
 
+
 class TypesToolTests(SecurityTest, WarningInterceptor):
 
     layer = FunctionalZCMLLayer
@@ -432,6 +438,7 @@
         newSecurityManager(None, UserWithRoles('FooAdder').__of__(self.f))
 
     def tearDown(self):
+        cleanUp()
         noSecurityManager()
 
     def test_constructInstance_w_id_munge(self):
@@ -440,7 +447,40 @@
         majyk_dust = self.f._getOb('majyk_dust')
         self.assertEqual(majyk_dust.id, 'majyk_dust')
 
+    def test_events(self):
+        events = []
 
+        @adapter(IObjectWillBeAddedEvent)
+        def _handleObjectWillBeAdded(event):
+            events.append(event)
+        provideHandler(_handleObjectWillBeAdded)
+
+        @adapter(IObjectAddedEvent)
+        def _handleObjectAdded(event):
+            events.append(event)
+        provideHandler(_handleObjectAdded)
+
+        @adapter(IContainerModifiedEvent)
+        def _handleContainerModified(event):
+            events.append(event)
+        provideHandler(_handleContainerModified)
+
+        self.ti.constructInstance(self.f, 'foo')
+        self.assertEquals(len(events), 2)
+
+        evt = events[0]
+        self.failUnless(IObjectAddedEvent.providedBy(evt))
+        self.assertEquals(evt.object, self.f.foo)
+        self.assertEquals(evt.oldParent, None)
+        self.assertEquals(evt.oldName, None)
+        self.assertEquals(evt.newParent, self.f)
+        self.assertEquals(evt.newName, 'foo')
+
+        evt = events[1]
+        self.failUnless(IContainerModifiedEvent.providedBy(evt))
+        self.assertEquals(evt.object, self.f)
+
+
 class FTINewstyleConstructionTests(FTIConstructionTestCase, SecurityTest):
 
     def setUp(self):
@@ -457,7 +497,48 @@
         cleanUp()
         SecurityTest.tearDown(self)
 
+    def test_events(self):
+        events = []
 
+        @adapter(IObjectWillBeAddedEvent)
+        def _handleObjectWillBeAdded(event):
+            events.append(event)
+        provideHandler(_handleObjectWillBeAdded)
+
+        @adapter(IObjectAddedEvent)
+        def _handleObjectAdded(event):
+            events.append(event)
+        provideHandler(_handleObjectAdded)
+
+        @adapter(IContainerModifiedEvent)
+        def _handleContainerModified(event):
+            events.append(event)
+        provideHandler(_handleContainerModified)
+
+        self.ti.constructInstance(self.f, 'foo')
+        self.assertEquals(len(events), 3)
+
+        evt = events[0]
+        self.failUnless(IObjectWillBeAddedEvent.providedBy(evt))
+        self.assertEquals(evt.object, self.f.foo)
+        self.assertEquals(evt.oldParent, None)
+        self.assertEquals(evt.oldName, None)
+        self.assertEquals(evt.newParent, self.f)
+        self.assertEquals(evt.newName, 'foo')
+
+        evt = events[1]
+        self.failUnless(IObjectAddedEvent.providedBy(evt))
+        self.assertEquals(evt.object, self.f.foo)
+        self.assertEquals(evt.oldParent, None)
+        self.assertEquals(evt.oldName, None)
+        self.assertEquals(evt.newParent, self.f)
+        self.assertEquals(evt.newName, 'foo')
+
+        evt = events[2]
+        self.failUnless(IContainerModifiedEvent.providedBy(evt))
+        self.assertEquals(evt.object, self.f)
+
+
 def test_suite():
     return unittest.TestSuite((
         unittest.makeSuite(TypesToolTests),



More information about the Checkins mailing list