[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