Commit ad42d728 authored by Florent Guillaume's avatar Florent Guillaume

Zope now sends Zope 3 events when objects are added or removed from

standard containers. manage_afterAdd, manage_beforeDelete and
manage_afterClone are now deprecated. See
lib/python/Products/Five/tests/event.txt for details.

This requires Five 1.3 (included in Zope 2.9).
parent 7a3b9de0
...@@ -26,6 +26,11 @@ Zope Changes ...@@ -26,6 +26,11 @@ Zope Changes
Features added Features added
- Zope now sends Zope 3 events when objects are added or removed
from standard containers. manage_afterAdd, manage_beforeDelete
and manage_afterClone are now deprecated. See
lib/python/Products/Five/tests/event.txt for details.
- Zope now utilizes ZODB 3.6. It had previously used - Zope now utilizes ZODB 3.6. It had previously used
ZODB 3.4. As a result, the DBTab package was removed, as ZODB 3.4. As a result, the DBTab package was removed, as
ZODB 3.6 has multidatabase support that makes DBTab ZODB 3.6 has multidatabase support that makes DBTab
......
...@@ -459,6 +459,10 @@ class AppInitializer: ...@@ -459,6 +459,10 @@ class AppInitializer:
from Products.Sessions.BrowserIdManager import BrowserIdManager from Products.Sessions.BrowserIdManager import BrowserIdManager
bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager') bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager')
app._setObject('browser_id_manager', bid) app._setObject('browser_id_manager', bid)
# FIXME explicitely call manage_afterAdd, as sometimes
# events are initialized too late
browser_id_manager = app.browser_id_manager
browser_id_manager.manage_afterAdd(browser_id_manager, app)
app._setInitializerFlag('browser_id_manager') app._setInitializerFlag('browser_id_manager')
self.commit('Added browser_id_manager') self.commit('Added browser_id_manager')
...@@ -475,6 +479,10 @@ class AppInitializer: ...@@ -475,6 +479,10 @@ class AppInitializer:
path='/temp_folder/session_data', path='/temp_folder/session_data',
requestName='SESSION') requestName='SESSION')
app._setObject('session_data_manager', sdm) app._setObject('session_data_manager', sdm)
# FIXME explicitely call manage_afterAdd, as sometimes
# events are initialized too late
session_data_manager = app.session_data_manager
session_data_manager.manage_afterAdd(session_data_manager, app)
app._setInitializerFlag('session_data_manager') app._setInitializerFlag('session_data_manager')
self.commit('Added session_data_manager') self.commit('Added session_data_manager')
...@@ -523,6 +531,10 @@ class AppInitializer: ...@@ -523,6 +531,10 @@ class AppInitializer:
from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
error_log = SiteErrorLog() error_log = SiteErrorLog()
app._setObject('error_log', error_log) app._setObject('error_log', error_log)
# FIXME explicitely call manage_afterAdd, as sometimes
# events are initialized too late
error_log = app.error_log
error_log.manage_afterAdd(error_log, app)
app._setInitializerFlag('error_log') app._setInitializerFlag('error_log')
self.commit('Added site error_log at /error_log') self.commit('Added site error_log at /error_log')
......
...@@ -30,6 +30,11 @@ from App.Dialogs import MessageDialog ...@@ -30,6 +30,11 @@ from App.Dialogs import MessageDialog
from webdav.Lockable import ResourceLockedError from webdav.Lockable import ResourceLockedError
from zExceptions import Unauthorized, BadRequest from zExceptions import Unauthorized, BadRequest
from zope.interface import implements from zope.interface import implements
from zope.event import notify
from zope.app.event.objectevent import ObjectCopiedEvent
from zope.app.container.contained import ObjectMovedEvent
from Products.Five.event import ObjectWillBeMovedEvent
from Products.Five.event import FiveObjectClonedEvent
from OFS.interfaces import ICopyContainer from OFS.interfaces import ICopyContainer
from OFS.interfaces import ICopySource from OFS.interfaces import ICopySource
...@@ -154,85 +159,123 @@ class CopyContainer(ExtensionClass.Base): ...@@ -154,85 +159,123 @@ class CopyContainer(ExtensionClass.Base):
If calling manage_pasteObjects from python code, pass the result of a If calling manage_pasteObjects from python code, pass the result of a
previous call to manage_cutObjects or manage_copyObjects as the first previous call to manage_cutObjects or manage_copyObjects as the first
argument. argument.
Also sends IObjectCopiedEvent and IFiveObjectClonedEvent
or IObjectWillBeMovedEvent and IObjectMovedEvent.
""" """
cp=None # Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
if cb_copy_data is not None: if cb_copy_data is not None:
cp=cb_copy_data cp = cb_copy_data
elif REQUEST is not None and REQUEST.has_key('__cp'):
cp = REQUEST['__cp']
else: else:
if REQUEST and REQUEST.has_key('__cp'): cp = None
cp=REQUEST['__cp']
if cp is None: if cp is None:
raise CopyError, eNoData raise CopyError, eNoData
try: cp=_cb_decode(cp) try:
except: raise CopyError, eInvalid op, mdatas = _cb_decode(cp)
except:
raise CopyError, eInvalid
oblist=[] oblist = []
op=cp[0]
app = self.getPhysicalRoot() app = self.getPhysicalRoot()
result = [] for mdata in mdatas:
for mdata in cp[1]:
m = Moniker.loadMoniker(mdata) m = Moniker.loadMoniker(mdata)
try: ob = m.bind(app) try:
except: raise CopyError, eNotFound ob = m.bind(app)
except ConflictError:
raise
except:
raise CopyError, eNotFound
self._verifyObjectPaste(ob, validate_src=op+1) self._verifyObjectPaste(ob, validate_src=op+1)
oblist.append(ob) oblist.append(ob)
if op==0: result = []
if op == 0:
# Copy operation # Copy operation
for ob in oblist: for ob in oblist:
orig_id = ob.getId()
if not ob.cb_isCopyable(): if not ob.cb_isCopyable():
raise CopyError, eNotSupported % escape(ob.getId()) raise CopyError, eNotSupported % escape(orig_id)
try: ob._notifyOfCopyTo(self, op=0)
except: raise CopyError, MessageDialog( try:
title='Copy Error', ob._notifyOfCopyTo(self, op=0)
message=sys.exc_info()[1], except ConflictError:
action ='manage_main') raise
ob=ob._getCopy(self) except:
orig_id=ob.getId() raise CopyError, MessageDialog(
id=self._get_id(ob.getId()) title="Copy Error",
result.append({'id':orig_id, 'new_id':id}) message=sys.exc_info()[1],
action='manage_main')
id = self._get_id(orig_id)
result.append({'id': orig_id, 'new_id': id})
ob = ob._getCopy(self)
ob._setId(id) ob._setId(id)
notify(ObjectCopiedEvent(ob))
self._setObject(id, ob) self._setObject(id, ob)
ob = self._getOb(id) ob = self._getOb(id)
ob._postCopy(self, op=0)
ob.manage_afterClone(ob)
ob.wl_clearLocks() ob.wl_clearLocks()
ob._postCopy(self, op=0)
maybeCallDeprecated('manage_afterClone', ob)
notify(FiveObjectClonedEvent(ob))
if REQUEST is not None: if REQUEST is not None:
return self.manage_main(self, REQUEST, update_menu=1, return self.manage_main(self, REQUEST, update_menu=1,
cb_dataValid=1) cb_dataValid=1)
if op==1: elif op == 1:
# Move operation # Move operation
for ob in oblist: for ob in oblist:
id=ob.getId() orig_id = ob.getId()
if not ob.cb_isMoveable(): if not ob.cb_isMoveable():
raise CopyError, eNotSupported % escape(id) raise CopyError, eNotSupported % escape(orig_id)
try: ob._notifyOfCopyTo(self, op=1)
except: raise CopyError, MessageDialog( try:
title='Move Error', ob._notifyOfCopyTo(self, op=1)
message=sys.exc_info()[1], except ConflictError:
action ='manage_main') raise
except:
raise CopyError, MessageDialog(
title="Move Error",
message=sys.exc_info()[1],
action='manage_main')
if not sanity_check(self, ob): if not sanity_check(self, ob):
raise CopyError, 'This object cannot be pasted into itself' raise CopyError, "This object cannot be pasted into itself"
orig_container = aq_parent(aq_inner(ob))
if aq_base(orig_container) is aq_base(self):
id = orig_id
else:
id = self._get_id(orig_id)
result.append({'id': orig_id, 'new_id': id})
notify(ObjectWillBeMovedEvent(ob, orig_container, orig_id,
self, id))
# try to make ownership explicit so that it gets carried # try to make ownership explicit so that it gets carried
# along to the new location if needed. # along to the new location if needed.
ob.manage_changeOwnershipType(explicit=1) ob.manage_changeOwnershipType(explicit=1)
aq_parent(aq_inner(ob))._delObject(id) orig_container._delObject(orig_id, suppress_events=True)
ob = aq_base(ob) ob = aq_base(ob)
orig_id=id
id=self._get_id(id)
result.append({'id':orig_id, 'new_id':id })
ob._setId(id) ob._setId(id)
self._setObject(id, ob, set_owner=0)
ob=self._getOb(id)
ob._postCopy(self, op=1)
self._setObject(id, ob, set_owner=0, suppress_events=True)
ob = self._getOb(id)
notify(ObjectMovedEvent(ob, orig_container, orig_id, self, id))
ob._postCopy(self, op=1)
# try to make ownership implicit if possible # try to make ownership implicit if possible
ob.manage_changeOwnershipType(explicit=0) ob.manage_changeOwnershipType(explicit=0)
...@@ -243,6 +286,7 @@ class CopyContainer(ExtensionClass.Base): ...@@ -243,6 +286,7 @@ class CopyContainer(ExtensionClass.Base):
REQUEST['__cp'] = None REQUEST['__cp'] = None
return self.manage_main(self, REQUEST, update_menu=1, return self.manage_main(self, REQUEST, update_menu=1,
cb_dataValid=0) cb_dataValid=0)
return result return result
manage_renameForm=Globals.DTMLFile('dtml/renameForm', globals()) manage_renameForm=Globals.DTMLFile('dtml/renameForm', globals())
...@@ -259,31 +303,48 @@ class CopyContainer(ExtensionClass.Base): ...@@ -259,31 +303,48 @@ class CopyContainer(ExtensionClass.Base):
return None return None
def manage_renameObject(self, id, new_id, REQUEST=None): def manage_renameObject(self, id, new_id, REQUEST=None):
"""Rename a particular sub-object""" """Rename a particular sub-object.
try: self._checkId(new_id) """
except: raise CopyError, MessageDialog( try:
title='Invalid Id', self._checkId(new_id)
message=sys.exc_info()[1], except:
action ='manage_main') raise CopyError, MessageDialog(
ob=self._getOb(id) title='Invalid Id',
message=sys.exc_info()[1],
action ='manage_main')
ob = self._getOb(id)
if ob.wl_isLocked(): if ob.wl_isLocked():
raise ResourceLockedError, 'Object "%s" is locked via WebDAV' % ob.getId() raise ResourceLockedError, ('Object "%s" is locked via WebDAV'
% ob.getId())
if not ob.cb_isMoveable(): if not ob.cb_isMoveable():
raise CopyError, eNotSupported % escape(id) raise CopyError, eNotSupported % escape(id)
self._verifyObjectPaste(ob) self._verifyObjectPaste(ob)
try: ob._notifyOfCopyTo(self, op=1)
except: raise CopyError, MessageDialog( try:
title='Rename Error', ob._notifyOfCopyTo(self, op=1)
message=sys.exc_info()[1], except ConflictError:
action ='manage_main') raise
self._delObject(id) except:
raise CopyError, MessageDialog(
title="Rename Error",
message=sys.exc_info()[1],
action ='manage_main')
notify(ObjectWillBeMovedEvent(ob, self, id, self, new_id))
self._delObject(id, suppress_events=True)
ob = aq_base(ob) ob = aq_base(ob)
ob._setId(new_id) ob._setId(new_id)
# Note - because a rename always keeps the same context, we # Note - because a rename always keeps the same context, we
# can just leave the ownership info unchanged. # can just leave the ownership info unchanged.
self._setObject(new_id, ob, set_owner=0) self._setObject(new_id, ob, set_owner=0, suppress_events=True)
ob = self._getOb(new_id) ob = self._getOb(new_id)
notify(ObjectMovedEvent(ob, self, id, self, new_id))
ob._postCopy(self, op=1) ob._postCopy(self, op=1)
if REQUEST is not None: if REQUEST is not None:
...@@ -296,26 +357,46 @@ class CopyContainer(ExtensionClass.Base): ...@@ -296,26 +357,46 @@ class CopyContainer(ExtensionClass.Base):
# Because it's still a "management" function. # Because it's still a "management" function.
manage_clone__roles__=None manage_clone__roles__=None
def manage_clone(self, ob, id, REQUEST=None): def manage_clone(self, ob, id, REQUEST=None):
# Clone an object, creating a new object with the given id. """Clone an object, creating a new object with the given id.
"""
# Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
if not ob.cb_isCopyable(): if not ob.cb_isCopyable():
raise CopyError, eNotSupported % escape(ob.getId()) raise CopyError, eNotSupported % escape(ob.getId())
try: self._checkId(id) try:
except: raise CopyError, MessageDialog( self._checkId(id)
title='Invalid Id', except:
message=sys.exc_info()[1], raise CopyError, MessageDialog(
action ='manage_main') title='Invalid Id',
message=sys.exc_info()[1],
action ='manage_main')
self._verifyObjectPaste(ob) self._verifyObjectPaste(ob)
try: ob._notifyOfCopyTo(self, op=0)
except: raise CopyError, MessageDialog( try:
title='Clone Error', ob._notifyOfCopyTo(self, op=0)
message=sys.exc_info()[1], except ConflictError:
action ='manage_main') raise
ob=ob._getCopy(self) except:
raise CopyError, MessageDialog(
title="Clone Error",
message=sys.exc_info()[1],
action='manage_main')
ob = ob._getCopy(self)
ob._setId(id) ob._setId(id)
notify(ObjectCopiedEvent(ob))
self._setObject(id, ob) self._setObject(id, ob)
ob=self._getOb(id) ob = self._getOb(id)
ob._postCopy(self, op=0) ob._postCopy(self, op=0)
ob.manage_afterClone(ob)
maybeCallDeprecated('manage_afterClone', ob)
notify(FiveObjectClonedEvent(ob))
return ob return ob
def cb_dataValid(self): def cb_dataValid(self):
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
$Id$ $Id$
""" """
import warnings
import marshal import marshal
import sys, fnmatch, copy, os, re import sys, fnmatch, copy, os, re
from cgi import escape from cgi import escape
...@@ -42,6 +43,11 @@ from zope.interface import implements ...@@ -42,6 +43,11 @@ from zope.interface import implements
import CopySupport import CopySupport
from interfaces import IObjectManager from interfaces import IObjectManager
from Traversable import Traversable from Traversable import Traversable
from zope.event import notify
from zope.app.container.contained import ObjectAddedEvent
from zope.app.container.contained import ObjectRemovedEvent
from Products.Five.event import ObjectWillBeAddedEvent
from Products.Five.event import ObjectWillBeRemovedEvent
# the name BadRequestException is relied upon by 3rd-party code # the name BadRequestException is relied upon by 3rd-party code
...@@ -266,11 +272,20 @@ class ObjectManager( ...@@ -266,11 +272,20 @@ class ObjectManager(
raise AttributeError, id raise AttributeError, id
return default return default
def _setObject(self, id, object, roles=None, user=None, set_owner=1): def _setObject(self, id, object, roles=None, user=None, set_owner=1,
v=self._checkId(id) suppress_events=False):
if v is not None: id=v """Set an object into this container.
try: t=object.meta_type
except: t=None Also sends IObjectWillBeAddedEvent and IObjectAddedEvent.
"""
# Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
ob = object # better name, keep original function signature
v = self._checkId(id)
if v is not None:
id = v
t = getattr(ob, 'meta_type', None)
# If an object by the given id already exists, remove it. # If an object by the given id already exists, remove it.
for object_info in self._objects: for object_info in self._objects:
...@@ -278,78 +293,78 @@ class ObjectManager( ...@@ -278,78 +293,78 @@ class ObjectManager(
self._delObject(id) self._delObject(id)
break break
self._objects=self._objects+({'id':id,'meta_type':t},) if not suppress_events:
self._setOb(id,object) notify(ObjectWillBeAddedEvent(ob, self, id))
object=self._getOb(id)
self._objects = self._objects + ({'id': id, 'meta_type': t},)
self._setOb(id, ob)
ob = self._getOb(id)
if set_owner: if set_owner:
object.manage_fixupOwnershipAfterAdd() # TODO: eventify manage_fixupOwnershipAfterAdd
# This will be called for a copy/clone, or a normal _setObject.
ob.manage_fixupOwnershipAfterAdd()
# Try to give user the local role "Owner", but only if # Try to give user the local role "Owner", but only if
# no local roles have been set on the object yet. # no local roles have been set on the object yet.
if hasattr(object, '__ac_local_roles__'): if getattr(ob, '__ac_local_roles__', _marker) is None:
if object.__ac_local_roles__ is None: user = getSecurityManager().getUser()
user=getSecurityManager().getUser() if user is not None:
if user is not None: userid = user.getId()
userid=user.getId() if userid is not None:
if userid is not None: ob.manage_setLocalRoles(userid, ['Owner'])
object.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
object.manage_afterAdd(object, self) notify(ObjectAddedEvent(ob, self, id))
maybeCallDeprecated('manage_afterAdd', ob, self)
return id return id
def manage_afterAdd(self, item, container): def manage_afterAdd(self, item, container):
for object in self.objectValues(): # Don't do recursion anymore, a subscriber does that.
try: s=object._p_changed warnings.warn(
except: s=0 "%s.manage_afterAdd is deprecated and will be removed in "
if hasattr(aq_base(object), 'manage_afterAdd'): "Zope 2.11, you should use an IObjectAddedEvent "
object.manage_afterAdd(item, container) "subscriber instead." % self.__class__.__name__,
if s is None: object._p_deactivate() DeprecationWarning, stacklevel=2)
manage_afterAdd.__five_method__ = True
def manage_afterClone(self, item): def manage_afterClone(self, item):
for object in self.objectValues(): # Don't do recursion anymore, a subscriber does that.
try: s=object._p_changed warnings.warn(
except: s=0 "%s.manage_afterClone is deprecated and will be removed in "
if hasattr(aq_base(object), 'manage_afterClone'): "Zope 2.11, you should use an IFiveObjectClonedEvent "
object.manage_afterClone(item) "subscriber instead." % self.__class__.__name__,
if s is None: object._p_deactivate() DeprecationWarning, stacklevel=2)
manage_afterClone.__five_method__ = True
def manage_beforeDelete(self, item, container): def manage_beforeDelete(self, item, container):
for object in self.objectValues(): # Don't do recursion anymore, a subscriber does that.
try: s=object._p_changed warnings.warn(
except: s=0 "%s.manage_beforeDelete is deprecated and will be removed in "
try: "Zope 2.11, you should use an IObjectWillBeRemovedEvent "
if hasattr(aq_base(object), 'manage_beforeDelete'): "subscriber instead." % self.__class__.__name__,
object.manage_beforeDelete(item, container) DeprecationWarning, stacklevel=2)
except BeforeDeleteException, ob: manage_beforeDelete.__five_method__ = True
raise
except ConflictError: def _delObject(self, id, dp=1, suppress_events=False):
raise """Delete an object from this container.
except:
LOG('Zope',ERROR,'manage_beforeDelete() threw', Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent.
error=sys.exc_info()) """
# In debug mode when non-Manager, let exceptions propagate. # Done here to avoid circular imports
if getConfiguration().debug_mode: from Products.Five.subscribers import maybeCallDeprecated
if not getSecurityManager().getUser().has_role('Manager'):
raise ob = self._getOb(id)
if s is None: object._p_deactivate()
maybeCallDeprecated('manage_beforeDelete', ob, self)
def _delObject(self, id, dp=1):
object=self._getOb(id) if not suppress_events:
try: notify(ObjectWillBeRemovedEvent(ob, self, id))
object.manage_beforeDelete(object, self)
except BeforeDeleteException, ob: self._objects = tuple([i for i in self._objects
raise if i['id'] != id])
except ConflictError:
raise
except:
LOG('Zope', ERROR, '_delObject() threw',
error=sys.exc_info())
# In debug mode when non-Manager, let exceptions propagate.
if getConfiguration().debug_mode:
if not getSecurityManager().getUser().has_role('Manager'):
raise
self._objects=tuple(filter(lambda i,n=id: i['id']!=n, self._objects))
self._delOb(id) self._delOb(id)
# Indicate to the object that it has been deleted. This is # Indicate to the object that it has been deleted. This is
...@@ -357,8 +372,13 @@ class ObjectManager( ...@@ -357,8 +372,13 @@ class ObjectManager(
# tolerate failure here because the object being deleted could # tolerate failure here because the object being deleted could
# be a Broken object, and it is not possible to set attributes # be a Broken object, and it is not possible to set attributes
# on Broken objects. # on Broken objects.
try: object._v__object_deleted__ = 1 try:
except: pass ob._v__object_deleted__ = 1
except:
pass
if not suppress_events:
notify(ObjectRemovedEvent(ob, self, id))
def objectIds(self, spec=None): def objectIds(self, spec=None):
# Returns a list of subobject ids of the current object. # Returns a list of subobject ids of the current object.
......
...@@ -30,7 +30,7 @@ from IOrderSupport import IOrderedContainer as z2IOrderedContainer ...@@ -30,7 +30,7 @@ from IOrderSupport import IOrderedContainer as z2IOrderedContainer
from ObjectManager import ObjectManager from ObjectManager import ObjectManager
class OrderSupport: class OrderSupport(object):
""" Ordered container mixin class. """ Ordered container mixin class.
...@@ -251,13 +251,12 @@ class OrderSupport: ...@@ -251,13 +251,12 @@ class OrderSupport:
# Override Inherited Method of ObjectManager Subclass # Override Inherited Method of ObjectManager Subclass
# #
_old_manage_renameObject = ObjectManager.inheritedAttribute(
'manage_renameObject')
def manage_renameObject(self, id, new_id, REQUEST=None): def manage_renameObject(self, id, new_id, REQUEST=None):
""" Rename a particular sub-object without changing its position. """ Rename a particular sub-object without changing its position.
""" """
old_position = self.getObjectPosition(id) old_position = self.getObjectPosition(id)
result = self._old_manage_renameObject(id, new_id, REQUEST) result = super(OrderSupport, self).manage_renameObject(id, new_id,
REQUEST)
self.moveObjectToPosition(new_id, old_position) self.moveObjectToPosition(new_id, old_position)
return result return result
......
...@@ -20,6 +20,7 @@ item types. ...@@ -20,6 +20,7 @@ item types.
$Id$ $Id$
""" """
import warnings
import marshal, re, sys, time import marshal, re, sys, time
import AccessControl.Role, AccessControl.Owned, App.Common import AccessControl.Role, AccessControl.Owned, App.Common
...@@ -60,13 +61,28 @@ class Item(Base, Resource, CopySource, App.Management.Tabs, Traversable, ...@@ -60,13 +61,28 @@ class Item(Base, Resource, CopySource, App.Management.Tabs, Traversable,
isTopLevelPrincipiaApplicationObject=0 isTopLevelPrincipiaApplicationObject=0
def manage_afterAdd(self, item, container): def manage_afterAdd(self, item, container):
pass warnings.warn(
"%s.manage_afterAdd is deprecated and will be removed in "
"Zope 2.11, you should use an IObjectAddedEvent "
"subscriber instead." % self.__class__.__name__,
DeprecationWarning, stacklevel=2)
manage_afterAdd.__five_method__ = True
def manage_beforeDelete(self, item, container): def manage_beforeDelete(self, item, container):
pass warnings.warn(
"%s.manage_beforeDelete is deprecated and will be removed in "
"Zope 2.11, you should use an IObjectWillBeRemovedEvent "
"subscriber instead." % self.__class__.__name__,
DeprecationWarning, stacklevel=2)
manage_beforeDelete.__five_method__ = True
def manage_afterClone(self, item): def manage_afterClone(self, item):
pass warnings.warn(
"%s.manage_afterClone is deprecated and will be removed in "
"Zope 2.11, you should use an IFiveObjectClonedEvent "
"subscriber instead." % self.__class__.__name__,
DeprecationWarning, stacklevel=2)
manage_afterClone.__five_method__ = True
# Direct use of the 'id' attribute is deprecated - use getId() # Direct use of the 'id' attribute is deprecated - use getId()
id='' id=''
......
...@@ -37,6 +37,11 @@ from AccessControl.Permissions import access_contents_information, \ ...@@ -37,6 +37,11 @@ from AccessControl.Permissions import access_contents_information, \
view_management_screens view_management_screens
from zLOG import LOG, INFO, ERROR, WARNING from zLOG import LOG, INFO, ERROR, WARNING
from Products.ZCatalog.Lazy import LazyMap from Products.ZCatalog.Lazy import LazyMap
from zope.event import notify
from zope.app.container.contained import ObjectAddedEvent
from zope.app.container.contained import ObjectRemovedEvent
from Products.Five.event import ObjectWillBeAddedEvent
from Products.Five.event import ObjectWillBeRemovedEvent
manage_addBTreeFolderForm = DTMLFile('folderAdd', globals()) manage_addBTreeFolderForm = DTMLFile('folderAdd', globals())
...@@ -404,47 +409,64 @@ class BTreeFolder2Base (Persistent): ...@@ -404,47 +409,64 @@ class BTreeFolder2Base (Persistent):
'it is already in use.' % id) 'it is already in use.' % id)
def _setObject(self, id, object, roles=None, user=None, set_owner=1): def _setObject(self, id, object, roles=None, user=None, set_owner=1,
v=self._checkId(id) suppress_events=False):
if v is not None: id=v # Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
ob = object # better name, keep original function signature
v = self._checkId(id)
if v is not None:
id = v
# If an object by the given id already exists, remove it. # If an object by the given id already exists, remove it.
if self.has_key(id): if self.has_key(id):
self._delObject(id) self._delObject(id)
self._setOb(id, object) if not suppress_events:
object = self._getOb(id) notify(ObjectWillBeAddedEvent(ob, self, id))
self._setOb(id, ob)
ob = self._getOb(id)
if set_owner: if set_owner:
object.manage_fixupOwnershipAfterAdd() # TODO: eventify manage_fixupOwnershipAfterAdd
# This will be called for a copy/clone, or a normal _setObject.
ob.manage_fixupOwnershipAfterAdd()
# Try to give user the local role "Owner", but only if # Try to give user the local role "Owner", but only if
# no local roles have been set on the object yet. # no local roles have been set on the object yet.
if hasattr(object, '__ac_local_roles__'): if getattr(ob, '__ac_local_roles__', _marker) is None:
if object.__ac_local_roles__ is None: user = getSecurityManager().getUser()
user=getSecurityManager().getUser() if user is not None:
if user is not None: userid = user.getId()
userid=user.getId() if userid is not None:
if userid is not None: ob.manage_setLocalRoles(userid, ['Owner'])
object.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
object.manage_afterAdd(object, self) notify(ObjectAddedEvent(ob, self, id))
maybeCallDeprecated('manage_afterAdd', ob, self)
return id return id
def _delObject(self, id, dp=1): def _delObject(self, id, dp=1, suppress_events=False):
object = self._getOb(id) # Done here to avoid circular imports
try: from Products.Five.subscribers import maybeCallDeprecated
object.manage_beforeDelete(object, self)
except BeforeDeleteException, ob: ob = self._getOb(id)
raise
except ConflictError: maybeCallDeprecated('manage_beforeDelete', ob, self)
raise
except: if not suppress_events:
LOG('Zope', ERROR, 'manage_beforeDelete() threw', notify(ObjectWillBeRemovedEvent(ob, self, id))
error=sys.exc_info())
self._delOb(id) self._delOb(id)
if not suppress_events:
notify(ObjectRemovedEvent(ob, self, id))
# Aliases for mapping-like access. # Aliases for mapping-like access.
__len__ = objectCount __len__ = objectCount
......
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