def test_replace(events):
    """If we try to replace an item without deleting it first, we'll get
    an error.
    """
    container = {}

    # We create a first item
    item = Item()
    setitem(container, container.__setitem__, u'c', item)

    # We try to override
    with pytest.raises(KeyError):
        setitem(container, container.__setitem__, u'c', [])

    # We have to delete to replace a key
    del container[u'c']
    setitem(container, container.__setitem__, u'c', [])

    assert len(events) == 4
    event = events.popleft()
    assert IObjectAddedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectModifiedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectAddedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectModifiedEvent.providedBy(event)
Example #2
0
def moveIntIdSubscriber(ob, event):
    """A subscriber to ObjectMovedEvent

    Updates the stored path for the object in all the unique
    id utilities.
    """
    if IObjectRemovedEvent.providedBy(event) or \
           IObjectAddedEvent.providedBy(event):
        return
    utilities = tuple(getAllUtilitiesRegisteredFor(IIntIds))
    if utilities:
        key = None
        try:
            key = IKeyReference(ob, None)
        except NotYet: # @@ temporary fix
            pass

        # Update objects that adapt to key reference
        if key is not None:
            for utility in utilities:
                try:
                    uid = utility.getId(ob)
                    utility.refs[uid] = key
                    utility.ids[key] = uid
                except KeyError:
                    pass
Example #3
0
def pstsubaction_moved(obj, event):
    """  """
    if IObjectAddedEvent.providedBy(
            event):  # Already managed in above subscriber
        return
    if event.newParent == event.oldParent and event.newName != event.oldName:  # it's not a move but a rename
        return
    # When deleting an action with a subaction, we pass here but the event context is the action !!!!
    if IObjectRemovedEvent.providedBy(event) and obj != event.object:
        return
    # Move of delete
    # we manage the flag on the old pstaction to indicate a subaction presence
    if not event.oldParent.listFolderContents(
        {'object_provides': IPSTSubAction.__identifier__}):
        set_to_annotation('imio.project.pst.has_subactions',
                          False,
                          obj=event.oldParent)
    # move into the moved subaction any existing task found in its new parent action
    if event.newParent:
        if getattr(obj, '_link_portal_type', '') == 'subaction_link':
            raise Invalid(
                "You cannot move a subaction link. Create a new one !")
        tasks = event.newParent.listFolderContents({'portal_type': 'task'})
        for task in tasks:
            api.content.move(task, obj)
        # we set a flag on the pstaction to indicate a subaction presence
        set_to_annotation('imio.project.pst.has_subactions',
                          True,
                          obj=event.newParent)
Example #4
0
def transitionMovedContent(context, action):
    """Transition objects when they have been moved."""
    if IObjectAddedEvent.providedBy(action):
        return
    if IObjectRemovedEvent.providedBy(action):
        return

    wf = getattr(context, "portal_workflow", None)

    if getattr(action.oldParent, "getProjectRoomState", None) is not None:
        if getattr(action.newParent, "getProjectRoomState", None) is None:
            # If an object is moved out of a project room, take ownership.
            becomeOwner(context)
            restoreOwnerPermissions(context)

            # If it uses the intranett_workflow, also hide it.
            if "intranett_workflow" in wf.getChainFor(context):
                wf.doActionFor(context, "hide")
                return
        else:
            # If an object is renamed inside a project room or moved between
            # project rooms, reapply removeOwnerPermissions.
            if wf.getInfoFor(context, "review_state") == "published":
                action.action = "autopublish"  # Abuse existing event
                removeOwnerPermissions(context, action)
                return

    # In all other cases the automatic transitions do the right thing.
    try:
        wf.doActionFor(context, "auto")
    except WorkflowException:
        pass  # This workflow is not ProjectRoom aware.
Example #5
0
def transitionMovedContent(context, action):
    """Transition objects when they have been moved."""
    if IObjectAddedEvent.providedBy(action):
        return
    if IObjectRemovedEvent.providedBy(action):
        return

    wf = getattr(context, 'portal_workflow', None)

    if getattr(action.oldParent, 'getProjectRoomState', None) is not None:
        if getattr(action.newParent, 'getProjectRoomState', None) is None:
            # If an object is moved out of a project room, take ownership.
            becomeOwner(context)
            restoreOwnerPermissions(context)

            # If it uses the intranett_workflow, also hide it.
            if 'intranett_workflow' in wf.getChainFor(context):
                wf.doActionFor(context, "hide")
                return
        else:
            # If an object is renamed inside a project room or moved between
            # project rooms, reapply removeOwnerPermissions.
            if wf.getInfoFor(context, 'review_state') == 'published':
                action.action = 'autopublish'  # Abuse existing event
                removeOwnerPermissions(context, action)
                return

    # In all other cases the automatic transitions do the right thing.
    try:
        wf.doActionFor(context, "auto")
    except WorkflowException:
        pass  # This workflow is not ProjectRoom aware.
def test_move_event(events):
    """If the item had a parent or name (as in a move or rename),
    we generate a move event, rather than an add event.
    """
    container = {}

    # We create a first item
    item = Item()
    setitem(container, container.__setitem__, u'c1', item)

    # Add operation are "moved" events.
    assert len(events) == 2
    event = events.popleft()
    assert IObjectAddedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectModifiedEvent.providedBy(event)
    assert isinstance(event, ContainerModifiedEvent)

    # We created an item already contained.
    item = Item()
    item.__parent__, item.__name__ = container, 'c2'
    setitem(container, container.__setitem__, u'c2', item)
    assert not len(events)

    # We now rewrite 'c2' under another name
    # Thus, we created a move event : +1 modification +1 move.
    setitem(container, container.__setitem__, u'c3', item)
    assert len(container) == 3
    event = events.popleft()
    assert IObjectMovedEvent.providedBy(event)
 def set_what(self, value):
     if IObjectAddedEvent.providedBy(value):
         self.data["what"] = "added"
         self.event = value
     elif IObjectRemovedEvent.providedBy(value):
         self.data["what"] = "removed"
         self.event = value
Example #8
0
def moveIntIdSubscriber(ob, event):
    """A subscriber to ObjectMovedEvent

    Updates the stored path for the object in all the unique
    id utilities.
    """
    if IObjectRemovedEvent.providedBy(event) or \
           IObjectAddedEvent.providedBy(event):
        return
    utilities = tuple(getAllUtilitiesRegisteredFor(IIntIds))
    if utilities:
        key = None
        try:
            key = IKeyReference(ob, None)
        except NotYet:  # @@ temporary fix
            pass

        # Update objects that adapt to key reference
        if key is not None:
            for utility in utilities:
                try:
                    uid = utility.getId(ob)
                    utility.refs[uid] = key
                    utility.ids[key] = uid
                except KeyError:
                    pass
def threadmoved(conv, event):
    """
    send email notification when a thread was moved
    """
    if IObjectRemovedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event):
        return
    n = queryUtility(INotifier)
    n.thread_moved(conv)
Example #10
0
def index_moved_content(content, event):
    """We index all added content (due to a move).
    """
    if getattr(content, "__initialization__", False):
        return

    if not IObjectAddedEvent.providedBy(event) and not IObjectRemovedEvent.providedBy(event):
        ICataloging(content).index()
Example #11
0
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)
Example #12
0
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)
Example #13
0
def index_moved_content(content, event):
    """We index all added content (due to a move).
    """
    if getattr(content, '__initialization__', False):
        return

    if (not IObjectAddedEvent.providedBy(event)
            and not IObjectRemovedEvent.providedBy(event)):
        ICataloging(content).index()
def threadmoved(conv, event):
    """
    Send email notification when a thread was moved
    """
    if IObjectRemovedEvent.providedBy(event) or IObjectAddedEvent.providedBy(event):
        return
    n = queryUtility(INotifier)
    n.thread_moved(conv)
    s = queryUtility(ISubscriptions)
    s.move_subscribers(event)
Example #15
0
def forwardevent(obj, event):
    """ Trigger an ObjectMovedOrRenamedEvent only
    if it's not an ObjectAddedEvent or an ObjectRemovedEvent"""
    if IObjectAddedEvent.providedBy(event) \
        or IObjectRemovedEvent.providedBy(event) \
            or IObjectMovedOrRenamedEvent.providedBy(event):
        return
    notify(
        ObjectMovedOrRenamedEvent(event.object, event.oldParent, event.oldName,
                                  event.newParent, event.newName))
def related_change_on_moved(obj, event):
    """ Set local roles on related objects after moving """
    if IObjectAddedEvent.providedBy(event) or IObjectRemovedEvent.providedBy(event):  # not move
        return
    if event.oldParent and event.newParent and event.oldParent == event.newParent:  # rename
        return
    (fti_config, fti) = fti_configuration(obj)
    if 'static_config' not in fti_config:
        return
    related_role_addition(obj, get_state(obj), fti_config)
Example #17
0
def todo_set_role(obj, evt):
    """ update role for assignees
    """
    todo = ITodo(obj)
    assignee = todo.assignee
    if not assignee and IObjectAddedEvent.providedBy(evt):
        assignee = obj.REQUEST.get('assignee')
    if assignee:
        obj.manage_addLocalRoles(assignee, [
            "Assignee",
        ])
Example #18
0
def moved_event(event):
    # only execute moved event if it's not a added or removed event since
    # those are handled elsewhere and they base off of this event class
    if (IObjectAddedEvent.providedBy(event) or
            IObjectRemovedEvent.providedBy(event)):
        return

    obj = event.object
    if not (IContentish.providedBy(obj) or IComment.providedBy(obj)):
        return
    execute_event(event)
Example #19
0
def forwardevent(obj, event):
    """ Trigger an ObjectMovedOrRenamedEvent only
    if it's not an ObjectAddedEvent or an ObjectRemovedEvent"""
    if IObjectAddedEvent.providedBy(event) \
        or IObjectRemovedEvent.providedBy(event) \
        or IObjectMovedOrRenamedEvent.providedBy(event):
        return
    notify(ObjectMovedOrRenamedEvent(event.object,
                                event.oldParent,
                                event.oldName,
                                event.newParent,
                                event.newName))
def test_interface_providing(events):
    """If the object implements `ILocation`, but not `IContained`, set it's
    `__parent__` and `__name__` attributes *and* declare that it
    implements `IContained`.
    """
    container = {}

    item = Location()
    assert not IContained.providedBy(item)

    setitem(container, container.__setitem__, u'l', item)
    assert container[u'l'] is item
    assert item.__parent__ is container
    assert item.__name__ == u'l'
    assert IContained.providedBy(item)

    # We get added and modification events:
    assert len(events) == 2
    event = events.popleft()
    assert IObjectAddedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectModifiedEvent.providedBy(event)

    # If the object doesn't even implement `ILocation`, put a
    # `ContainedProxy` around it:
    item = []
    setitem(container, container.__setitem__, u'i', item)
    assert container[u'i'] == []
    assert not container[u'i'] is item

    item = container[u'i']
    assert item.__parent__ is container
    assert item.__name__ == u'i'

    assert IContained.providedBy(item)
    event = events.popleft()
    assert IObjectAddedEvent.providedBy(event)
    event = events.popleft()
    assert IObjectModifiedEvent.providedBy(event)
Example #21
0
def document_moved_or_added(context, event):
    if IObjectRemovedEvent.providedBy(event):
        return

    if context.REQUEST.get(DISABLE_DOCPROPERTY_UPDATE_FLAG):
        return

    if IObjectAddedEvent.providedBy(event):
        # Be strict when adding new documents to GEVER, lenient on moving
        # ones that already made it into the system
        _update_docproperties(context, raise_on_error=True)
    else:
        _update_docproperties(context, raise_on_error=False)
def related_change_on_moved(obj, event):
    """ Set local roles on related objects after moving """
    if IObjectAddedEvent.providedBy(event) or IObjectRemovedEvent.providedBy(event):  # not move
        return
    if event.oldParent and event.newParent and event.oldParent == event.newParent:  # rename
        return
    (fti_config, fti) = fti_configuration(obj)
    if not fti_config:
        return
    for (name, f) in get_localrole_fields(fti):
        if name not in fti_config:
            continue
        related_role_addition(obj, get_state(obj), fti_config[name], name)
Example #23
0
def document_moved_or_added(context, event):
    if IObjectRemovedEvent.providedBy(event):
        return

    if context.REQUEST.get(DISABLE_DOCPROPERTY_UPDATE_FLAG):
        return

    if IObjectAddedEvent.providedBy(event):
        # Be strict when adding new documents to GEVER, lenient on moving
        # ones that already made it into the system
        _update_docproperties(context, raise_on_error=True)
    else:
        _update_docproperties(context, raise_on_error=False)
def handle_workspace_move_or_rename(context, event):
    if IObjectRemovedEvent.providedBy(event):
        return  # not a move with new/old, but a removal -- handled elsewhere
    if IObjectAddedEvent.providedBy(event):
        return  # not an add, but a move of existing
    site = getSite()
    pasgroups = ISiteMembers(site).groups
    roster = WorkspaceRoster(context)
    for workgroup in roster.groups.values():
        groupname, title = workgroup.pas_group()
        if groupname not in pasgroups:
            pasgroups.add(groupname, title=title)
        else:
            pasgroups.get(groupname).title = _u(title)
Example #25
0
def related_change_on_moved(obj, event):
    """ Set local roles on related objects after moving """
    if IObjectAddedEvent.providedBy(event) or IObjectRemovedEvent.providedBy(
            event):  # not move
        return
    if event.oldParent and event.newParent and event.oldParent == event.newParent:  # rename
        return
    (fti_config, fti) = fti_configuration(obj)
    if not fti_config:
        return
    for (name, f) in get_localrole_fields(fti):
        if name not in fti_config:
            continue
        related_role_addition(obj, get_state(obj), fti_config[name], name)
Example #26
0
def handle_workspace_move_or_rename(context, event):
    if IObjectRemovedEvent.providedBy(event):
        return  # not a move with new/old, but a removal -- handled elsewhere
    if IObjectAddedEvent.providedBy(event):
        return  # not an add, but a move of existing
    site = getSite()
    pasgroups = ISiteMembers(site).groups
    roster = WorkspaceRoster(context)
    for workgroup in roster.groups.values():
        groupname, title = workgroup.pas_group()
        if groupname not in pasgroups:
            pasgroups.add(groupname, title=title)
        else:
            pasgroups.get(groupname).title = _u(title)
Example #27
0
def purgeOnMovedOrRemoved(object, event):
    request = getRequest()
    confirmed_delete = ('delete_confirmation' in request.URL
                        and request.REQUEST_METHOD == 'POST'
                        and 'form.submitted' in request.form)
    if IObjectRemovedEvent.providedBy(event) and not confirmed_delete:
        # ignore extra delete events
        return
    # Don't purge when added
    if IObjectAddedEvent.providedBy(event):
        return
    if isPurged(object) and 'portal_factory' not in request.URL:
        notify(Purge(object))
    parent = object.getParentNode()
    if parent:
        notify(Purge(parent))
Example #28
0
def update_budget_splits(obj, event=None):
    base_obj = obj._link if base_hasattr(obj, '_link_portal_type') else obj
    expected_objects = {base_obj}
    if IObjectAddedEvent.providedBy(event):
        expected_objects.add(obj)
    for rel in base_obj.back_references():
        expected_objects.add(rel)
    if getattr(base_obj, 'budget_split', None) is None:
        base_obj.budget_split = []
    expected_line_uids = [
        expected_obj.UID() for expected_obj in expected_objects
    ]
    existing_line_uids = [line['uid'] for line in base_obj.budget_split]

    # remove old lines
    for uid_to_remove in set(existing_line_uids).difference(
            expected_line_uids):
        line_to_remove = [
            line for line in base_obj.budget_split
            if line['uid'] == uid_to_remove
        ][0]
        base_obj.budget_split.remove(line_to_remove)

    # add new lines (100 % for base object, 0 % for links)
    for uid_to_add in set(expected_line_uids).difference(existing_line_uids):
        if obj.UID() == uid_to_add:
            object_to_add = obj
        else:
            object_to_add = api.content.get(UID=uid_to_add)
        percentage = 0.0 if base_hasattr(object_to_add,
                                         '_link_portal_type') else 100.0
        title = reference_numbers_title(object_to_add)
        base_obj.budget_split.append({
            'uid': uid_to_add,
            'percentage': percentage,
            'title': title,
        })

    # fix percentages if total isn't equal to 100.0
    current_percentages = sum(
        [line['percentage'] for line in base_obj.budget_split])
    if current_percentages != 100.0:
        corrective_coefficient = 100.0 / current_percentages
        for line in base_obj.budget_split:
            line['percentage'] *= corrective_coefficient
Example #29
0
def object_moved(context, event):
    # Since IObjectAddedEvent subclasses IObjectMovedEvent this event
    # handler is also called for IObjectAddedEvent but we should not
    # do anything in this case.
    if IObjectAddedEvent.providedBy(event):
        return

    # Skip automatically renamed objects during copy & paste process.
    if ICopyPasteRequestLayer.providedBy(getRequest()):
        return

    title = _(u'label_object_moved',
              default=u'Object moved: ${title}',
              mapping={'title': context.title_or_id()})

    journal_entry_factory(context.aq_inner.aq_parent, OBJECT_MOVED_EVENT,
                          title)
    return
Example #30
0
def object_moved(context, event):
    # Since IObjectAddedEvent subclasses IObjectMovedEvent this event
    # handler is also called for IObjectAddedEvent but we should not
    # do anything in this case.
    if IObjectAddedEvent.providedBy(event):
        return

    # Skip automatically renamed objects during copy & paste process.
    if ICopyPasteRequestLayer.providedBy(getRequest()):
        return

    title = _(u'label_object_moved',
              default=u'Object moved: ${title}',
              mapping={'title': context.title_or_id()}
              )

    journal_entry_factory(
        context.aq_inner.aq_parent, OBJECT_MOVED_EVENT, title)
    return
Example #31
0
def update_todo_state(obj, event):
    """
    After editing a Todo item, set the workflow state to either Open or Planned
    depending on the state of the Case.
    Also update access permissions on the Case, which might have changed due to
    a change in assignment.

    """
    # Do nothing on copy
    if IObjectCopiedEvent.providedBy(event):
        return

    if IObjectAddedEvent.providedBy(event):
        # This attribute is set when copying from a template
        # handle_case_workflow_state_changed will take care of everything
        if getattr(event.newParent, '_v_skip_update_todo_state', None):
            return
    obj.set_appropriate_state()
    obj.reindexObject()
    parent = parent_workspace(obj)
    if ICase.providedBy(parent):
        parent.update_case_access()
    def get_what_info(self, event):
        #Archetypes
        if IObjectEditedEvent.providedBy(event):
            return self.get_object_modified_info(event)
        elif IObjectInitializedEvent.providedBy(event):
            return self.get_object_modified_info(event)
        #plone
        elif IConfigurationChangedEvent.providedBy(event):
            return self.get_configuration_changed_info(event)
#        #plone.app.form (formlib)
#        elif IEditSavedEvent.providedBy(event):
#            return 'editsaved'
#        #plone.app.iterate
#        elif ICheckinEvent.providedBy(event):
#            return 'checkedin'
#        elif ICheckoutEvent.providedBy(event):
#            return 'checkedout'
#        elif IWorkingCopyDeletedEvent.providedBy(event):
#            return 'workingcopydeleted'
#        #plone.app.registry
        elif IRecordModifiedEvent.providedBy(event):
            return self.get_record_modified_info(event)
        # DCWorkflow
        elif ITransitionEvent.providedBy(event):
            return self.get_transition_info(event)
        # CMFCore
        elif IActionSucceededEvent.providedBy(event):
            return self.get_action_succeed_info(event)
        # zope
        elif IObjectCopiedEvent.providedBy(event):
            return self.get_object_copied_info(event)
        elif IObjectMovedEvent.providedBy(event):
            return self.get_object_moved_info(event)
        elif IObjectAddedEvent.providedBy(event):
            return self.get_object_moved_info(event)
        elif IObjectRemovedEvent.providedBy(event):
            return self.get_object_moved_info(event)
Example #33
0
    def __call__(self):
        req = getRequest()
        if req.environ.get('disable.auditlog', False):
            return True

        event = self.event
        obj = event.object
        # order of those checks is important since some interfaces
        # base off the others
        rule = inspect.stack()[1][0].f_locals.get('self', None)
        registry = getUtility(IRegistry)
        trackWorkingCopies = registry['collective.auditlog.interfaces.IAuditLogSettings.trackworkingcopies']  # noqa

        if not self.canExecute(rule, req):
            return True  # cut out early, we can't do this event

        data = {
            'info': ''
        }

        if IPloneFormGenField.providedBy(obj):
            # if ploneformgen field, use parent object for modified data
            data['field'] = obj.getId()
            obj = aq_parent(obj)

        # the order of those interface checks matters since some interfaces
        # inherit from others
        if IObjectRemovedEvent.providedBy(event):
            # need to keep track of removed events so it doesn't get called
            # more than once for each object
            action = 'removed'
        elif (IObjectInitializedEvent.providedBy(event) or
                IObjectCreatedEvent.providedBy(event) or
                IObjectAddedEvent.providedBy(event)):
            action = 'added'
        elif IObjectMovedEvent.providedBy(event):
            # moves can also be renames. Check the parent object
            if event.oldParent == event.newParent:
                if rule is None or 'Rename' in rule.rule.title:
                    info = {'previous_id': event.oldName}
                    data['info'] = json.dumps(info)
                    action = 'rename'
                else:
                    # cut out here, double action for this event
                    return True
            else:
                if rule is None or 'Moved' in rule.rule.title:
                    parent_path = '/'.join(event.oldParent.getPhysicalPath())
                    previous_location = parent_path + '/' + event.oldName
                    info = {'previous_location': previous_location}
                    data['info'] = json.dumps(info)
                    action = 'moved'
                else:
                    # step out immediately since this could be a double action
                    return True
        elif IObjectModifiedEvent.providedBy(event):
            action = 'modified'
        elif IActionSucceededEvent.providedBy(event):
            info = {'transition': event.action,
                    'comments': self.get_history_comment()}
            data['info'] = json.dumps(info)
            action = 'workflow'
        elif IObjectClonedEvent.providedBy(event):
            action = 'copied'
        elif ICheckinEvent.providedBy(event):
            info = {'message': event.message}
            data['info'] = json.dumps(info)
            action = 'checked in'
            req.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        elif IBeforeCheckoutEvent.providedBy(event):
            action = 'checked out'
            req.environ['disable.auditlog'] = True
        elif ICancelCheckoutEvent.providedBy(event):
            action = 'cancel check out'
            req.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        elif IUserLoggedInEvent.providedBy(event):
            action = 'logged in'
            info = {'user': event.object.getUserName()}
            data['info'] = json.dumps(info)
        elif IUserLoggedOutEvent.providedBy(event):
            action = 'logged out'
        else:
            logger.warn('no action matched')
            return True

        if IWorkingCopy.providedBy(obj):
            # if working copy, iterate, check if Track Working Copies is
            # enabled
            if trackWorkingCopies:
                # if enabled in control panel, use original object and move
                # working copy path to working_copy
                data['working_copy'] = '/'.join(obj.getPhysicalPath())
                relationships = obj.getReferences(
                    WorkingCopyRelation.relationship)
                # check relationships, if none, something is wrong, not logging
                # action
                if len(relationships) > 0:
                    obj = relationships[0]
                else:
                    return True
            else:
                # if not enabled, we only care about checked messages
                if 'check' not in action:
                    return True

        data.update(getObjectInfo(obj))
        data['action'] = action

        addLogEntry(obj, data)
        return True
Example #34
0
    def __call__(self):
        event = self.event
        service_to_ping = self.element.service_to_ping
        obj = self.event.object
        container = obj.getParentNode()
        noasync_msg = 'No instance for async operations was defined.'

        def pingCRSDS(service_to_ping, obj_url, create):
            """ Ping the CR/SDS service
            """
            options = {}
            options['service_to_ping'] = service_to_ping
            options['obj_url'] = self.sanitize_url(obj_url)
            options['create'] = create

            # Use RabbitMQ if available
            if self.rabbit_config:
                options['create'] = 'create' if options.get(
                    'create', False) else 'update'
                return ping_RabbitMQ(options)

            # Use zc.async if available
            if async_service is None:
                logger.warn("Can't pingCRSDS, plone.app.async not installed!")
                return

            queue = async_service.getQueues()['']
            try:
                async_service.queueJobInQueue(
                    queue, ('rdf',),
                    ping_CRSDS, self.context, options
                )
            except ComponentLookupError:
                logger.info(noasync_msg)

        def pingCRSDS_backrel(service_to_ping, obj, create):
            """ Ping backward relations
            """
            if hasattr(obj, 'getBRefs'):
                back_relations = obj.getBRefs('relatesTo')
            else:
                back_relations = [o.to_object
                    for o in getattr(obj, 'relatedItems')
                ]

            for rel in back_relations:
                if rel is not None:
                    obj_url = "%s/@@rdf" % rel.absolute_url()
                    pingCRSDS(service_to_ping, obj_url, create)

        def pingCRSDS_children(service_to_ping, obj, create):
            """ Ping all sub-objects
            """
            if obj.portal_type == "Discussion Item":
                # 22047 skip object if it's of type Discussion Item
                return
            for child in obj.objectIds():
                child_obj = obj.get(child)
                if not child_obj:
                    logger.info(
                        "Couldn't retrieve child id %s for %s",
                        child, obj.absolute_url())
                    continue
                obj_url = "%s/@@rdf" % child_obj.absolute_url()
                pingCRSDS(service_to_ping, obj_url, create)
                pingCRSDS_children(service_to_ping, child_obj, create)

        # When no request the task is called from a async task, see #19830
        request = getattr(obj, 'REQUEST', None)

        # Detect special object used to force acquisition, see #18904
        if isinstance(request, str):
            request = None

        create = IObjectAddedEvent.providedBy(event)

        if service_to_ping == "":
            return

        if hasVersionsInstalled and IVersionEnhanced.providedBy(obj) \
                and request:
            obj_versions = IGetVersions(obj).versions()
        else:
            obj_versions = [obj]

        async_service = queryUtility(IAsyncService)

        # If object has translations
        if hasLinguaPloneInstalled and ITranslatable.providedBy(obj):
            if obj.isCanonical():
                # Ping all translations
                for trans in obj.getTranslations().items():
                    if trans[0] != 'en':
                        trans_obj = trans[1][0]
                        obj_url = trans_obj.absolute_url()
                        pingCRSDS(service_to_ping, obj_url, create)
            else:
                # Ping only canonical
                can_obj = obj.getCanonical()
                obj_url = can_obj.absolute_url()
                pingCRSDS(service_to_ping, obj_url, create)

        # If object was deleted
        if IObjectRemovedEvent.providedBy(event):
            # Ping backward relations
            pingCRSDS_backrel(service_to_ping, obj, create)

            # Ping all sub-objects
            pingCRSDS_children(service_to_ping, obj, create)

        # If object was moved/renamed first ping with the old object's URL
        if IObjectMovedOrRenamedEvent.providedBy(event):
            obj_url = "%s/%s/@@rdf" % (event.oldParent.absolute_url(),
                                       event.oldName)
            pingCRSDS(service_to_ping, obj_url, False)

            # then ping with the container of the old object
            obj_url = "%s/@@rdf" % event.oldParent.absolute_url()
            pingCRSDS(service_to_ping, obj_url, False)

            # Ping backward relations
            pingCRSDS_backrel(service_to_ping, obj, create)

            # Ping all sub-objects
            pingCRSDS_children(service_to_ping, obj, create)

        # Ping each version
        for obj in obj_versions:
            obj_url = "%s/@@rdf" % obj.absolute_url()
            pingCRSDS(service_to_ping, obj_url, create)

        # If no Aquisition there is no container, see #18904
        if container:
            obj_url = "%s/@@rdf" % container.absolute_url()
            pingCRSDS(service_to_ping, obj_url, False)

        return True
Example #35
0
    def __call__(self):
        event = self.event
        service_to_ping = self.element.service_to_ping
        obj = self.event.object
        container = obj.getParentNode()
        noasync_msg = 'No instance for async operations was defined.'

        def pingCRSDS(service_to_ping, obj_url, create):
            """ Ping the CR/SDS service
            """
            if async_service is None:
                logger.warn("Can't pingCRSDS, plone.app.async not installed!")
                return

            options = {}
            options['service_to_ping'] = service_to_ping
            options['obj_url'] = self.sanitize_url(obj_url)
            options['create'] = create
            queue = async_service.getQueues()['']
            try:
                async_service.queueJobInQueue(queue, ('rdf', ), ping_CRSDS,
                                              self.context, options)
            except ComponentLookupError:
                logger.info(noasync_msg)

        def pingCRSDS_backrel(service_to_ping, obj, create):
            """ Ping backward relations
            """
            back_relations = obj.getBRefs('relatesTo')
            for rel in back_relations:
                if rel is not None:
                    obj_url = "%s/@@rdf" % rel.absolute_url()
                    pingCRSDS(service_to_ping, obj_url, create)

        def pingCRSDS_children(service_to_ping, obj, create):
            """ Ping all sub-objects
            """
            if obj.portal_type == "Discussion Item":
                # 22047 skip object if it's of type Discussion Item
                return
            for child in obj.objectIds():
                child_obj = obj.get(child)
                if not child_obj:
                    logger.info("Couldn't retrieve child id %s for %s", child,
                                obj.absolute_url())
                    continue
                obj_url = "%s/@@rdf" % child_obj.absolute_url()
                pingCRSDS(service_to_ping, obj_url, create)
                pingCRSDS_children(service_to_ping, child_obj, create)

        # When no request the task is called from a async task, see #19830
        request = getattr(obj, 'REQUEST', None)

        # Detect special object used to force acquisition, see #18904
        if isinstance(request, str):
            request = None

        create = IObjectAddedEvent.providedBy(event)

        if service_to_ping == "":
            return

        if hasVersionsInstalled and IVersionEnhanced.providedBy(obj) \
                and request:
            obj_versions = IGetVersions(obj).versions()
        else:
            obj_versions = [obj]

        async_service = queryUtility(IAsyncService)

        # If object has translations
        if hasLinguaPloneInstalled and ITranslatable.providedBy(obj):
            if obj.isCanonical():
                # Ping all translations
                for trans in obj.getTranslations().items():
                    if trans[0] != 'en':
                        trans_obj = trans[1][0]
                        obj_url = trans_obj.absolute_url()
                        pingCRSDS(service_to_ping, obj_url, create)
            else:
                # Ping only canonical
                can_obj = obj.getCanonical()
                obj_url = can_obj.absolute_url()
                pingCRSDS(service_to_ping, obj_url, create)

        # If object was deleted
        if IObjectRemovedEvent.providedBy(event):
            # Ping backward relations
            pingCRSDS_backrel(service_to_ping, obj, create)

            # Ping all sub-objects
            pingCRSDS_children(service_to_ping, obj, create)

        # If object was moved/renamed first ping with the old object's URL
        if IObjectMovedOrRenamedEvent.providedBy(event):
            obj_url = "%s/%s/@@rdf" % (event.oldParent.absolute_url(),
                                       event.oldName)
            pingCRSDS(service_to_ping, obj_url, False)

            # then ping with the container of the old object
            obj_url = "%s/@@rdf" % event.oldParent.absolute_url()
            pingCRSDS(service_to_ping, obj_url, False)

            # Ping backward relations
            pingCRSDS_backrel(service_to_ping, obj, create)

            # Ping all sub-objects
            pingCRSDS_children(service_to_ping, obj, create)

        # Ping each version
        for obj in obj_versions:
            obj_url = "%s/@@rdf" % obj.absolute_url()
            pingCRSDS(service_to_ping, obj_url, create)

        # If no Aquisition there is no container, see #18904
        if container:
            obj_url = "%s/@@rdf" % container.absolute_url()
            pingCRSDS(service_to_ping, obj_url, False)

        return True
Example #36
0
 def test_notify_events_by_default(self):
     create(Builder('book').having(title=u'Testtitle'))
     created_event, added_event = self.portal.fired_events
     self.assertTrue(IObjectCreatedEvent.providedBy(created_event))
     self.assertTrue(IObjectAddedEvent.providedBy(added_event))
Example #37
0
    def getLogEntry(self):
        ''' Get's a log entry for your action
        '''
        event = self.event
        obj = event.object
        data = {'info': ''}

        # order of those checks is important since some interfaces
        # base off the others
        if IPloneFormGenField.providedBy(obj):
            # if ploneformgen field, use parent object for modified data
            data['field'] = obj.getId()
            obj = aq_parent(obj)

        # the order of those interface checks matters since some interfaces
        # inherit from others
        if IObjectRemovedEvent.providedBy(event):
            # need to keep track of removed events so it doesn't get called
            # more than once for each object
            action = 'removed'
        elif (IObjectInitializedEvent.providedBy(event)
              or IObjectCreatedEvent.providedBy(event)
              or IObjectAddedEvent.providedBy(event)):
            action = 'added'
        elif IObjectMovedEvent.providedBy(event):
            # moves can also be renames. Check the parent object
            if event.oldParent == event.newParent:
                if 'Rename' not in self.rule.rule.title:
                    # cut out here, double action for this event
                    return {}
                data['info'] = 'previous id: %s' % event.oldName
                action = 'rename'
            else:
                if 'Moved' not in self.rule.rule.title:
                    # step out immediately since this could be a double action
                    return {}
                data['info'] = 'previous location: %s/%s' % (
                    '/'.join(event.oldParent.getPhysicalPath()),
                    event.oldName,
                )
                action = 'moved'
        elif IObjectModifiedEvent.providedBy(event):
            action = 'modified'
        elif IActionSucceededEvent.providedBy(event):
            data['info'] = 'workflow transition: %s; comments: %s' % (
                event.action,
                self.get_history_comment(),
            )
            action = 'workflow'
        elif IObjectClonedEvent.providedBy(event):
            action = 'copied'
        elif ICheckinEvent.providedBy(event):
            data['info'] = event.message
            action = 'checked in'
            self.request.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        elif IBeforeCheckoutEvent.providedBy(event):
            action = 'checked out'
            self.request.environ['disable.auditlog'] = True
        elif ICancelCheckoutEvent.providedBy(event):
            action = 'cancel check out'
            self.request.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        else:
            logger.warn('no action matched')
            return {}

        if IWorkingCopy.providedBy(obj):
            # if working copy, iterate, check if Track Working Copies is
            # enabled
            if not self.trackWorkingCopies:
                # if not enabled, we only care about checked messages
                if 'check' not in action:
                    return {}
            # if enabled in control panel, use original object and move
            # working copy path to working_copy
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            relationships = obj.getReferences(WorkingCopyRelation.relationship)
            # check relationships, if none, something is wrong, not logging
            # action
            if len(relationships) <= 0:
                return {}
            obj = relationships[0]

        data.update(self._getObjectInfo(obj))
        data['action'] = action
        return data
Example #38
0
def log_moved(context, event):
    is_remove = IObjectRemovedEvent.providedBy(event)
    is_add = IObjectAddedEvent.providedBy(event)
    if is_add or is_remove:
        return
    ModificationLogger().moved(context)
Example #39
0
    def getLogEntry(self):
        ''' Get's a log entry for your action
        '''
        event = self.event
        obj = event.object
        data = {'info': ''}

        # order of those checks is important since some interfaces
        # base off the others
        if IPloneFormGenField.providedBy(obj):
            # if ploneformgen field, use parent object for modified data
            data['field'] = obj.getId()
            obj = aq_parent(obj)

        # the order of those interface checks matters since some interfaces
        # inherit from others
        if IObjectRemovedEvent.providedBy(event):
            # need to keep track of removed events so it doesn't get called
            # more than once for each object
            action = 'removed'
        elif (
            IObjectInitializedEvent.providedBy(event) or
            IObjectCreatedEvent.providedBy(event) or
            IObjectAddedEvent.providedBy(event)
        ):
            action = 'added'
        elif IObjectMovedEvent.providedBy(event):
            # moves can also be renames. Check the parent object
            if event.oldParent == event.newParent:
                if 'Rename' not in self.rule.rule.title:
                    # cut out here, double action for this event
                    return {}
                data['info'] = 'previous id: %s' % event.oldName
                action = 'rename'
            else:
                if 'Moved' not in self.rule.rule.title:
                    # step out immediately since this could be a double action
                    return {}
                data['info'] = 'previous location: %s/%s' % (
                    '/'.join(event.oldParent.getPhysicalPath()),
                    event.oldName,
                )
                action = 'moved'
        elif IObjectModifiedEvent.providedBy(event):
            action = 'modified'
        elif IActionSucceededEvent.providedBy(event):
            data['info'] = 'workflow transition: %s; comments: %s' % (
                event.action,
                self.get_history_comment(),
            )
            action = 'workflow'
        elif IObjectClonedEvent.providedBy(event):
            action = 'copied'
        elif ICheckinEvent.providedBy(event):
            data['info'] = event.message
            action = 'checked in'
            self.request.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        elif IBeforeCheckoutEvent.providedBy(event):
            action = 'checked out'
            self.request.environ['disable.auditlog'] = True
        elif ICancelCheckoutEvent.providedBy(event):
            action = 'cancel check out'
            self.request.environ['disable.auditlog'] = True
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            obj = event.baseline
        else:
            logger.warn('no action matched')
            return {}

        if IWorkingCopy.providedBy(obj):
            # if working copy, iterate, check if Track Working Copies is
            # enabled
            if not self.trackWorkingCopies:
                # if not enabled, we only care about checked messages
                if 'check' not in action:
                    return {}
            # if enabled in control panel, use original object and move
            # working copy path to working_copy
            data['working_copy'] = '/'.join(obj.getPhysicalPath())
            relationships = obj.getReferences(
                WorkingCopyRelation.relationship)
            # check relationships, if none, something is wrong, not logging
            # action
            if len(relationships) <= 0:
                return {}
            obj = relationships[0]

        data.update(self._getObjectInfo(obj))
        data['action'] = action
        return data