Ejemplo n.º 1
0
    def update(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        count = 0
        kwargs = {}

        if HAS_LINGUAPLONE or HAS_PAM:
            kwargs['Language'] = 'all'

        for brain in catalog(**kwargs):
            obj = brain.getObject()
            if IBaseObject.providedBy(obj):
                modifiedArchetype(obj, 'dummy event parameter')
                count += 1
            elif IDexterityContent.providedBy(obj):
                if IReferenceable.providedBy(obj):
                    modifiedDexterity(obj, 'dummy event parameter')
                count += 1
        return count
Ejemplo n.º 2
0
    def update(self):
        catalog = getToolByName(self.context, 'portal_catalog')
        count = 0
        kwargs = {}

        if HAS_LINGUAPLONE or HAS_PAM:
            kwargs['Language'] = 'all'

        for brain in catalog(**kwargs):
            obj = brain.getObject()
            if IBaseObject.providedBy(obj):
                modifiedArchetype(obj, 'dummy event parameter')
                count += 1
            elif IDexterityContent.providedBy(obj):
                if IReferenceable.providedBy(obj):
                    modifiedDexterity(obj, 'dummy event parameter')
                count += 1
        return count
Ejemplo n.º 3
0
    def __iter__(self):
        # keep a copy of previous generator to post-process items
        self.previous, self.postprocess = itertools.tee(self.previous)

        for item in self.previous:
            yield item

        for item in self.postprocess:

            pathkey = self.pathkey(*item.keys())[0]
            if not pathkey:  # not enough info
                continue
            path = item[pathkey]

            obj = traverse(self.context, str(path).lstrip('/'), None)
            if obj is None:  # object not found
                continue

            if self.key not in item:  # not enough info
                continue

            html = item[self.key]
            # Parse text with regex and call resolve_uid method
            # to fix for every URL
            html = URL_RE.sub(self.resolve_uid, html)

            # Create Rich Text value to update content field
            value = RichTextValue(html, 'text/html', 'text/html')

            # Update object value
            setattr(obj, self.key, value)

            # XXX: this seems to be very expensive
            # Update linkintegrity references
            if IBaseObject.providedBy(obj):
                modifiedArchetype(obj, event=None)
            elif IDexterityContent.providedBy(obj):
                modifiedDexterity(obj, event=None)
Ejemplo n.º 4
0
def link_items(  # noqa
    context,
    source_obj,
    target_obj,
    relationship=None,
    fieldname='relatedItems',
):
    """Add a relation between two content objects.

    This uses the field 'relatedItems' and works for Archetypes and Dexterity.
    By passing a fieldname and a relationship it can be used to create
    arbitrary relations.
    """
    # relations from AT to DX and from DX to AT are only possible through
    # the referenceable-behavior:
    # plone.app.referenceablebehavior.referenceable.IReferenceable
    drop_msg = """Dropping reference from %s to %s since
    plone.app.referenceablebehavior is not enabled!"""

    if source_obj is target_obj:
        # Thou shalt not relate to yourself.
        return

    # if fieldname != 'relatedItems':
    # 'relatedItems' is the default field for AT and DX
    # See plone.app.relationfield.behavior.IRelatedItems for DX and
    # Products.ATContentTypes.content.schemata.relatedItemsField for AT
    # They always use these relationships:
    # 'relatesTo' (Archetpyes) and 'relatedItems' (Dexterity)
    # Maybe be we should handle custom relations somewhat different?

    if relationship in ['relatesTo', 'relatedItems']:
        # These are the two default-relationships used by AT and DX
        # for the field 'relatedItems' respectively.
        pass

    if IDexterityContent.providedBy(source_obj):
        source_type = 'DX'
    else:
        source_type = 'AT'

    if IDexterityContent.providedBy(target_obj):
        target_type = 'DX'
    else:
        target_type = 'AT'

    if relationship == referencedRelationship:
        # 'relatesTo' is the relationship for linkintegrity-relations.
        # Linkintegrity-relations should automatically be (re)created by
        # plone.app.linkintegrity.handlers.modifiedDexterity or
        # plone.app.linkintegrity.handlers.modifiedArchetype
        # when a ObjectModifiedEvent is thrown.
        # These relations are only created if the source has a richtext-field
        # with a link to the target and should not be created manually.
        if source_type == 'AT':
            modifiedArchetype(source_obj, None)
        if source_type == 'DX':
            modifiedDexterity(source_obj, None)
        return

    if source_type == 'AT':
        # If there is any Archetypes-content there is also the
        # reference_catalog. For a site without AT content this
        # might not be there at all.
        reference_catalog = getToolByName(context, REFERENCE_CATALOG)
        uid_catalog = getToolByName(context, 'uid_catalog')
        if target_type == 'DX' and not is_referenceable(target_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return

        # Make sure both objects are properly indexed and referenceable
        # Some objects that werde just created (migrated) are not yet
        # indexed properly.
        source_uid = IUUID(source_obj)
        target_uid = IUUID(target_obj)
        _catalog = uid_catalog._catalog

        if not _catalog.indexes['UID']._index.get(source_uid):
            uid_catalog.catalog_object(source_obj, source_uid)
            modified(source_obj)

        if not _catalog.indexes['UID']._index.get(target_uid):
            uid_catalog.catalog_object(target_obj, target_uid)
            modified(target_obj)

        field = source_obj.getField(fieldname)
        accessor = field.getAccessor(source_obj)
        existing_at_relations = accessor()

        if not isinstance(existing_at_relations, list):
            existing_at_relations = [i for i in existing_at_relations]
        if not existing_at_relations:
            existing_at_relations = []
        if target_obj in existing_at_relations:
            # don't do anything
            return

        target_uid = IUUID(target_obj)
        targetUIDs = [
            ref.targetUID for ref in reference_catalog.getReferences(
                source_obj, relationship)
        ]
        if target_uid in targetUIDs:
            # Drop relation since the old ones are most likely broken.
            reference_catalog.deleteReference(source_obj, target_uid,
                                              relationship)

        existing_at_relations.append(target_obj)
        mutator = field.getMutator(source_obj)
        mutator(existing_at_relations)
        modified(source_obj)
        return

    if source_type is 'DX':
        if target_type is 'AT' and not is_referenceable(source_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return
        # handle dx-relation
        intids = getUtility(IIntIds)
        to_id = intids.getId(target_obj)
        existing_dx_relations = getattr(source_obj, fieldname, [])
        # purge broken relations
        existing_dx_relations = [
            i for i in existing_dx_relations if i.to_id is not None
        ]

        if to_id not in [i.to_id for i in existing_dx_relations]:
            existing_dx_relations.append(RelationValue(to_id))
            setattr(source_obj, fieldname, existing_dx_relations)
            modified(source_obj)
            return
Ejemplo n.º 5
0
def link_items(  # noqa
    context,
    source_obj,
    target_obj,
    relationship=None,
    fieldname='relatedItems',
):
    """Add a relation between two content objects.

    This uses the field 'relatedItems' and works for Archetypes and Dexterity.
    By passing a fieldname and a relationship it can be used to create
    arbitrary relations.
    """
    # relations from AT to DX and from DX to AT are only possible through
    # the referenceable-behavior:
    # plone.app.referenceablebehavior.referenceable.IReferenceable
    drop_msg = """Dropping reference from %s to %s since
    plone.app.referenceablebehavior is not enabled!"""

    if source_obj is target_obj:
        # Thou shalt not relate to yourself.
        return

    # if fieldname != 'relatedItems':
        # 'relatedItems' is the default field for AT and DX
        # See plone.app.relationfield.behavior.IRelatedItems for DX and
        # Products.ATContentTypes.content.schemata.relatedItemsField for AT
        # They always use these relationships:
        # 'relatesTo' (Archetpyes) and 'relatedItems' (Dexterity)
        # Maybe be we should handle custom relations somewhat different?

    if relationship in ['relatesTo', 'relatedItems']:
        # These are the two default-relationships used by AT and DX
        # for the field 'relatedItems' respectively.
        pass

    if IDexterityContent.providedBy(source_obj):
        source_type = 'DX'
    else:
        source_type = 'AT'

    if IDexterityContent.providedBy(target_obj):
        target_type = 'DX'
    else:
        target_type = 'AT'

    if relationship == referencedRelationship:
        # 'relatesTo' is the relationship for linkintegrity-relations.
        # Linkintegrity-relations should automatically be (re)created by
        # plone.app.linkintegrity.handlers.modifiedDexterity or
        # plone.app.linkintegrity.handlers.modifiedArchetype
        # when a ObjectModifiedEvent is thrown.
        # These relations are only created if the source has a richtext-field
        # with a link to the target and should not be created manually.
        if source_type == 'AT':
            modifiedArchetype(source_obj, None)
        if source_type == 'DX':
            modifiedDexterity(source_obj, None)
        return

    if source_type == 'AT':
        # If there is any Archetypes-content there is also the
        # reference_catalog. For a site without AT content this
        # might not be there at all.
        reference_catalog = getToolByName(context, REFERENCE_CATALOG)
        uid_catalog = getToolByName(context, 'uid_catalog')
        if target_type == 'DX' and not is_referenceable(target_obj):
            logger.info(drop_msg % (
                source_obj.absolute_url(), target_obj.absolute_url()))
            return

        # Make sure both objects are properly indexed and referenceable
        # Some objects that werde just created (migrated) are not yet
        # indexed properly.
        source_uid = IUUID(source_obj)
        target_uid = IUUID(target_obj)
        _catalog = uid_catalog._catalog

        if not _catalog.indexes['UID']._index.get(source_uid):
            uid_catalog.catalog_object(source_obj, source_uid)
            modified(source_obj)

        if not _catalog.indexes['UID']._index.get(target_uid):
            uid_catalog.catalog_object(target_obj, target_uid)
            modified(target_obj)

        field = source_obj.getField(fieldname)
        if field is None:
            # we can't migrate if it doesn't actually have the field
            return
        accessor = field.getAccessor(source_obj)
        existing_at_relations = accessor()

        if not isinstance(existing_at_relations, list):
            existing_at_relations = [i for i in existing_at_relations]
        if not existing_at_relations:
            existing_at_relations = []
        if target_obj in existing_at_relations:
            # don't do anything
            return

        target_uid = IUUID(target_obj)
        targetUIDs = [ref.targetUID for ref in reference_catalog.getReferences(
            source_obj, relationship)]
        if target_uid in targetUIDs:
            # Drop relation since the old ones are most likely broken.
            reference_catalog.deleteReference(
                source_obj, target_uid, relationship)

        existing_at_relations.append(target_obj)
        mutator = field.getMutator(source_obj)
        mutator(existing_at_relations)
        modified(source_obj)
        return

    if source_type is 'DX':
        if target_type is 'AT' and not is_referenceable(source_obj):
            logger.info(drop_msg % (
                source_obj.absolute_url(), target_obj.absolute_url()))
            return
        # handle dx-relation
        if relationship == 'translationOf':
            # LinguaPlone relations make no sense for Dexterity
            return

        intids = getUtility(IIntIds)
        to_id = intids.getId(target_obj)
        existing_dx_relations = getattr(source_obj, fieldname, [])
        # purge broken relations
        existing_dx_relations = [
            i for i in existing_dx_relations if i.to_id is not None]

        if to_id not in [i.to_id for i in existing_dx_relations]:
            existing_dx_relations.append(RelationValue(to_id))
            setattr(source_obj, fieldname, existing_dx_relations)
            modified(source_obj)
            return
Ejemplo n.º 6
0
def link_items(  # noqa
    context,
    source_obj,
    target_obj,
    relationship=None,
    fieldname='relatedItems',
):
    """Add a relation between two content objects.

    This uses the field 'relatedItems' and works for Archetypes and Dexterity.
    By passing a fieldname and a relationship it can be used to create
    arbitrary relations.

    Note: for the relatedItems field, Products.ATContentTypes uses 'relatesTo'
    and plone.app.contenttypes uses 'relatedItems'.
    We switch between these two, based on the source object.
    """
    # relations from AT to DX and from DX to AT are only possible through
    # the referenceable-behavior:
    # plone.app.referenceablebehavior.referenceable.IReferenceable
    drop_msg = """Dropping reference from %s to %s since
    plone.app.referenceablebehavior is not enabled!"""

    if source_obj is target_obj:
        # Thou shalt not relate to yourself.
        return

    if IDexterityContent.providedBy(source_obj):
        source_type = 'DX'
    else:
        source_type = 'AT'

    if IDexterityContent.providedBy(target_obj):
        target_type = 'DX'
    else:
        target_type = 'AT'

    if relationship == referencedRelationship:
        # 'isReferencing' is the relationship for linkintegrity-relations.
        # Linkintegrity-relations should automatically be (re)created by
        # plone.app.linkintegrity.handlers.modifiedDexterity or
        # plone.app.linkintegrity.handlers.modifiedArchetype
        # when a ObjectModifiedEvent is thrown.
        # These relations are only created if the source has a richtext-field
        # with a link to the target and should not be created manually.
        if source_type == 'AT':
            modifiedArchetype(source_obj, None)
        if source_type == 'DX':
            modifiedDexterity(source_obj, None)
        return

    if source_type == 'AT':
        if relationship == 'relatedItems':
            relationship = 'relatesTo'
        # If there is any Archetypes-content there is also the
        # reference_catalog. For a site without AT content this
        # might not be there at all.
        reference_catalog = getToolByName(context, REFERENCE_CATALOG)
        uid_catalog = getToolByName(context, 'uid_catalog')
        if target_type == 'DX' and not is_referenceable(target_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return

        # Make sure both objects are properly indexed and referenceable
        # Some objects that werde just created (migrated) are not yet
        # indexed properly.
        source_uid = IUUID(source_obj)
        target_uid = IUUID(target_obj)
        _catalog = uid_catalog._catalog

        if not _catalog.indexes['UID']._index.get(source_uid):
            uid_catalog.catalog_object(source_obj, source_uid)
            modified(source_obj)

        if not _catalog.indexes['UID']._index.get(target_uid):
            uid_catalog.catalog_object(target_obj, target_uid)
            modified(target_obj)

        field = source_obj.getField(fieldname)
        if field is None:
            # we can't migrate if it doesn't actually have the field
            return
        accessor = field.getAccessor(source_obj)
        existing_at_relations = accessor()

        if not isinstance(existing_at_relations, list):
            existing_at_relations = [i for i in existing_at_relations]
        if not existing_at_relations:
            existing_at_relations = []
        if target_obj in existing_at_relations:
            # don't do anything
            return

        target_uid = IUUID(target_obj)
        targetUIDs = [
            ref.targetUID for ref in reference_catalog.getReferences(
                source_obj, relationship)
        ]
        if target_uid in targetUIDs:
            # Drop relation since the old ones are most likely broken.
            reference_catalog.deleteReference(source_obj, target_uid,
                                              relationship)

        existing_at_relations.append(target_obj)
        mutator = field.getMutator(source_obj)
        mutator(existing_at_relations)
        modified(source_obj)
        return

    if source_type is 'DX':
        if relationship == 'relatesTo':
            relationship = 'relatedItems'
        if target_type is 'AT' and not is_referenceable(source_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return
        # handle dx-relation
        if relationship == 'translationOf':
            # LinguaPlone relations make no sense for Dexterity
            return

        intids = getUtility(IIntIds)
        to_id = intids.getId(target_obj)
        # Before we set the fieldname attribute on the source object,
        # we need to know if this should be a list or a single item.
        # Might be None at the moment.
        # We check the field definition.
        fti = getUtility(IDexterityFTI, name=source_obj.portal_type)
        field = None
        for schema in iterSchemataForType(fti):
            field = schema.get(fieldname, None)
            if field is not None:
                break
        if isinstance(field, RelationList):
            existing_relations = getattr(source_obj, fieldname, [])
            if existing_relations is None:
                existing_relations = []
            else:
                # purge broken relations
                existing_relations = [
                    i for i in existing_relations if i.to_id is not None
                ]
            if to_id not in [i.to_id for i in existing_relations]:
                existing_relations.append(RelationValue(to_id))
                setattr(source_obj, fieldname, existing_relations)
                modified(source_obj)
                return
            return
        elif isinstance(field, (Relation, RelationChoice)):
            setattr(source_obj, fieldname, RelationValue(to_id))
            modified(source_obj)
            return

        # We should never end up here!
        logger.warning(
            'Ignoring unknown fieldname %s when restoring relation %s from %s to %s',
            fieldname, relationship, source_obj.absolute_url(),
            target_obj.absolute_url())