def deleteDocument(self, doc): """ Delete the document from database. """ if not self.isCurrentUserAuthor(doc): if hasattr(self, 'REQUEST'): self.writeMessageOnPage("You cannot delete this document.", self.REQUEST, error=False) raise Unauthorized, "You cannot delete this document." else: # execute the onDeleteDocument code of the form form = doc.getForm() if form: message = None try: message = self.runFormulaScript( SCRIPT_ID_DELIMITER.join(['form', form.id, 'ondelete']), doc, form.onDeleteDocument) except PlominoScriptException, e: e.reportError('Document has been deleted, ' 'but onDelete event failed.') if message: # Abort deletion if hasattr(self, 'REQUEST'): doc.writeMessageOnPage(message, self.REQUEST, False) self.REQUEST.RESPONSE.redirect(doc.absolute_url()) return None self.getIndex().unindexDocument(doc) if self.getIndexInPortal(): self.portal_catalog.uncatalog_object( "/".join(self.getPhysicalPath() + (doc.id, ))) event.notify(ObjectRemovedEvent(doc, self.documents, doc.id)) self.documents._delOb(doc.id)
def test_components_unregistered_on_delete_does_not_error_with_no_components( self): # noqa portal_type = 'testtype' fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, Interface) site_manager_mock = self.mocker.proxy( PersistentComponents(bases=(getGlobalSiteManager(), ))) getSiteManager_mock = self.mocker.replace( 'zope.component.hooks.getSiteManager') self.expect(getSiteManager_mock(dummy_site)).result(site_manager_mock) # We expect to always be able to unregister without error, even if the # components do not exists (as here) self.expect( site_manager_mock.unregisterUtility( provided=IDexterityFTI, name=portal_type)).passthrough() self.replay() ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId()))
def test_deleted_factory_not_unregistered_if_not_unique(self): portal_type = u"testtype" fti = DexterityFTI(portal_type, factory='common-factory') portal_type2 = u"testtype2" fti2 = DexterityFTI(portal_type2, factory='common-factory') container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, ISiteRoot) site_manager_mock = Mock(wraps=PersistentComponents( bases=(getGlobalSiteManager(), ))) from zope.component.hooks import getSiteManager self.patch_global(getSiteManager, return_value=site_manager_mock) # Pretend two FTIs are registered, both using common-factory # NB: Assuming that "testtype" was already removed when this gets # called site_manager_mock.registeredUtilities = Mock(return_value=[ self.create_dummy(provided=IFactory, name='common-factory', info='plone.dexterity.dynamic'), self.create_dummy(component=fti2, provided=IDexterityFTI, name='testtype2', info='plone.dexterity.dynamic'), ]) ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) # We shouldn't remove this since fti2 still uses it # The type itself should be removed though site_manager_mock.unregisterUtility.assert_called_once_with( provided=IDexterityFTI, name=u'testtype')
def test_global_components_not_unregistered_on_delete(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, ISiteRoot) site_manager_mock = Mock(wraps=PersistentComponents( bases=(getGlobalSiteManager(), ))) from zope.component.hooks import getSiteManager self.patch_global(getSiteManager, return_value=site_manager_mock) # Register FTI utility and factory utility self.mock_utility(fti, IDexterityFTI, name=portal_type) self.mock_utility(DexterityFactory(portal_type), IFactory, name=portal_type) # We expect to always be able to unregister without error, even if the # component exists. The factory is only unregistered if it was # registered with info='plone.dexterity.dynamic'. ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) site_dummy = self.create_dummy( getSiteManager=lambda: site_manager_mock) setSite(site_dummy) setHooks() self.assertNotEquals(None, queryUtility(IDexterityFTI, name=portal_type)) self.assertNotEquals(None, queryUtility(IFactory, name=portal_type))
def test_components_unregistered_on_delete(self): portal_type = u"testtype" fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, ISiteRoot) site_manager_mock = Mock(wraps=PersistentComponents( bases=(getGlobalSiteManager(), ))) from zope.component.hooks import getSiteManager self.patch_global(getSiteManager, return_value=site_manager_mock) # First add the components ftiAdded(fti, ObjectAddedEvent(fti, container_dummy, fti.getId())) # Then remove them again ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) site_dummy = self.create_dummy( getSiteManager=lambda: site_manager_mock) setSite(site_dummy) setHooks() self.assertEqual(None, queryUtility(IDexterityFTI, name=portal_type)) self.assertEqual(None, queryUtility(IFactory, name=portal_type))
def _delObject(self, id): object = self._getOb(id) notify(ObjectWillBeRemovedEvent(object, self, id)) if hasattr(aq_base(object), 'manage_beforeDelete'): object.manage_beforeDelete(object, self) self._delOb(id) notify(ObjectRemovedEvent(object, self, id)) notifyContainerModified(self)
def delete(self, id): # We need to fire an ObjectRemovedEvent ourselves here because # self[id].__parent__ is not exactly the same as self, which # in the end means that __delitem__ does not fire an # ObjectRemovedEvent for us. # # Also, now we can say the oldParent is the issue instead of # this adapter. event = ObjectRemovedEvent(self[id], oldParent=self.context, oldName=id) self.remove(self[id]) notify(event)
def test_deleted_factory_not_unregistered_if_not_unique(self): portal_type = 'testtype' fti = DexterityFTI(portal_type, factory='common-factory') portal_type2 = 'testtype2' fti2 = DexterityFTI(portal_type2, factory='common-factory') container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, Interface) site_manager_mock = self.mocker.proxy( PersistentComponents(bases=(getGlobalSiteManager(), ))) getSiteManager_mock = self.mocker.replace( 'zope.component.hooks.getSiteManager') self.expect( getSiteManager_mock(dummy_site)).result(site_manager_mock).count( 1, None) # Pretend two FTIs are registered, both using common-factory # NB: Assuming that 'testtype' was already removed when this gets # called self.expect(site_manager_mock.registeredUtilities()).result([ self.create_dummy(provided=IFactory, name='common-factory', info='plone.dexterity.dynamic'), self.create_dummy(component=fti2, provided=IDexterityFTI, name='testtype2', info='plone.dexterity.dynamic'), ]) # We shouldn't remove this since fti2 still uses it self.expect( site_manager_mock.unregisterUtility( provided=IFactory, name='common-factory')).count(0) # The type itself should be removed though self.expect( site_manager_mock.unregisterUtility(provided=IDexterityFTI, name='testtype')).count(1) self.replay() ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId()))
def _remove(self, obj=None, suppress_events=False): """remove object from our side of a relationship""" if obj: objs = [obj] else: objs = self.objectValuesAll() if not suppress_events: for robj in objs: notify(ObjectWillBeRemovedEvent(robj, self, robj.getId())) if obj: id = obj.id if not self._objects.has_key(id): raise ObjectNotFound("object %s not found on %s" % (obj.getPrimaryId(), self.getPrimaryId())) del self._objects[id] else: self._objects = OOBTree() self.__primary_parent__._p_changed = True if not suppress_events: for robj in objs: notify(ObjectRemovedEvent(robj, self, robj.getId()))
def test_global_components_not_unregistered_on_delete(self): portal_type = 'testtype' fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, Interface) site_manager_mock = self.mocker.proxy( PersistentComponents(bases=(getGlobalSiteManager(), ))) getSiteManager_mock = self.mocker.replace( 'zope.component.hooks.getSiteManager') self.expect(getSiteManager_mock(dummy_site)).result(site_manager_mock) # Register FTI utility and factory utility self.mock_utility(fti, IDexterityFTI, name=portal_type) self.mock_utility(DexterityFactory(portal_type), IFactory, name=portal_type) # We expect to always be able to unregister without error, even if the # component exists. The factory is only unregistered if it was # registered with info='plone.dexterity.dynamic'. self.expect( site_manager_mock.unregisterUtility( provided=IDexterityFTI, name=portal_type)).passthrough() self.replay() ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) site_dummy = self.create_dummy( getSiteManager=lambda: site_manager_mock) setSite(site_dummy) setHooks() self.assertNotEquals(None, queryUtility(IDexterityFTI, name=portal_type)) self.assertNotEquals(None, queryUtility(IFactory, name=portal_type))
def test_components_unregistered_on_delete(self): portal_type = 'testtype' fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, Interface) site_manager_mock = self.mocker.proxy( PersistentComponents(bases=(getGlobalSiteManager(), ))) getSiteManager_mock = self.mocker.replace( 'zope.component.hooks.getSiteManager') self.expect( getSiteManager_mock(dummy_site)).result(site_manager_mock).count( 1, None) # We expect to always be able to unregister without error, even if the # components do not exists (as here) self.expect( site_manager_mock.unregisterUtility( provided=IDexterityFTI, name=portal_type)).passthrough() self.expect( site_manager_mock.unregisterUtility( provided=IFactory, name=portal_type)).passthrough() self.replay() # First add the components ftiAdded(fti, ObjectAddedEvent(fti, container_dummy, fti.getId())) # Then remove them again ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) site_dummy = self.create_dummy( getSiteManager=lambda: site_manager_mock) setSite(site_dummy) setHooks() self.assertEqual(None, queryUtility(IDexterityFTI, name=portal_type)) self.assertEqual(None, queryUtility(IFactory, name=portal_type))
def test_components_unregistered_on_delete_does_not_error_with_no_components(self): # noqa portal_type = u"testtype" fti = DexterityFTI(portal_type) container_dummy = self.create_dummy() # Mock the lookup of the site and the site manager at the site root dummy_site = self.create_dummy() self.mock_utility(dummy_site, ISiteRoot) site_manager_mock = Mock( wraps=PersistentComponents(bases=(getGlobalSiteManager(),))) from zope.component.hooks import getSiteManager self.patch_global(getSiteManager, return_value=site_manager_mock) # We expect to always be able to unregister without error, even if the # components do not exist (as here) ftiRemoved(fti, ObjectRemovedEvent(fti, container_dummy, fti.getId())) site_manager_mock.unregisterUtility.assert_called_once_with( provided=IDexterityFTI, name=portal_type)
def deleteDocument(self, doc): """ Delete the document from database. """ if not self.isCurrentUserAuthor(doc): raise Unauthorized, "You cannot delete this document." else: # execute the onDeleteDocument code of the form form = doc.getForm() if form: try: self.runFormulaScript("form_" + form.id + "_ondelete", doc, form.onDeleteDocument) except PlominoScriptException, e: e.reportError( 'Document has been deleted, but onDelete event failed.' ) self.getIndex().unindexDocument(doc) if self.getIndexInPortal(): self.portal_catalog.uncatalog_object( "/".join(self.getPhysicalPath() + (doc.id, ))) event.notify(ObjectRemovedEvent(doc, self.documents, doc.id)) self.documents._delOb(doc.id)
class DeleteForm(PageForm): """Delete-form for Bungeni content. Confirmation The user is presented with a confirmation form which details the items that are going to be deleted. Subobjects Recursively, a permission check is carried out for each item that is going to be deleted. If a permission check fails, an error message is displayed to the user. Will redirect back to the container on success. """ form_template = NamedTemplate("alchemist.form") template = ViewPageTemplateFile("templates/delete.pt") #template = z3evoque.PageViewTemplateFile("delete.html") _next_url = None form_fields = formlib.form.Fields() def _can_delete_item(self, action): return True def nextURL(self): return self._next_url def update(self): self.subobjects = self.get_subobjects() super(DeleteForm, self).update() def get_subobjects(self): return () def delete_subobjects(self): return 0 @formlib.form.action(_(u"Delete"), name="delete", condition=_can_delete_item) def handle_delete(self, action, data): count = self.delete_subobjects() container = self.context.__parent__ trusted = removeSecurityProxy(self.context) session = Session() session.delete(trusted) count += 1 try: session.flush() except IntegrityError, e: # this should not happen in production; it's a critical # error, because the transaction might have failed in the # second phase of the commit session.rollback() log.critical(e) self.status = _( "Could not delete item due to database integrity error. " "You may wish to try deleting any related sub-records first?") return self.render() #TODO: check that it is removed from the index! notify( ObjectRemovedEvent(self.context, oldParent=container, oldName=self.context.__name__)) # we have to switch our context here otherwise the deleted object will # be merged into the session again and reappear magically self.context = container cascade_modifications(container) next_url = self.nextURL() if next_url is None: next_url = url.absoluteURL(container, self.request) + \ "/?portal_status_message=%d items deleted" % count if self.is_headless: log.info("Deleting in headless mode - No redirection") else: self.request.response.redirect(next_url)
class DeleteForm(PageForm): """Delete-form for Bungeni content. Confirmation The user is presented with a confirmation form which details the items that are going to be deleted. Subobjects Recursively, a permission check is carried out for each item that is going to be deleted. If a permission check fails, an error message is displayed to the user. Will redirect back to the container on success. """ # evoque template = z3evoque.PageViewTemplateFile("delete.html") # zpt # !+form_template(mr, jul-2010) this is unused here, but needed by # some adapter of this "object delete" view #form_template = NamedTemplate("alchemist.form") #template = ViewPageTemplateFile("templates/delete.pt") _next_url = None form_fields = formlib.form.Fields() def _can_delete_item(self, action): return True def nextURL(self): return self._next_url def update(self): self.subobjects = self.get_subobjects() super(DeleteForm, self).update() def get_subobjects(self): return () def delete_subobjects(self): return 0 @formlib.form.action(_(u"Delete"), condition=_can_delete_item) def handle_delete(self, action, data): count = self.delete_subobjects() container = self.context.__parent__ trusted = removeSecurityProxy(self.context) session = Session() session.delete(trusted) count += 1 try: session.flush() except IntegrityError, e: # this should not happen in production; it's a critical # error, because the transaction might have failed in the # second phase of the commit session.rollback() log.critical(e) self.status = _(u"Could not delete item due to " "database integrity error") return self.render() # !+SESSION_CLOSE(taras.sterch, july-2011) there is no need to close the # session. Transaction manager will take care of this. Hope it does not # brake anything. #session.close() #TODO: check that it is removed from the index! notify( ObjectRemovedEvent(self.context, oldParent=container, oldName=self.context.__name__)) # we have to switch our context here otherwise the deleted object will # be merged into the session again and reappear magically self.context = container next_url = self.nextURL() if next_url is None: next_url = url.absoluteURL(container, self.request) + \ "/?portal_status_message=%d items deleted" % count self.request.response.redirect(next_url)
def delete(self, id): event = ObjectRemovedEvent(self[id], oldParent=self.context, oldName=id) self.remove(id) notify(event)