def update(self): catalog = getToolByName(self.context, 'portal_catalog') count = 0 for brain in catalog(Language='all'): obj = brain.getObject() if IBaseObject.providedBy(obj): modifiedArchetype(obj, 'dummy event parameter') count += 1 return count
def update(self): catalog = getToolByName(self.context, 'portal_catalog') count = 0 brains = catalog(Language='all') ## In some environments 'Language' index may be patched. ## Let's try to find items without it as well. if not brains: brains = catalog() for brain in brains: obj = brain.getObject() if IBaseObject.providedBy(obj): modifiedArchetype(obj, 'dummy event parameter') count += 1 return count
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
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)
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
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
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())