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
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
ZODB 3.4. As a result, the DBTab package was removed, as
ZODB 3.6 has multidatabase support that makes DBTab
......
......@@ -459,6 +459,10 @@ class AppInitializer:
from Products.Sessions.BrowserIdManager import BrowserIdManager
bid = BrowserIdManager('browser_id_manager', 'Browser Id Manager')
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')
self.commit('Added browser_id_manager')
......@@ -475,6 +479,10 @@ class AppInitializer:
path='/temp_folder/session_data',
requestName='SESSION')
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')
self.commit('Added session_data_manager')
......@@ -523,6 +531,10 @@ class AppInitializer:
from Products.SiteErrorLog.SiteErrorLog import SiteErrorLog
error_log = SiteErrorLog()
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')
self.commit('Added site error_log at /error_log')
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
$Id$
"""
import warnings
import marshal
import sys, fnmatch, copy, os, re
from cgi import escape
......@@ -42,6 +43,11 @@ from zope.interface import implements
import CopySupport
from interfaces import IObjectManager
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
......@@ -266,11 +272,20 @@ class ObjectManager(
raise AttributeError, id
return default
def _setObject(self, id, object, roles=None, user=None, set_owner=1):
v=self._checkId(id)
if v is not None: id=v
try: t=object.meta_type
except: t=None
def _setObject(self, id, object, roles=None, user=None, set_owner=1,
suppress_events=False):
"""Set an object into this container.
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.
for object_info in self._objects:
......@@ -278,78 +293,78 @@ class ObjectManager(
self._delObject(id)
break
self._objects=self._objects+({'id':id,'meta_type':t},)
self._setOb(id,object)
object=self._getOb(id)
if not suppress_events:
notify(ObjectWillBeAddedEvent(ob, self, id))
self._objects = self._objects + ({'id': id, 'meta_type': t},)
self._setOb(id, ob)
ob = self._getOb(id)
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
# no local roles have been set on the object yet.
if hasattr(object, '__ac_local_roles__'):
if object.__ac_local_roles__ is None:
user=getSecurityManager().getUser()
if user is not None:
userid=user.getId()
if userid is not None:
object.manage_setLocalRoles(userid, ['Owner'])
object.manage_afterAdd(object, self)
if getattr(ob, '__ac_local_roles__', _marker) is None:
user = getSecurityManager().getUser()
if user is not None:
userid = user.getId()
if userid is not None:
ob.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
notify(ObjectAddedEvent(ob, self, id))
maybeCallDeprecated('manage_afterAdd', ob, self)
return id
def manage_afterAdd(self, item, container):
for object in self.objectValues():
try: s=object._p_changed
except: s=0
if hasattr(aq_base(object), 'manage_afterAdd'):
object.manage_afterAdd(item, container)
if s is None: object._p_deactivate()
# Don't do recursion anymore, a subscriber does that.
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_afterClone(self, item):
for object in self.objectValues():
try: s=object._p_changed
except: s=0
if hasattr(aq_base(object), 'manage_afterClone'):
object.manage_afterClone(item)
if s is None: object._p_deactivate()
# Don't do recursion anymore, a subscriber does that.
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
def manage_beforeDelete(self, item, container):
for object in self.objectValues():
try: s=object._p_changed
except: s=0
try:
if hasattr(aq_base(object), 'manage_beforeDelete'):
object.manage_beforeDelete(item, container)
except BeforeDeleteException, ob:
raise
except ConflictError:
raise
except:
LOG('Zope',ERROR,'manage_beforeDelete() 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
if s is None: object._p_deactivate()
def _delObject(self, id, dp=1):
object=self._getOb(id)
try:
object.manage_beforeDelete(object, self)
except BeforeDeleteException, ob:
raise
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))
# Don't do recursion anymore, a subscriber does that.
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 _delObject(self, id, dp=1, suppress_events=False):
"""Delete an object from this container.
Also sends IObjectWillBeRemovedEvent and IObjectRemovedEvent.
"""
# Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
ob = self._getOb(id)
maybeCallDeprecated('manage_beforeDelete', ob, self)
if not suppress_events:
notify(ObjectWillBeRemovedEvent(ob, self, id))
self._objects = tuple([i for i in self._objects
if i['id'] != id])
self._delOb(id)
# Indicate to the object that it has been deleted. This is
......@@ -357,8 +372,13 @@ class ObjectManager(
# tolerate failure here because the object being deleted could
# be a Broken object, and it is not possible to set attributes
# on Broken objects.
try: object._v__object_deleted__ = 1
except: pass
try:
ob._v__object_deleted__ = 1
except:
pass
if not suppress_events:
notify(ObjectRemovedEvent(ob, self, id))
def objectIds(self, spec=None):
# Returns a list of subobject ids of the current object.
......
......@@ -30,7 +30,7 @@ from IOrderSupport import IOrderedContainer as z2IOrderedContainer
from ObjectManager import ObjectManager
class OrderSupport:
class OrderSupport(object):
""" Ordered container mixin class.
......@@ -251,13 +251,12 @@ class OrderSupport:
# Override Inherited Method of ObjectManager Subclass
#
_old_manage_renameObject = ObjectManager.inheritedAttribute(
'manage_renameObject')
def manage_renameObject(self, id, new_id, REQUEST=None):
""" Rename a particular sub-object without changing its position.
"""
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)
return result
......
......@@ -20,6 +20,7 @@ item types.
$Id$
"""
import warnings
import marshal, re, sys, time
import AccessControl.Role, AccessControl.Owned, App.Common
......@@ -60,13 +61,28 @@ class Item(Base, Resource, CopySource, App.Management.Tabs, Traversable,
isTopLevelPrincipiaApplicationObject=0
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):
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):
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()
id=''
......
......@@ -37,6 +37,11 @@ from AccessControl.Permissions import access_contents_information, \
view_management_screens
from zLOG import LOG, INFO, ERROR, WARNING
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())
......@@ -404,47 +409,64 @@ class BTreeFolder2Base (Persistent):
'it is already in use.' % id)
def _setObject(self, id, object, roles=None, user=None, set_owner=1):
v=self._checkId(id)
if v is not None: id=v
def _setObject(self, id, object, roles=None, user=None, set_owner=1,
suppress_events=False):
# 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 self.has_key(id):
self._delObject(id)
self._setOb(id, object)
object = self._getOb(id)
if not suppress_events:
notify(ObjectWillBeAddedEvent(ob, self, id))
self._setOb(id, ob)
ob = self._getOb(id)
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
# no local roles have been set on the object yet.
if hasattr(object, '__ac_local_roles__'):
if object.__ac_local_roles__ is None:
user=getSecurityManager().getUser()
if user is not None:
userid=user.getId()
if userid is not None:
object.manage_setLocalRoles(userid, ['Owner'])
object.manage_afterAdd(object, self)
if getattr(ob, '__ac_local_roles__', _marker) is None:
user = getSecurityManager().getUser()
if user is not None:
userid = user.getId()
if userid is not None:
ob.manage_setLocalRoles(userid, ['Owner'])
if not suppress_events:
notify(ObjectAddedEvent(ob, self, id))
maybeCallDeprecated('manage_afterAdd', ob, self)
return id
def _delObject(self, id, dp=1):
object = self._getOb(id)
try:
object.manage_beforeDelete(object, self)
except BeforeDeleteException, ob:
raise
except ConflictError:
raise
except:
LOG('Zope', ERROR, 'manage_beforeDelete() threw',
error=sys.exc_info())
def _delObject(self, id, dp=1, suppress_events=False):
# Done here to avoid circular imports
from Products.Five.subscribers import maybeCallDeprecated
ob = self._getOb(id)
maybeCallDeprecated('manage_beforeDelete', ob, self)
if not suppress_events:
notify(ObjectWillBeRemovedEvent(ob, self, id))
self._delOb(id)
if not suppress_events:
notify(ObjectRemovedEvent(ob, self, id))
# Aliases for mapping-like access.
__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