def on_removed_resource(resource, event): request = getattr(resource, 'REQUEST', None) if request is None: return info = ILinkIntegrityInfo(request) if info.integrityCheckingEnabled(): if info.getIntegrityBreaches(): return # info.isConfirmedItem simply does not work # it is really awful to have to deal with these internals if 'form.submitted' not in request: return if 'form.button.Cancel' in request: return if getattr(request, 'link_integrity_events_counter', 0) != 2: return log.info('extinguising resource {}'.format(resource.uuid())) db.extinguish_resource(resource.uuid())
def is_relevant(self): request = self.obj.REQUEST if getattr(request, '_activity_reported', False): return False else: setattr(request, '_activity_reported', True) info = ILinkIntegrityInfo(request) if not info.integrityCheckingEnabled(): return True elif info.isConfirmedItem(self.obj): return True if request.URL.endswith('/sl_delete_object'): return True if request.has_key('form.submitted') and \ request.URL.endswith('/delete_confirmation'): return True if request.URL.endswith('/folder_delete'): return True if request.has_key('form.button.Cancel'): return True return False
def isLinked(obj): """ check if the given content object is linked from another one WARNING: don't use this function in your code!! it is a helper for the link integrity code and will potentially abort the ongoing transaction, giving you unexpected results... """ # first check to see if link integrity handling has been enabled at all # and if so, if the removal of the object was already confirmed, i.e. # while replaying the request; unfortunately this makes it necessary # to import from plone.app.linkintegrity here, hence the try block... try: from plone.app.linkintegrity.interfaces import ILinkIntegrityInfo info = ILinkIntegrityInfo(obj.REQUEST) except (ImportError, TypeError): # if p.a.li isn't installed the following check can be cut short... return False if not info.integrityCheckingEnabled(): return False if info.isConfirmedItem(obj): return True # otherwise, when not replaying the request already, it is tried to # delete the object, making it possible to find out if it was referenced, # i.e. in case a link integrity exception was raised linked = False parent = obj.aq_inner.aq_parent try: parent.manage_delObjects(obj.getId()) except OFS.ObjectManager.BeforeDeleteException, e: linked = True
def referencedObjectRemoved(obj, event): """ check if the removal was already confirmed or redirect to the form """ # if the object the event was fired on doesn't have a `REQUEST` attribute # we can safely assume no direct user action was involved and therefore # never raise a link integrity exception... request = aq_get(obj, 'REQUEST', None) if not request: return info = ILinkIntegrityInfo(request) # first we check if link integrity checking was enabled if not info.integrityCheckingEnabled(): return # since the event gets called for every subobject before it's # called for the item deleted directly via _delObject (event.object) # itself, but we do not want to present the user with a confirmation # form for every (referred) subobject, so we remember and skip them... info.addDeletedItem(obj) if obj is not event.object: return # if the number of expected events has been stored to help us prevent # multiple forms (i.e. in folder_delete), we wait for the next event # if we know there will be another... if info.moreEventsToExpect(): return # at this point all subobjects have been removed already, so all # link integrity breaches caused by that have been collected as well; # if there aren't any (after things have been cleaned up), # we keep lurking in the shadows... if not info.getIntegrityBreaches(): return # if the user has confirmed to remove the currently handled item in a # previous confirmation form we won't need it anymore this time around... if info.isConfirmedItem(obj): return # otherwise we raise an exception and pass the object that is supposed # to be removed as the exception value so we can use it as the context # for the view triggered by the exception; this is needed since the # view is an adapter for the exception and a request, so it gets the # exception object as the context, which is not very useful... raise LinkIntegrityNotificationException(obj)
def handle_remove_event(obj, event): """If an object will be removed on the senders instance, we need to create a publisher delete job. """ # the event is notified for every subobject, but we only want to check # the top object which the users tries to delete if obj is not event.object: return workflow = get_workflow_name(obj) if not workflow or workflow not in config.PUBLISHING_WORKFLOWS: # we don't have a workflow or the workflow does not publish ever - so we # don't need to delete anything on the receiver. return # the event handler is fired twice (once from link integrity check), but # we just want to do our stuff once. And we should only do it if the user # already did confirm. do_delete = False request = getattr(obj, 'REQUEST', None) if request is None: do_delete = True else: info = ILinkIntegrityInfo(request) if not info.integrityCheckingEnabled(): do_delete = True elif info.isConfirmedItem(obj): do_delete = True if request.URL.endswith('/sl_delete_object'): do_delete = True if request.has_key('form.submitted') and \ request.URL.endswith('/delete_confirmation'): do_delete = True if request.URL.endswith('/folder_delete'): do_delete = True if request.has_key('form.button.Cancel'): do_delete = True # register the job if do_delete: obj.restrictedTraverse('@@publisher.delete')()
def isLinked(obj): """ check if the given content object is linked from another one WARNING: this function can be time consuming !! It deletes the object in a subtransaction that is rollbacked. In other words, the object is kept safe. Nevertheless, this implies that it also deletes recursively all object's subobjects and references, which can be very expensive. """ # first check to see if link integrity handling has been enabled at all # and if so, if the removal of the object was already confirmed, i.e. # while replaying the request; unfortunately this makes it necessary # to import from plone.app.linkintegrity here, hence the try block... try: from plone.app.linkintegrity.interfaces import ILinkIntegrityInfo info = ILinkIntegrityInfo(obj.REQUEST) except (ImportError, TypeError): # if p.a.li isn't installed the following check can be cut short... return False if not info.integrityCheckingEnabled(): return False if info.isConfirmedItem(obj): return True # otherwise, when not replaying the request already, it is tried to # delete the object, making it possible to find out if it was referenced, # i.e. in case a link integrity exception was raised linked = False parent = obj.aq_inner.aq_parent try: savepoint = transaction.savepoint() parent.manage_delObjects(obj.getId()) except OFS.ObjectManager.BeforeDeleteException: linked = True except: # ignore other exceptions, not useful to us at this point pass finally: savepoint.rollback() return linked