def remove_ghosts(obj, event): """We are going to remove a object: we need to check if its neutral and remove their indexes also. """ if not IObjectWillBeAddedEvent.providedBy(event) \ and (IObjectWillBeMovedEvent.providedBy(event) or IObjectWillBeRemovedEvent.providedBy(event)): if not is_shared_original(obj): return content_id = IUUID(obj).split('-')[0] site = getSite() try: pc = getToolByName(site, 'portal_catalog') except AttributeError: # In case we are removing the site there is no portal_catalog return language_tool = getToolByName(site, 'portal_languages') language_infos = language_tool.supported_langs for language_info in language_infos: brains = pc.unrestrictedSearchResults( UID=content_id + '-' + language_info) for brain in brains: obj.unrestrictedTraverse(brain.getPath()).unindexObject() brains = pc.unrestrictedSearchResults( UID=content_id) for brain in brains: obj.unrestrictedTraverse(brain.getPath()).unindexObject() if IActionSucceededEvent.providedBy(event): reindex_neutral(obj, event)
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty', ), ('python', )) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual( self.reflecto.manage_renameObjects(('foo', ), ('bar', )), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def testRenameEvents(self): self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('monty',), ('python',)) self.assertEqual(len(getEvents()), 0) self.assertRaises(KeyError, self.reflecto.manage_renameObjects, ('foo', 'monty'), ('bar', 'python')) self.assertEqual(len(getEvents()), 1) events = getEvents(IObjectWillBeMovedEvent) self.assertEqual(len(events), 1) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].newName, 'bar') self.assertEqual(self.reflecto.manage_renameObjects(('foo',), ('bar',)), ['foo']) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[1])) self.assertTrue(IObjectMovedEvent.providedBy(events[2])) self.assertEqual(events[2].oldName, 'foo') self.assertEqual(events[2].newName, 'bar') self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertTrue(events[3].object is self.reflecto)
def handleComentedObject(ob, event): if IObjectAddedEvent.providedBy(event): catalog_comments(ob) elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: catalog_comments(ob) elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: uncatalog_comments(ob)
def onDeviceDeleted(object, event): ''' Clean up the dangling reference to a device if that device has been removed. (Note: we may re-create the device automatically next time someone calls self.ensure_proxy_device, though) ''' if not IObjectWillBeAddedEvent.providedBy(event) and not IObjectWillBeMovedEvent.providedBy(event): if hasattr(object, 'openstackProxyComponentUUID'): component = GUIDManager(object.dmd).getObject(getattr(object, 'openstackProxyComponentUUID', None)) if component: component.release_proxy_device() object.openstackProxyComponentUUID = None
def onDeviceDeleted(object, event): ''' Clean up the dangling reference to a device if that device has been removed. (Note: we may re-create the device automatically next time someone calls self.ensure_proxy_device, though) ''' if not IObjectWillBeAddedEvent.providedBy( event) and not IObjectWillBeMovedEvent.providedBy(event): if hasattr(object, 'openstackProxyComponentUUID'): component = GUIDManager(object.dmd).getObject( getattr(object, 'openstackProxyComponentUUID', None)) if component: component.release_proxy_device() object.openstackProxyComponentUUID = None
def handleContentishEvent(ob, event): """ Event subscriber for (IContentish, IObjectEvent) events. """ if IObjectAddedEvent.providedBy(event): if event.newParent is not None: ob.indexObject() elif IObjectClonedEvent.providedBy(event): ob.notifyWorkflowCreated() elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: ob.indexObject() elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: ob.unindexObject()
def handleOpaqueItemEvent(ob, event): """ Event subscriber for (ICallableOpaqueItemEvents, IObjectEvent) events. """ if IObjectAddedEvent.providedBy(event): if event.newParent is not None: ob.manage_afterAdd(ob, event.newParent) elif IObjectClonedEvent.providedBy(event): ob.manage_afterClone(ob) elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: ob.manage_afterAdd(ob, event.newParent) elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: ob.manage_beforeDelete(ob, event.oldParent)
def handleCookieCrumblerEvent(ob, event): """ Event subscriber for (un)registering a CC as a before traverse hook. """ if not ICookieCrumbler.providedBy(ob): return if IObjectMovedEvent.providedBy(event): if event.newParent is not None: # register before traverse hook handle = ob.meta_type + '/' + ob.getId() nc = BeforeTraverse.NameCaller(ob.getId()) BeforeTraverse.registerBeforeTraverse(event.newParent, nc, handle) elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: # unregister before traverse hook handle = ob.meta_type + '/' + ob.getId() BeforeTraverse.unregisterBeforeTraverse(event.oldParent, handle)
def handleCachingPolicyManagerEvent(ob, event): """ Event subscriber for (un)registering a CPM as CacheManager """ if not ICachingPolicyManager.providedBy(ob): return if IObjectMovedEvent.providedBy(event): if event.newParent is not None: ids = getVerifiedManagerIds(event.newParent) id = ob.getId() if id not in ids: setattr(event.newParent, ZCM_MANAGERS, ids + (id,)) elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: ids = list(getVerifiedManagerIds(event.oldParent)) id = ob.getId() if id in ids: ids.remove(id) setattr(event.oldParent, ZCM_MANAGERS, tuple(ids))
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo', )) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def testCutEvents(self): cp = self.reflecto.manage_cutObjects(('foo',)) self.reflecto['subdir'].manage_pasteObjects(cp) events = getEvents() self.assertEqual(len(events), 4) self.assertTrue(IObjectWillBeMovedEvent.providedBy(events[0])) self.assertEqual(events[0].oldName, 'foo') self.assertEqual(events[0].oldParent, self.reflecto) self.assertEqual(events[0].newName, 'foo') self.assertEqual(events[0].newParent, self.reflecto['subdir']) self.assertTrue(IObjectMovedEvent.providedBy(events[1])) self.assertEqual(events[1].object.getId(), 'foo') self.assertTrue(IContainerModifiedEvent.providedBy(events[2])) self.assertEqual(events[2].object, self.reflecto) self.assertTrue(IContainerModifiedEvent.providedBy(events[3])) self.assertEqual(events[3].object, self.reflecto['subdir'])
def handleContentishEvent(ob, event): """ Event subscriber for (IContentish, IObjectEvent) events. """ if IObjectAddedEvent.providedBy(event): ob.notifyWorkflowCreated() ob.indexObject() elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: ob.indexObject() elif IObjectWillBeMovedEvent.providedBy(event): if event.oldParent is not None: ob.unindexObject() elif IObjectCopiedEvent.providedBy(event): if hasattr(aq_base(ob), 'workflow_history'): del ob.workflow_history elif IObjectCreatedEvent.providedBy(event): if hasattr(aq_base(ob), 'addCreator'): ob.addCreator()
def changeMailingList(ml, event): """An event listener which registers and unregisters lists with the ListLookup utility on list changes. Some framework setup: >>> from zope.app.testing.placelesssetup import setUp, tearDown >>> import Products.Five >>> from Products.Five import zcml >>> setUp() >>> zcml.load_config('meta.zcml', package=Products.Five) >>> zcml.load_config('permissions.zcml', package=Products.Five) >>> zcml.load_config("configure.zcml", package=Products.Five.site) >>> from Products.listen.utilities import tests >>> zcml.load_config('configure.zcml', package=tests) Now let's make a fake mailing list in our site >>> from zope.app.component.hooks import setSite >>> app = self.folder >>> tests.enable_local_site(app) >>> setSite(app) >>> ml = tests.install_fake_ml(app, suppress_events=True) >>> setSite(ml) Then we setup our listener >>> from zope.app.event.interfaces import IObjectModifiedEvent >>> from zope.app.container.interfaces import IObjectMovedEvent >>> from OFS.interfaces import IObjectWillBeRemovedEvent >>> from Products.listen.utilities.list_lookup import changeMailingList >>> from zope.component import handle >>> from Products.listen.interfaces import IMailingList >>> handle([IMailingList, IObjectWillBeRemovedEvent], changeMailingList) >>> handle([IMailingList, IObjectMovedEvent], changeMailingList) >>> handle([IMailingList, IObjectModifiedEvent], changeMailingList) Create and register our utility. Have to do some faking of the component registry stuff to get our mock environment to work: >>> from Products.listen.interfaces import IListLookup >>> from Products.listen.utilities.list_lookup import ListLookup >>> from Products.listen.lib.common import get_utility_for_context >>> sm = app.getSiteManager() >>> sm.registerUtility(ListLookup('list_lookup'), IListLookup) >>> tests.register_fake_component_adapter() >>> ll = get_utility_for_context(IListLookup, context=app) >>> print ll.getListForAddress(ml.mailto) None Send our added event: >>> from zope.event import notify >>> from zope.app.container.contained import ObjectAddedEvent >>> notify(ObjectAddedEvent(ml, app, 'ml')) >>> ll.getListForAddress(ml.mailto) == ml True Change the list and send an event: >>> ml.mailto = '*****@*****.**' >>> from zope.app.event.objectevent import ObjectModifiedEvent >>> notify(ObjectModifiedEvent(ml)) >>> ll.getListForAddress(ml.mailto) == ml True Send a removal event, which should do nothing, as we rely on before removal: >>> from zope.app.container.contained import ObjectRemovedEvent >>> notify(ObjectRemovedEvent(ml, app, 'ml')) >>> ll.getListForAddress(ml.mailto) == ml True Send a before removal event: >>> from OFS.event import ObjectWillBeRemovedEvent >>> notify(ObjectWillBeRemovedEvent(ml)) >>> ll.getListForAddress(ml.mailto) is None True >>> tearDown() """ # Use the new parent object as the context, unless it is unavailable, then # use the list itself parent = None if hasattr(event, 'newParent'): parent = event.newParent if parent is None: parent = ml try: ll = getUtility(IListLookup) except ComponentLookupError: # site won't be set if you delete the Plone site from the ZMI orig_site = getSite() setSite(ml) ll = getUtility(IListLookup, context=ml) setSite(orig_site) if IObjectWillBeAddedEvent.providedBy(event): # Registration is taken care of after add pass elif IObjectWillBeRemovedEvent.providedBy(event): ll.unregisterList(ml) elif IObjectWillBeMovedEvent.providedBy(event): ll.unregisterList(ml) elif IObjectRemovedEvent.providedBy(event): # Unregistration is taken care of before removal pass elif IObjectModifiedEvent.providedBy(event): if not IContainerModifiedEvent.providedBy(event): ll.updateList(ml) elif IObjectAddedEvent.providedBy(event) or IObjectCreatedEvent.providedBy(event): ll.registerList(ml) elif IObjectMovedEvent.providedBy(event): ll.registerList(ml)
def handleContentishEvent(ob, event): """ Event subscriber for (IContentish, IObjectEvent) events. """ if IObjectAddedEvent.providedBy(event): ob.notifyWorkflowCreated() ob.indexObject() elif IObjectMovedEvent.providedBy(event): if event.newParent is not None: if hasattr(aq_base(ob), 'notifyModified'): ob.notifyModified() rid = getattr(ob, '__rid', None) if rid: catalog = api.portal.get_tool('portal_catalog') _catalog = catalog._catalog new_path = '/'.join(ob.getPhysicalPath()) old_path = _catalog.paths[rid] del _catalog.uids[old_path] _catalog.uids[new_path] = rid _catalog.paths[rid] = new_path ob.reindexObject(idxs=[ 'path', 'allowedRolesAndUsers', 'modified', 'id', 'getId' ]) delattr(ob, '__rid') elif event.newParent is not None: # This may happen if "collective.indexing" is installed and an object # is added and renamed/moved in the same transaction (e.g. during the # creation of an object with "plone.api" in a subscriber listening # on "IObjectAddedEvent" as in https://github.com/4teamwork/ftw.events/blob/f1a77440866c6d963961497f68781098c1b4bc8f/ftw/events/configure.zcml#L22). ob.indexObject() elif IObjectWillBeMovedEvent.providedBy(event): from ftw.copymovepatches.utils import getQueue # Prepare Rename if indexing queue is implemented if event.oldParent == event.newParent and getQueue is not None: # The queue needs to be processed, since the `renameObjectsByPaths` # script allows the user to rename the object and also sets a new # title if he wants. # In some circumstances this leads to a inconsistent catalog state. # Mainly if other event handler also triggers a `process` queue by # asking the catalog for something. # The result was for example a "reindex" of a already deleted # object. queue = getQueue() queue.process() # Move/Rename if event.oldParent is not None and event.newParent is not None: catalog = api.portal.get_tool('portal_catalog') ob_path = '/'.join(ob.getPhysicalPath()) if ob_path in catalog._catalog.uids: rid = catalog._catalog.uids[ob_path] setattr(ob, '__rid', rid) else: # This may happen if "collective.indexing" is installed and an object # is added and renamed/moved in the same transaction (e.g. during the # creation of an object with "plone.api" in a subscriber listening # on "IObjectAddedEvent" as in https://github.com/4teamwork/ftw.events/blob/f1a77440866c6d963961497f68781098c1b4bc8f/ftw/events/configure.zcml#L22). return elif event.oldParent is not None: # Delete ob.unindexObject() elif IObjectCopiedEvent.providedBy(event): if hasattr(aq_base(ob), 'workflow_history'): del ob.workflow_history elif IObjectCreatedEvent.providedBy(event): if hasattr(aq_base(ob), 'addCreator'): ob.addCreator()
def changeMailingList(ml, event): """An event listener which registers and unregisters lists with the ListLookup utility on list changes. Some framework setup: >>> from zope.app.testing.placelesssetup import setUp, tearDown >>> import Products.Five >>> from Products.Five import zcml >>> setUp() >>> zcml.load_config('meta.zcml', package=Products.Five) >>> zcml.load_config('permissions.zcml', package=Products.Five) >>> zcml.load_config("configure.zcml", package=Products.Five.site) >>> from Products.listen.utilities import tests >>> zcml.load_config('configure.zcml', package=tests) Now let's make a fake mailing list in our site >>> from zope.app.component.hooks import setSite >>> app = self.folder >>> tests.enable_local_site(app) >>> setSite(app) >>> ml = tests.install_fake_ml(app, suppress_events=True) >>> setSite(ml) Then we setup our listener >>> from zope.app.event.interfaces import IObjectModifiedEvent >>> from zope.app.container.interfaces import IObjectMovedEvent >>> from OFS.interfaces import IObjectWillBeRemovedEvent >>> from Products.listen.utilities.list_lookup import changeMailingList >>> from zope.component import handle >>> from Products.listen.interfaces import IMailingList >>> handle([IMailingList, IObjectWillBeRemovedEvent], changeMailingList) >>> handle([IMailingList, IObjectMovedEvent], changeMailingList) >>> handle([IMailingList, IObjectModifiedEvent], changeMailingList) Create and register our utility. Have to do some faking of the component registry stuff to get our mock environment to work: >>> from Products.listen.interfaces import IListLookup >>> from Products.listen.utilities.list_lookup import ListLookup >>> from Products.listen.lib.common import get_utility_for_context >>> sm = app.getSiteManager() >>> sm.registerUtility(ListLookup('list_lookup'), IListLookup) >>> tests.register_fake_component_adapter() >>> ll = get_utility_for_context(IListLookup, context=app) >>> print ll.getListForAddress(ml.mailto) None Send our added event: >>> from zope.event import notify >>> from zope.app.container.contained import ObjectAddedEvent >>> notify(ObjectAddedEvent(ml, app, 'ml')) >>> ll.getListForAddress(ml.mailto) == ml True Change the list and send an event: >>> ml.mailto = '*****@*****.**' >>> from zope.app.event.objectevent import ObjectModifiedEvent >>> notify(ObjectModifiedEvent(ml)) >>> ll.getListForAddress(ml.mailto) == ml True Send a removal event, which should do nothing, as we rely on before removal: >>> from zope.app.container.contained import ObjectRemovedEvent >>> notify(ObjectRemovedEvent(ml, app, 'ml')) >>> ll.getListForAddress(ml.mailto) == ml True Send a before removal event: >>> from OFS.event import ObjectWillBeRemovedEvent >>> notify(ObjectWillBeRemovedEvent(ml)) >>> ll.getListForAddress(ml.mailto) is None True >>> tearDown() """ # Use the new parent object as the context, unless it is unavailable, then # use the list itself parent = None if hasattr(event, 'newParent'): parent = event.newParent if parent is None: parent = ml try: ll = getUtility(IListLookup) except ComponentLookupError: # site won't be set if you delete the Plone site from the ZMI orig_site = getSite() setSite(ml) ll = getUtility(IListLookup, context=ml) setSite(orig_site) if IObjectWillBeAddedEvent.providedBy(event): # Registration is taken care of after add pass elif IObjectWillBeRemovedEvent.providedBy(event): ll.unregisterList(ml) elif IObjectWillBeMovedEvent.providedBy(event): ll.unregisterList(ml) elif IObjectRemovedEvent.providedBy(event): # Unregistration is taken care of before removal pass elif IObjectModifiedEvent.providedBy(event): if not IContainerModifiedEvent.providedBy(event): ll.updateList(ml) elif IObjectAddedEvent.providedBy(event) or IObjectCreatedEvent.providedBy( event): ll.registerList(ml) elif IObjectMovedEvent.providedBy(event): ll.registerList(ml)