def addRelations(obj, event):
    """Register relations.

    Any relation object on the object will be added.
    """
    for name, relation in _relations(obj):
        rel_event._setRelation(obj, name, relation)
def addRelations(obj, event):
    """Register relations.

    Any relation object on the object will be added.
    """
    for name, relation in _relations(obj):
        rel_event._setRelation(obj, name, relation)
Esempio n. 3
0
def migrate_linkintegrity_relations(context):
    """Migrate linkintegrity-relation from reference_catalog to zc.relation.
    """
    reference_catalog = getToolByName(context, REFERENCE_CATALOG, None)
    intids = getUtility(IIntIds)
    if reference_catalog is not None:
        # Only handle linkintegrity-relations ('isReferencing').
        # [:] copies the full result list to make sure
        # it won't change while we delete references below
        for brain in reference_catalog(relationship=referencedRelationship)[:]:
            try:
                source_obj = uuidToObject(brain.sourceUID)
                target_obj = uuidToObject(brain.targetUID)
            except AttributeError:
                source_obj = target_obj = None
            if source_obj is None or target_obj is None:
                # reference_catalog may be inconsistent
                log.info(
                    'Cannot delete relation since the relation_catalog is inconsistent.'
                )  # noqa: E501
                continue
            # Delete old reference
            reference_catalog.deleteReference(
                source_obj, target_obj, relationship=referencedRelationship)

            # Trigger the recreation of linkintegrity-relation in
            # the relation_catalog (zc.relation)
            target_id = ensure_intid(target_obj, intids)
            if target_id is None:
                continue
            rel = RelationValue(target_id)
            _setRelation(source_obj, referencedRelationship, rel)
Esempio n. 4
0
def updateReferences(obj, refs):
    """Renew all linkintegritry-references.

    Search the zc.relation catalog for linkintegritry-references for this obj.
    Drop them all and set the new ones.
    TODO: Might be improved by not changing anything if the links are the same.
    """
    intids = getUtility(IIntIds)
    try:
        int_id = intids.getId(obj)
    except KeyError:
        # In some cases a object is not yet registered by the intid catalog
        try:
            int_id = intids.register(obj)
        except NotYet:
            return
    catalog = getUtility(ICatalog)
    # unpack the rels before deleting
    old_rels = [
        i
        for i in catalog.findRelations({
            'from_id': int_id,
            'from_attribute': referencedRelationship
        })
    ]
    for old_rel in old_rels:
        catalog.unindex(old_rel)
    for ref in refs:
        _setRelation(obj, referencedRelationship, ref)
Esempio n. 5
0
def updateReferences(obj, refs):
    """Renew all linkintegritry-references.

    Search the zc.relation catalog for linkintegritry-references for this obj.
    Drop them all and set the new ones.
    TODO: Might be improved by not changing anything if the links are the same.
    """
    intids = getUtility(IIntIds)
    try:
        int_id = intids.getId(obj)
    except KeyError:
        # In some cases a object is not yet registered by the intid catalog
        try:
            int_id = intids.register(obj)
        except NotYet:
            return
    catalog = getUtility(ICatalog)
    # unpack the rels before deleting
    old_rels = [i for i in catalog.findRelations(
        {'from_id': int_id,
         'from_attribute': referencedRelationship})]
    for old_rel in old_rels:
        catalog.unindex(old_rel)
    for ref in refs:
        _setRelation(obj, referencedRelationship, ref)
Esempio n. 6
0
def add_behavior_relations(obj, event):
    """Register relations in behaviors.

    This event handler fixes a bug in plone.app.relationfield, which only
    updates the zc.catalog when an object gets modified, but not when it gets
    added.
    """
    for behavior_interface, name, relation in extract_relations(obj):
        _setRelation(obj, name, relation)
Esempio n. 7
0
def add_behavior_relations(obj, event):
    """Register relations in behaviors.

    This event handler fixes a bug in plone.app.relationfield, which only
    updates the zc.catalog when an object gets modified, but not when it gets
    added.
    """
    for behavior_interface, name, relation in extract_relations(obj):
        _setRelation(obj, name, relation)
Esempio n. 8
0
 def copyTo(self, container):
     context = aq_inner(self.context)
     wc = self._copyBaseline(container)
     # get id of objects
     intids = component.getUtility(IIntIds)
     wc_id = intids.getId(wc)
     # create a relation
     relation = StagingRelationValue(wc_id)
     event._setRelation(context, ITERATE_RELATION_NAME, relation)
     return wc, relation
Esempio n. 9
0
    def add_relations_to_relation_catalog(self, old_object, new_object):
        for behavior_interface, name, relation in extract_relations(new_object):
            if isinstance(relation, (str, unicode)):
                # We probably got a UID, but we are working with intids
                # and can not do anything with it, so we skip it.
                LOG.warning('Got a invalid relation ({!r}), which is not '
                            'z3c.relationfield compatible.'.format(relation))
                continue

            _setRelation(new_object, name, relation)
Esempio n. 10
0
 def copyTo(self, container):
     context = aq_inner(self.context)
     wc = self._copyBaseline(container)
     # get id of objects
     intids = component.getUtility(IIntIds)
     wc_id = intids.getId(wc)
     # create a relation
     relation = StagingRelationValue(wc_id)
     event._setRelation(context, ITERATE_RELATION_NAME, relation)
     return wc, relation
Esempio n. 11
0
 def test_references_dx_to_at(self):
     at = create(Builder('page').titled('AT'))
     dx = create(Builder('example dx type').titled(u'DX'))
     at_relation = create_relation('/'.join(at.getPhysicalPath()))
     IRelatedItems(dx).relatedItems = [at_relation]
     _setRelation(dx, 'relatedItems', at_relation)
     self.assertEquals(
         [at],
         list(get_state(dx).get_references())
     )
Esempio n. 12
0
    def test_references_dx_to_dx(self):
        foo = create(Builder('example dx type').titled(u'Foo'))
        bar = create(Builder('example dx type').titled(u'Bar'))

        foo_relation = create_relation('/'.join(foo.getPhysicalPath()))
        IRelatedItems(bar).relatedItems = [foo_relation]
        _setRelation(bar, 'relatedItems', foo_relation)
        self.assertEquals(
            [foo],
            list(get_state(bar).get_references())
        )
Esempio n. 13
0
    def add_relations_to_relation_catalog(self, old_object, new_object):
        for behavior_interface, name, relation in extract_relations(
                new_object):
            if isinstance(relation, (str, six.text_type)):
                # We probably got a UID, but we are working with intids
                # and can not do anything with it, so we skip it.
                LOG.warning('Got a invalid relation ({!r}), which is not '
                            'z3c.relationfield compatible.'.format(relation))
                continue

            _setRelation(new_object, name, relation)
Esempio n. 14
0
 def copyTo( self, container ):
     context = aq_inner( self.context )
     wc = self._copyBaseline( container )
     # get id of objects
     intids = component.getUtility( IIntIds )
     wc_id = intids.getId( wc )
     # create a relation
     relation = StagingRelationValue( wc_id )
     event._setRelation( context, STAGING_RELATION_NAME, relation )
     #
     self._handleReferences( self.context, wc, 'checkout', relation )
     return wc, relation
Esempio n. 15
0
 def toFieldValue(self, value):
     if not value:
         return value
     intids = component.queryUtility(IIntIds)
     for row in value:
         for key in row:
             if row[key] and IRelationChoice.providedBy(self.field.value_type.schema[key]):
                 to_id = intids.queryId(row[key])
                 if to_id:
                     relation = RelationValue(to_id)
                     _setRelation(row[key], key, relation)
                     row[key] = relation
     return value
Esempio n. 16
0
def updateReferences(obj, refs):
    """Renew all linkintegritry-references.

    Search the zc.relation catalog for linkintegritry-references for this obj.
    Drop them all and set the new ones.
    TODO: Might be improved by not changing anything if the links are the same.
    """
    int_id = ensure_intid(obj)
    if int_id is None:
        return
    catalog = getUtility(ICatalog)
    # unpack the rels before deleting
    old_rels = [i for i in catalog.findRelations(
        {'from_id': int_id,
         'from_attribute': referencedRelationship})]
    for old_rel in old_rels:
        catalog.unindex(old_rel)
    for ref in refs:
        _setRelation(obj, referencedRelationship, ref)
def create_media_base_path(obj, event):
    """automatically create related base path"""

    create = api.portal.get_registry_record(
        "collective.behavior.relatedmedia.create_media_container_base_paths",
        default=False,
    )

    if (not create or obj.related_media_base_path
            or getattr(obj.REQUEST, "translation_info", {})):
        # do not create or we already have a value or we create a translation just return
        return

    media_root = get_media_root(obj)

    if media_root is None:
        # do nothing ... no media root path is defined
        return

    # we use UID for media container id to avoid duplicate ids in media root
    media_base_id = obj.UID()

    if media_base_id not in media_root:
        # create base path
        media_base = createContentInContainer(
            media_root,
            "Folder",
            id=media_base_id,
            title=obj.Title(),
        )
    else:
        # XXX: this should never happen?
        media_base = media_root[media_base_id]

    _rel = create_relation("/".join(media_base.getPhysicalPath()))
    # fix RelationValue properties
    _setRelation(obj, "related_media_base_path", _rel)
    obj.related_media_base_path = _rel
Esempio n. 18
0
    def test_delete_confirmation_for_any_reference(self):
        """Test, if delete confirmation shows also a warning if items are
        deleted, which are referenced by other items via a reference field.
        """
        img1 = self.portal['image1']
        doc1 = self.portal['doc1']

        intids_tool = getUtility(IIntIds)
        to_id = intids_tool.getId(img1)
        rel = RelationValue(to_id)
        _setRelation(doc1, 'related_image', rel)

        # Test, if relation is present in the relation catalog
        catalog = getUtility(ICatalog)
        rels = list(catalog.findRelations({'to_id': to_id}))
        self.assertEqual(len(rels), 1)

        # Test, if delete_confirmation_info shows also other relations than
        # ``isReferencing``.
        info = img1.restrictedTraverse('@@delete_confirmation_info')
        breaches = info.get_breaches()
        self.assertEqual(len(breaches), 1)
        self.assertEqual(len(info.get_breaches()[0]['sources']), 1)
Esempio n. 19
0
def link_objects(source, target, relationship):
    """Create a relation from source to target using zc.relation

    For RelationChoice or RelationList it will add the relation as attribute.
    Other relations they will only be added to the relation-catalog.
    """
    if not IDexterityContent.providedBy(source):
        logger.info(u'{} is no dexterity content'.format(source.portal_type))
        return

    if not IDexterityContent.providedBy(target):
        logger.info(u'{} is no dexterity content'.format(target.portal_type))
        return

    relation_catalog = getUtility(ICatalog)
    intids = getUtility(IIntIds)
    to_id = intids.getId(target)
    from_id = intids.getId(source)
    from_attribute = relationship

    # Check if there is exactly this relation.
    # If so remove it and create a fresh one.
    query = {
        'from_attribute': from_attribute,
        'from_id': from_id,
        'to_id': to_id,
    }
    for rel in relation_catalog.findRelations(query):
        relation_catalog.unindex(rel)

    if from_attribute == referencedRelationship:
        # Don't mess with linkintegrity-relations!
        # Refresh them by triggering this subscriber.
        modifiedContent(source, None)
        return

    if from_attribute == ITERATE_RELATION_NAME:
        # Iterate relations use a subclass of RelationValue
        relation = StagingRelationValue(to_id)
        event._setRelation(source, ITERATE_RELATION_NAME, relation)
        return

    field_and_schema = get_field_and_schema_for_fieldname(
        from_attribute, source.portal_type)

    if field_and_schema is None:
        # The relationship is not the name of a field. Only create a relation.
        logger.info(u'No field. Setting relation {} from {} to {}'.format(
            source.absolute_url(), target.absolute_url(), relationship))
        event._setRelation(source, from_attribute, RelationValue(to_id))
        return

    field, schema = field_and_schema

    if isinstance(field, RelationList):
        logger.info('Add relation to relationlist {} from {} to {}'.format(
            from_attribute, source.absolute_url(), target.absolute_url()))
        existing_relations = getattr(source, from_attribute, [])
        existing_relations.append(RelationValue(to_id))
        setattr(source, from_attribute, existing_relations)
        modified(source)
        return

    elif isinstance(field, (Relation, RelationChoice)):
        logger.info('Add relation {} from {} to {}'.format(
            from_attribute, source.absolute_url(), target.absolute_url()))
        setattr(source, from_attribute, RelationValue(to_id))
        modified(source)
        return

    # We should never end up here!
    logger.info('Warning: Unexpected relation {} from {} to {}'.format(
        from_attribute, source.absolute_url(), target.absolute_url()))
Esempio n. 20
0
def restore_relations(context=None, all_relations=None):
    """Restore relations from a annotation on the portal.
    """

    portal = api.portal.get()
    if all_relations is None:
        all_relations = IAnnotations(portal)[RELATIONS_KEY]
    logger.info('Loaded {0} relations to restore'.format(len(all_relations)))
    update_linkintegrity = set()
    modified_items = set()
    modified_relation_lists = defaultdict(list)

    # remove duplicates but keep original order
    unique_relations = []
    seen = set()
    seen_add = seen.add
    for i in all_relations:
        hashable = tuple(i.items())
        if hashable not in seen:
            unique_relations.append(i)
            seen_add(hashable)
        else:
            logger.info(u'Dropping duplicate: {}'.format(hashable))

    if len(unique_relations) < len(all_relations):
        logger.info('Dropping {0} duplicates'.format(
            len(all_relations) - len(unique_relations)))
        all_relations = unique_relations

    intids = getUtility(IIntIds)
    for index, item in enumerate(all_relations, start=1):
        if not index % 500:
            logger.info(u'Restored {} of {} relations...'.format(
                index, len(all_relations)))
        source_obj = uuidToObject(item['from_uuid'])
        target_obj = uuidToObject(item['to_uuid'])

        if not source_obj:
            logger.info(u'{} is missing'.format(item['from_uuid']))
            continue

        if not target_obj:
            logger.info(u'{} is missing'.format(item['to_uuid']))
            continue

        if not IDexterityContent.providedBy(source_obj):
            logger.info(u'{} is no dexterity content'.format(
                source_obj.portal_type))
            continue

        if not IDexterityContent.providedBy(target_obj):
            logger.info(u'{} is no dexterity content'.format(
                target_obj.portal_type))
            continue

        from_attribute = item['from_attribute']
        to_id = intids.getId(target_obj)

        if from_attribute == referencedRelationship:
            # Ignore linkintegrity for now. We'll rebuilt it at the end!
            update_linkintegrity.add(item['from_uuid'])
            continue

        if from_attribute == ITERATE_RELATION_NAME:
            # Iterate relations are not set as values of fields
            relation = StagingRelationValue(to_id)
            event._setRelation(source_obj, ITERATE_RELATION_NAME, relation)
            continue

        field_and_schema = get_field_and_schema_for_fieldname(
            from_attribute, source_obj.portal_type)
        if field_and_schema is None:
            # the from_attribute is no field
            # we could either create a fresh relation or log the case
            logger.info(u'No field. Setting relation: {}'.format(item))
            event._setRelation(source_obj, from_attribute,
                               RelationValue(to_id))
            continue

        field, schema = field_and_schema
        relation = RelationValue(to_id)

        if isinstance(field, RelationList):
            logger.info(
                'Add relation to relationslist {} from {} to {}'.format(
                    from_attribute, source_obj.absolute_url(),
                    target_obj.absolute_url()))
            if item['from_uuid'] in modified_relation_lists.get(
                    from_attribute, []):
                # Do not purge relations
                existing_relations = getattr(source_obj, from_attribute, [])
            else:
                # First touch. Make sure we purge!
                existing_relations = []
            existing_relations.append(relation)
            setattr(source_obj, from_attribute, existing_relations)
            modified_items.add(item['from_uuid'])
            modified_relation_lists[from_attribute].append(item['from_uuid'])
            continue

        elif isinstance(field, (Relation, RelationChoice)):
            logger.info('Add relation {} from {} to {}'.format(
                from_attribute, source_obj.absolute_url(),
                target_obj.absolute_url()))
            setattr(source_obj, from_attribute, relation)
            modified_items.add(item['from_uuid'])
            continue

        else:
            # we should never end up here!
            logger.info('Warning: Unexpected relation {} from {} to {}'.format(
                from_attribute, source_obj.absolute_url(),
                target_obj.absolute_url()))

    update_linkintegrity = set(update_linkintegrity)
    logger.info('Updating linkintegrity for {} items'.format(
        len(update_linkintegrity)))
    for uuid in sorted(update_linkintegrity):
        modifiedContent(uuidToObject(uuid), None)
    logger.info('Updating relations for {} items'.format(len(modified_items)))
    for uuid in sorted(modified_items):
        obj = uuidToObject(uuid)
        # updateRelations from z3c.relationfield does not properly update relations in behaviors
        # that are registered with a marker-interface.
        # update_behavior_relations (from plone.app.relationfield) does that but does not update
        # those in the main schema. Duh!
        updateRelations(obj, None)
        update_behavior_relations(obj, None)

    # purge annotation from portal if they exist
    if RELATIONS_KEY in IAnnotations(portal):
        del IAnnotations(portal)[RELATIONS_KEY]
    logger.info('Done!')
Esempio n. 21
0
def update_behavior_relations(obj, event):
    """Re-register relations in behaviors
    """
    for behavior_interface, name, relation in extract_relations(obj):
        _setRelation(obj, name, relation)
Esempio n. 22
0
 def add_relations_to_relation_catalog(self, old_object, new_object):
     for behavior_interface, name, relation in extract_relations(new_object):
         _setRelation(new_object, name, relation)
Esempio n. 23
0
def update_behavior_relations(obj, event):
    """Re-register relations in behaviors
    """
    for behavior_interface, name, relation in extract_relations(obj):
        _setRelation(obj, name, relation)
def updateRelations(obj, event):
    storage = IWCAnnotator(obj)
    if storage:
        _setRelation(obj, STAGING_RELATION_NAME, storage.get_relation())
Esempio n. 25
0
def restore_relations(context=None, all_relations=None):
    """Restore relations from a annotation on the portal.
    """

    portal = api.portal.get()
    if all_relations is None:
        all_relations = IAnnotations(portal)[RELATIONS_KEY]
    logger.info('Loaded {0} relations to restore'.format(len(all_relations)))
    update_linkintegrity = []
    modified_items = []
    modified_relation_lists = defaultdict(list)

    # remove duplicates but keep original order
    seen = set()
    seen_add = seen.add
    unique_relations = [
        i for i in all_relations
        if not (tuple(i.items()) in seen or seen_add(tuple(i.items())))
    ]

    if len(unique_relations) < len(all_relations):
        logger.info('Dropping {0} duplicates'.format(
            len(all_relations) - len(unique_relations)))
        all_relations = unique_relations

    intids = getUtility(IIntIds)
    for item in all_relations:
        source_obj = uuidToObject(item['from_uuid'])
        target_obj = uuidToObject(item['to_uuid'])

        if not source_obj:
            logger.info(u'{} is missing'.format(item['from_uuid']))
            continue

        if not target_obj:
            logger.info(u'{} is missing'.format(item['to_uuid']))
            continue

        if not IDexterityContent.providedBy(source_obj):
            logger.info(u'{} is no dexterity content'.format(
                source_obj.portal_type))
            continue

        if not IDexterityContent.providedBy(target_obj):
            logger.info(u'{} is no dexterity content'.format(
                target_obj.portal_type))
            continue

        from_attribute = item['from_attribute']
        to_id = intids.getId(target_obj)

        if from_attribute == referencedRelationship:
            # Ignore linkintegrity for now. We'll rebuilt it at the end!
            update_linkintegrity.append(item['from_uuid'])
            continue

        if from_attribute == ITERATE_RELATION_NAME:
            # Iterate relations are not set as values of fields
            relation = StagingRelationValue(to_id)
            event._setRelation(source_obj, ITERATE_RELATION_NAME, relation)
            continue

        fti = getUtility(IDexterityFTI, name=source_obj.portal_type)
        field_and_schema = get_field_and_schema_for_fieldname(
            from_attribute, fti)
        if field_and_schema is None:
            # the from_attribute is no field
            # we could either create a fresh relation or log the case
            logger.info(u'No field. Setting relation: {}'.format(item))
            event._setRelation(source_obj, from_attribute,
                               RelationValue(to_id))
            continue

        field, schema = field_and_schema
        relation = RelationValue(to_id)

        if isinstance(field, RelationList):
            logger.info(
                'Add relation to relationslist {} from {} to {}'.format(
                    from_attribute, source_obj.absolute_url(),
                    target_obj.absolute_url()))
            if item['from_uuid'] in modified_relation_lists.get(
                    from_attribute, []):
                # Do not purge relations
                existing_relations = getattr(source_obj, from_attribute, [])
            else:
                # First touch. Make sure we purge!
                existing_relations = []
            existing_relations.append(relation)
            setattr(source_obj, from_attribute, existing_relations)
            modified_items.append(item['from_uuid'])
            modified_relation_lists[from_attribute].append(item['from_uuid'])
            continue

        elif isinstance(field, (Relation, RelationChoice)):
            logger.info('Add relation {} from {} to {}'.format(
                from_attribute, source_obj.absolute_url(),
                target_obj.absolute_url()))
            setattr(source_obj, from_attribute, relation)
            modified_items.append(item['from_uuid'])
            continue

        else:
            # we should never end up here!
            logger.info('Warning: Unexpected relation {} from {} to {}'.format(
                from_attribute, source_obj.absolute_url(),
                target_obj.absolute_url()))

    to_update = set(update_linkintegrity + modified_items)
    if to_update:
        logger.info('Reindexing {} items'.format(len(to_update)))
    for uuid in sorted(to_update):
        # call modified for all changed items
        modifiedContent(uuidToObject(uuid), None)

    # purge annotation from portal if they exist
    if RELATIONS_KEY in IAnnotations(portal):
        del IAnnotations(portal)[RELATIONS_KEY]