def _potential_relations(obj): """Given an object return tuples of name, index, relation value. Returns both IRelationValue attributes as well as ITemporaryRelationValue attributes. If this is a IRelationList attribute, index will contain the index in the list. If it's a IRelation attribute, index will be None. """ for iface in providedBy(obj).flattened(): for name, field in getFields(iface).items(): if IRelation.providedBy(field): try: relation = getattr(obj, name) except AttributeError: # can't find this relation on the object continue yield name, None, relation if IRelationList.providedBy(field): try: l = getattr(obj, name) except AttributeError: # can't find the relation list on this object continue if l is not None: for i, relation in enumerate(l): yield name, i, relation
def toFieldValue(self, value): """Converts from widget value to field. :param value: List of UID's separated by separator defined :type value: string :returns: List of content objects :rtype: list | tuple | set """ if not value: return self.field.missing_value collectionType = self.field._type if isinstance(collectionType, tuple): collectionType = collectionType[-1] separator = getattr(self.widget, 'separator', ';') value = value.split(separator) if IRelationList.providedBy(self.field): try: catalog = getToolByName(self.widget.context, 'portal_catalog') except AttributeError: catalog = getToolByName(getSite(), 'portal_catalog') objects = {item.UID: item.getObject() for item in catalog(UID=value) if item} return collectionType(objects[uid] for uid in value if uid in objects.keys()) else: return collectionType(v for v in value)
def set(self, data, only_keys=None): if not only_keys: only_keys = data.keys() # relations are done later to avoid circular dependencies errors db = i.IDatabaseGetter(self.context).database() intids = getUtility(IIntIds) for it in [k for k in data if k in only_keys]: value = data[it] field = i.ILiberticEvent.get(it) if IRelationList.providedBy(field) and bool(value): newval = [] for v in value: if not IRelationValue.providedBy(v): v = RelationValue(intids.getId(v)) newval.append(v) value = newval ctx = self.context if it in ['expires', 'effective']: ctx = IPublication(self.context) if (it in ['contained', 'related'] and value): nval = [] for itm in value: if not isinstance(itm, basestring): itm = IUUID(itm) nval.append(itm) value = tuple(nval) setattr(ctx, it, value) IExcludeFromNavigation(self.context).exclude_from_nav = False db.reindexObject()
def copy_fields(self, translation): doomed = False target_language = queryAdapter(translation, ILanguage).get_language() relation_copier = lambda r, l=target_language, f=self.copy_relation: f(r, l) for schema in iterSchemata(self.context): for field_name in schema: if ILanguageIndependentField.providedBy(schema[field_name]): value = getattr(schema(self.context), field_name, _marker) if value == _marker: continue elif IRelationValue.providedBy(value): value = self.copy_relation(value, target_language) elif IRelationList.providedBy(schema[field_name]): value = map(relation_copier, value or []) doomed = True setattr(schema(translation), field_name, value) # If at least one field has been copied over to the translation # we need to inform subscriber to trigger an ObjectModifiedEvent # on that translation. return doomed
def copy_fields(self, translation): doomed = False target_language = queryAdapter(translation, ILanguage).get_language() def relation_copier(rel, lang=target_language, fun=self.copy_relation): return fun(rel, lang) for schema in iterSchemata(self.context): for field_name in schema: if ILanguageIndependentField.providedBy(schema[field_name]): value = getattr(schema(self.context), field_name, _marker) if value == _marker: continue elif IRelationValue.providedBy(value): value = self.copy_relation(value, target_language) elif IRelationList.providedBy(schema[field_name]): value = map(relation_copier, value or []) doomed = True setattr(schema(translation), field_name, value) # If at least one field has been copied over to the translation # we need to inform subscriber to trigger an ObjectModifiedEvent # on that translation. return doomed
def _potential_relations(obj): """Given an object return tuples of name, index, relation value. Returns both IRelationValue attributes as well as ITemporaryRelationValue attributes. If this is a IRelationList attribute, index will contain the index in the list. If it's a IRelation attribute, index will be None. """ for iface in providedBy(obj).flattened(): for name, field in getFields(iface).items(): frel = name + '_rel' _rel = iface.queryTaggedValue(frel) if _rel is not None: field = _rel name = frel if IRelation.providedBy(field): try: relation = getattr(obj, name) except AttributeError: # can't find this relation on the object continue yield name, None, relation if IRelationList.providedBy(field): try: l = getattr(obj, name) except AttributeError: # can't find the relation list on this object continue if l is not None: for i, relation in enumerate(l): yield name, i, relation
def toFieldValue(self, value): """Converts from widget value to field. :param value: List of UID's separated by separator defined :type value: string :returns: List of content objects :rtype: list | tuple | set """ if not value: return self.field.missing_value collectionType = self.field._type if isinstance(collectionType, tuple): collectionType = collectionType[-1] separator = getattr(self.widget, 'separator', ';') value = value.split(separator) if IRelationList.providedBy(self.field): try: catalog = getToolByName(self.widget.context, 'portal_catalog') except AttributeError: catalog = getToolByName(getSite(), 'portal_catalog') objects = { item.UID: item.getObject() for item in catalog(UID=value) if item } return collectionType(objects[uid] for uid in value if uid in objects.keys()) else: return collectionType(v for v in value)
def has_relation_fields(fti): for schema in iterSchemataForType(fti): for fieldname in schema: field = schema[fieldname] if (IRelationChoice.providedBy(field) or IRelationList.providedBy(field)): return True return False
def afterRetrieveModifier(self, obj, repo_clone, preserve=()): """Restore relations from the working copy.""" if IDexterityContent.providedBy(obj): for schemata in iterSchemata(obj): for name, field in getFields(schemata).items(): if IRelationChoice.providedBy(field) or IRelationList.providedBy(field): field.set(field.interface(repo_clone), field.query(field.interface(obj))) return [], [], {}
def afterRetrieveModifier(self, obj, repo_clone, preserve=()): """Restore relations from the working copy.""" if IDexterityContent.providedBy(obj): for schemata in iterSchemata(obj): for name, field in getFields(schemata).items(): if (IRelationChoice.providedBy(field) or IRelationList.providedBy(field)): field.set(field.interface(repo_clone), field.query(field.interface(obj))) return [], [], {}
def set_field_values(self, obj): for name, field in self.iter_fields(obj): if name in self.arguments: value = self.arguments.get(name) if HAS_RELATION and IRelationChoice.providedBy(field): value = self._as_relation_value(value) elif HAS_RELATION and IRelationList.providedBy(field): value = [self._as_relation_value(item) for item in value] field.set(field.interface(obj), value)
def toWidgetValue(self, value): """Converts from field value to widget. :param value: List of catalog brains. :type value: list :returns: List of of UID separated by separator defined on widget. :rtype: string """ if not value: return self.field.missing_value separator = getattr(self.widget, 'separator', ';') if IRelationList.providedBy(self.field): return separator.join([IUUID(o) for o in value if o]) else: return separator.join(v for v in value if v)
def toWidgetValue(self, value): """Converts from field value to widget. :param value: List of catalog brains. :type value: list :returns: List of of UID separated by separator defined on widget. :rtype: string """ if not value: return self.field.missing_value separator = getattr(self.widget, 'separator', ';') if IRelationList.providedBy(self.field): return separator.join([IUUID(o) for o in value if value]) else: return separator.join(v for v in value if v)
def getOnCloneModifiers(self, obj): """Removes relations. """ relations = {} if IDexterityContent.providedBy(obj): for schemata in iterSchemata(obj): for name, field in getFields(schemata).items(): if (IRelationChoice.providedBy(field) or IRelationList.providedBy(field)): field_value = field.query(field.interface(obj)) if field_value is not None: relations[id(aq_base(field_value))] = True def persistent_id(obj): return relations.get(id(obj), None) def persistent_load(obj): return None return persistent_id, persistent_load, [], []
def extract_relations(obj): assignable = IBehaviorAssignable(obj, None) if assignable is None: return for behavior in assignable.enumerateBehaviors(): if behavior.marker != behavior.interface: for name, field in getFields(behavior.interface).items(): if IRelation.providedBy(field): try: relation = getattr(behavior.interface(obj), name) except AttributeError: continue yield behavior.interface, name, relation if IRelationList.providedBy(field): try: l = getattr(behavior.interface(obj), name) except AttributeError: continue if l is not None: for relation in l: yield behavior.interface, name, relation
def get_fieldtype_by_schema(self, field): type_field = "" if IRelationList.providedBy(field): type_field = "relation" elif "ListField" in str(field): type_field = "datagridfield" self.datagrids[field.__name__] = False elif IChoice.providedBy(field): type_field = "choice" elif ITextLine.providedBy(field): type_field = "text" elif IList.providedBy(field): type_field = "list" elif IText.providedBy(field): type_field = "text" elif IRichText.providedBy(field): type_field = "text" else: type_field = "unknown" return type_field
def get_default_value_by_schema(self, field): type_field = " " if IRelationList.providedBy(field): type_field = [] elif "ListField" in str(field): type_field = [] self.datagrids[field.__name__] = False elif IChoice.providedBy(field): type_field = " " elif ITextLine.providedBy(field): type_field = " " elif IList.providedBy(field): type_field = [] elif IText.providedBy(field): type_field = " " elif IRichText.providedBy(field): type_field = " " else: type_field = " " return type_field
def get_blobs_from_relations(value, field): """Extract the blobs from relationfields. """ blobs = [] if IRelationChoice.providedBy(field): rel = value if rel and not rel.isBroken(): rel_obj = rel.to_object if rel_obj.portal_type == 'Image': blobs = [rel_obj.image] elif rel_obj.portal_type == 'File': blobs = [rel_obj.file] if IRelationList.providedBy(field): for rel in value: if rel and not rel.isBroken(): rel_obj = rel.to_object if rel_obj.portal_type == 'Image': blobs.append(rel_obj.image) elif rel_obj.portal_type == 'File': blobs.append(rel_obj.file) return blobs
def extract_relations(obj): assignable = IBehaviorAssignable(obj, None) if assignable is None: return for behavior in assignable.enumerateBehaviors(): if behavior.marker == behavior.interface: continue for name, field in getFields(behavior.interface).items(): if IRelation.providedBy(field): try: relation = getattr(behavior.interface(obj), name) except AttributeError: continue yield behavior.interface, name, relation if IRelationList.providedBy(field): try: rel_list = getattr(behavior.interface(obj), name) except AttributeError: continue if rel_list is not None: for relation in rel_list: yield behavior.interface, name, relation
def validate(self, value): if value: intids = getUtility(IIntIds) checkedout = [] for iid in value: if not IRelationList.providedBy(self.field): iid = int(iid) doc = intids.getObject(int(iid)) else: doc = iid brain = uuidToCatalogBrain(IUUID(doc)) if brain.checked_out: checkedout.append(doc.title) if len(checkedout): raise Invalid(_( u'error_checked_out_document', default=u'The documents (${title}) are still checked out. \ Please checkin them in bevore deliver', mapping={'title': ', '.join(checkedout)}))
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' if 'path' not in query: query['path'] = {} query['path']['query'] = '/'.join(self.context.getPhysicalPath()) brains = catalog(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue value = field.get(field.interface(obj)) if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if IDatetime.providedBy(field) or IDate.providedBy(field): value = api.portal.get_localized_time(value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) if HAS_GEOLOCATION and isinstance(value, Geolocation): value = value.__dict__ item_dict[fieldname] = value # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) return results
def __getattribute__(self, name): if name.startswith('_') or name.startswith( 'portal_') or name.startswith('@@') or name == 'sql_id': return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if name == 'view': #be sure session and sqlitem are up to date self._v_sql_item = None connection.session.close() if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID' and self.sql_virtual: return self.portal_type + '-' + connection.sql_table + '-' + str( self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): if not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) fti = ISQLTypeSettings( getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-' + self.portal_type) title = nameFromTitle.title folder = None if IRelationValue.providedBy(sql_folder_id): folder = sql_folder_id.to_object elif sql_folder_id and sql_folder_id.startswith('/'): portal = getToolByName(getSite(), 'portal_url').getPortalObject() folder = portal.restrictedTraverse(sql_folder_id) if folder: name = INameChooser(folder).chooseName(title, self) return name # return INameChooser(getSite()).chooseName(title, self) # return getUtility(IURLNormalizer).normalize(title) return self.sql_id if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() try: sql_id = getattr(sql_item, connection.sql_id_column, None) except orm_exc.DetachedInstanceError: self._v_sql_item = None sql_item = self.getSQLItem() sql_id = getattr(sql_item, connection.sql_id_column, None) fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_key = sql_column.split('.')[0] sql_item = getattr(sql_item, sql_key, None) if isinstance(sql_item, list): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: if not isinstance(sql_item, list): value = getattr(sql_item, sql_column, None) if not value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): value = '' elif (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [ a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None) ] if name == 'subject': return tuple( [getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IRelationChoice.providedBy( field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get( 'portal_type', []) else: allowed_types = field.value_type.source.query.get( 'portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr( adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName( getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr( tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [ getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None) ] else: valueids = getattr( value, sql_id_column, None) valueids = [str(a) for a in valueids] brains = catalog.unrestrictedSearchResults( portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append( SQLRelationValue( brain.portal_type, brain.UID, self)) if IRelationChoice.providedBy( field) and relations: return relations[0] elif IRelationList.providedBy( field) and relations: return relations elif ITuple.providedBy(field): return tuple( [getattr(a, fieldname, '') for a in value]) elif IList.providedBy(field): return [ getattr(a, fieldname, '') for a in value ] elif value and isinstance(value, list): value = getattr(value[0], fieldname, '') for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): if not value: return '' if not '<p' in value or not '<br' in value: value = '<p>' + '</p><p>'.join([ a for a in value.split('\n') if a.strip() ]) + '</p>' # try: # value = str(value) # except: # try: # value = value.decode('utf-8') # except: # try: # value = value.encode('utf-8') # except: # pass return RichTextValue(unidecode(value)) elif INamedBlobImage.providedBy(field): return NamedBlobImage( base64.b64decode(value), filename=unicode(self.portal_type + self.id + ".jpg")) elif ITuple.providedBy(field): if not value: return tuple([]) try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple( [a.strip() for a in value.split(',')]) elif IList.providedBy(field): if not value: return [] try: return [ a.decode('utf-8') for a in literal_eval(value) ] except: return [a.strip() for a in value.split(',')] elif IDatetime.providedBy(field) and hasattr( value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine( value, datetime.datetime.min.time()) if name in [ 'expiration_date', 'effective_date', 'effective', 'expires' ] and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine( value, datetime.datetime.min.time()) if isinstance(value, unicode) or name == 'id': try: value = str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def __getattribute__(self, name): if name.startswith('_') or name.startswith('portal_') or name.startswith('@@'): return super(SQLDexterityItem, self).__getattribute__(name) if name == 'id' and not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID': return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type) title = nameFromTitle.title if IRelationValue.providedBy(name): folder = sql_folder_id.to_object if folder: return INameChooser(folder).chooseName(title, self) return INameChooser(getSite()).chooseName(title, self) if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_item = getattr(sql_item, sql_column.split('.')[0], None) if sql_item and ((isinstance(sql_item, list) and len(sql_item)>1) or hasattr(sql_item, '_sa_instance_state')): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: value = getattr(sql_item, sql_column, None) #this is a relation if value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)] if name == 'subject': return tuple([getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IList.providedBy(field): return [getattr(a, fieldname, '') for a in value] # hope it has name! elif ITuple.providedBy(field): return tuple([getattr(a, fieldname, '') for a in value]) if IRelationChoice.providedBy(field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get('portal_type', []) else: allowed_types = field.value_type.source.query.get('portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr(adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName(getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr(tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)] else: valueids = getattr(value, sql_id_column, None) brains = catalog.searchResults(portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append(SQLRelationValue(brain.portal_type, brain.sql_id)) if IRelationChoice.providedBy(field) and relations: return relations[0] elif IRelationList.providedBy(field) and relations: return relations for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): return RichTextValue(value) if INamedBlobImage.providedBy(field): return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg")) if IList.providedBy(field): try: return [a.decode('utf-8') for a in literal_eval(value)] except: return [a.strip() for a in value.split(',')] if ITuple.providedBy(field): try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if isinstance(value, unicode) or name == 'id': try: return str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' brains = catalog(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue value = field.get(field.interface(obj)) if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if IDatetime.providedBy(field) or IDate.providedBy(field): value = api.portal.get_localized_time( value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) item_dict[fieldname] = value # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) return results
def __getattribute__(self, name): if name.startswith('_') or name.startswith('portal_') or name.startswith('@@') or name == 'sql_id': return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if name == 'view': #be sure session and sqlitem are up to date self._v_sql_item = None connection.session.close() if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID' and self.sql_virtual: return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): if not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type) title = nameFromTitle.title folder = None if IRelationValue.providedBy(sql_folder_id): folder = sql_folder_id.to_object elif sql_folder_id and sql_folder_id.startswith('/'): portal = getToolByName(getSite(), 'portal_url').getPortalObject() folder = portal.restrictedTraverse(sql_folder_id) if folder: name = INameChooser(folder).chooseName(title, self) return name # return INameChooser(getSite()).chooseName(title, self) # return getUtility(IURLNormalizer).normalize(title) return self.sql_id if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() try: sql_id = getattr(sql_item, connection.sql_id_column, None) except orm_exc.DetachedInstanceError: self._v_sql_item = None sql_item = self.getSQLItem() sql_id = getattr(sql_item, connection.sql_id_column, None) fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_key = sql_column.split('.')[0] sql_item = getattr(sql_item, sql_key, None) if isinstance(sql_item, list): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: if not isinstance(sql_item, list): value = getattr(sql_item, sql_column, None) if not value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): value = '' elif (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)] if name == 'subject': return tuple([getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IRelationChoice.providedBy(field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get('portal_type', []) else: allowed_types = field.value_type.source.query.get('portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr(adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName(getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr(tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)] else: valueids = getattr(value, sql_id_column, None) valueids = [str(a) for a in valueids] brains = catalog.unrestrictedSearchResults(portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append(SQLRelationValue(brain.portal_type, brain.UID, self)) if IRelationChoice.providedBy(field) and relations: return relations[0] elif IRelationList.providedBy(field) and relations: return relations elif ITuple.providedBy(field): return tuple([getattr(a, fieldname, '') for a in value]) elif IList.providedBy(field): return [getattr(a, fieldname, '') for a in value] elif value and isinstance(value, list): value = getattr(value[0], fieldname, '') for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): if not value: return '' if not '<p' in value or not '<br' in value: value = '<p>'+'</p><p>'.join([a for a in value.split('\n') if a.strip()])+'</p>' # try: # value = str(value) # except: # try: # value = value.decode('utf-8') # except: # try: # value = value.encode('utf-8') # except: # pass return RichTextValue(unidecode(value)) elif INamedBlobImage.providedBy(field): return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg")) elif ITuple.providedBy(field): if not value: return tuple([]) try: return tuple([a.decode('utf-8') for a in literal_eval(value)]) except: return tuple([a.strip() for a in value.split(',')]) elif IList.providedBy(field): if not value: return [] try: return [a.decode('utf-8') for a in literal_eval(value)] except: return [a.strip() for a in value.split(',')] elif IDatetime.providedBy(field) and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine(value, datetime.datetime.min.time()) if name in ['expiration_date','effective_date', 'effective', 'expires'] and hasattr(value, 'day') and not hasattr(value, 'hour'): value = datetime.datetime.combine(value, datetime.datetime.min.time()) if isinstance(value, unicode) or name == 'id': try: value = str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def __getattribute__(self, name): if name.startswith('_') or name.startswith( 'portal_') or name.startswith('@@'): return super(SQLDexterityItem, self).__getattribute__(name) if name == 'id' and not self.sql_virtual: return super(SQLDexterityItem, self).__getattribute__(name) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if connection == None and self.portal_type: fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None) if not fti: return None updateConnectionsForFti(fti) connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None) if not connection: return super(SQLDexterityItem, self).__getattribute__(name) if name == 'UID': return self.portal_type + '-' + connection.sql_table + '-' + str( self.sql_id) if name == 'id' and 'id' not in connection.fieldnames.keys(): fti = ISQLTypeSettings( getUtility(IDexterityFTI, name=self.portal_type)) nameFromTitle = INameFromTitle(self, None) if nameFromTitle is not None and nameFromTitle.title: sql_folder_id = getattr(fti, 'sql_folder_id', 'data-' + self.portal_type) title = nameFromTitle.title if IRelationValue.providedBy(name): folder = sql_folder_id.to_object if folder: return INameChooser(folder).chooseName(title, self) return INameChooser(getSite()).chooseName(title, self) if name in connection.fieldnames.keys(): sql_column = connection.fieldnames[name] sql_item = self.getSQLItem() fieldname = 'name' if sql_item and sql_column: while '.' in sql_column: sql_item = getattr(sql_item, sql_column.split('.')[0], None) if sql_item and ( (isinstance(sql_item, list) and len(sql_item) > 1) or hasattr(sql_item, '_sa_instance_state')): value = sql_item fieldname = sql_column.split('.')[-1] break sql_column = '.'.join(sql_column.split('.')[1:]) else: value = getattr(sql_item, sql_column, None) #this is a relation if value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')): sqlftis = [ a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None) ] if name == 'subject': return tuple( [getattr(a, fieldname, '') for a in value]) tableftis = [] for iface in iterSchemataForType(self.portal_type): if name in iface.names(): field = iface[name] if IList.providedBy(field): return [ getattr(a, fieldname, '') for a in value ] # hope it has name! elif ITuple.providedBy(field): return tuple( [getattr(a, fieldname, '') for a in value]) if IRelationChoice.providedBy( field) or IRelationList.providedBy(field): if IRelationChoice.providedBy(field): allowed_types = field.source.query.get( 'portal_type', []) else: allowed_types = field.value_type.source.query.get( 'portal_type', []) tableftis = [] for sqlfti in sqlftis: adapted = ISQLTypeSettings(sqlfti, None) if isinstance(value, list): classname = value[0].__class__.__name__ else: classname = value.__class__.__name__ if adapted and getattr( adapted, 'sql_table', None) == classname: if not allowed_types or sqlfti.id in allowed_types: tableftis.append(adapted) catalog = getToolByName( getSite(), 'portal_catalog') relations = [] for tablefti in tableftis: sql_id_column = getattr( tablefti, 'sql_id_column', 'id') valueids = [] if isinstance(value, list): valueids = [ getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None) ] else: valueids = getattr( value, sql_id_column, None) brains = catalog.searchResults( portal_type=tablefti.id, sql_id=valueids) for brain in brains: relations.append( SQLRelationValue( brain.portal_type, brain.sql_id)) if IRelationChoice.providedBy( field) and relations: return relations[0] elif IRelationList.providedBy( field) and relations: return relations for iface in iterSchemataForType(self.portal_type): if name == 'subject': try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple([a.strip() for a in value.split(',')]) if name in iface.names(): field = iface[name] if IRichText.providedBy(field): return RichTextValue(value) if INamedBlobImage.providedBy(field): return NamedBlobImage( base64.b64decode(value), filename=unicode(self.portal_type + self.id + ".jpg")) if IList.providedBy(field): try: return [ a.decode('utf-8') for a in literal_eval(value) ] except: return [a.strip() for a in value.split(',')] if ITuple.providedBy(field): try: return tuple([ a.decode('utf-8') for a in literal_eval(value) ]) except: return tuple( [a.strip() for a in value.split(',')]) if isinstance(value, unicode) or name == 'id': try: return str(value) except: pass return value return super(SQLDexterityItem, self).__getattribute__(name)
def export_blobs(self, portal_type, blob_type, blacklist, whitelist): """Return a zip-file with file and/or images for the required export. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) if blob_type == 'images': fields = [ i for i in all_fields if INamedImageField.providedBy(i[1]) or INamedBlobImageField.providedBy(i[1])] elif blob_type == 'files': fields = [ i for i in all_fields if INamedFileField.providedBy(i[1]) or INamedBlobFileField.providedBy(i[1])] elif blob_type == 'related': fields = [ i for i in all_fields if IRelationChoice.providedBy(i[1]) or IRelationList.providedBy(i[1])] tmp_file = NamedTemporaryFile() zip_file = zipfile.ZipFile(tmp_file, 'w') catalog = api.portal.get_tool('portal_catalog') query = {'portal_type': portal_type} blobs_found = False if HAS_MULTILINGUAL and 'Language' in catalog.indexes(): query['Language'] = 'all' for brain in catalog(query): obj = brain.getObject() for fieldname, field in fields: # manually filter for fields # if fieldname not in ['primary_picture']: # continue blobs = [] value = field.get(field.interface(obj)) if not value: continue if blob_type != 'related': blobs = [value] elif IRelationChoice.providedBy(field) or \ IRelationList.providedBy(field): blobs = get_blobs_from_relations(value, field) for blob in blobs: if not blob: continue filename = str((blob.filename).encode('utf8')) zip_file.writestr( '{0}_{1}/{2}'.format( brain.UID, # or: brain.id.upper(), fieldname, filename), str(blob.data) ) blobs_found = True zip_file.close() if not blobs_found: return 'No {0} found'.format(blob_type) data = file(tmp_file.name).read() response = self.request.response response.setHeader('content-type', 'application/zip') response.setHeader('content-length', len(data)) response.setHeader( 'content-disposition', 'attachment; filename="{0}.zip"'.format(blob_type)) return response.write(data)
def __iter__(self): # noqa # need to be refactored for item in self.previous: pathkey = self.pathkey(*list(item.keys()))[0] # not enough info if not pathkey: yield item continue path = item[pathkey] # Skip the Plone site object itself if not path: yield item continue obj = self.context.unrestrictedTraverse(path.lstrip("/"), None) # path doesn't exist if obj is None: yield item continue if IDexterityContent.providedBy(obj): uuid = item.get("plone.uuid") if uuid is not None: try: IMutableUUID(obj).set(str(uuid)) except Exception: self.errored.append(item["_original_path"]) files = item.setdefault(self.fileskey, {}) # For all fields in the schema, update in roughly the same way # z3c.form.widget.py would for schemata in iterSchemata(obj): for name, field in getFieldsInOrder(schemata): if name == "id": continue if field.readonly: continue # setting value from the blueprint cue value = item.get(name, _marker) if value is not _marker: if IRelationList.providedBy( field) or IRelationChoice.providedBy( field): # noqa self.transmogrifier.fixrelations.append(( "/".join(obj.getPhysicalPath()), name, value, )) # noqa # Value was given in pipeline, so set it deserializer = queryMultiAdapter((field, obj), IDeserializer) try: value = deserializer( value, files, item, self.disable_constraints, logger=self.log, ) field.set(field.interface(obj), value) continue except Exception: continue # Get the widget's current value, if it has one then # leave it alone value = getMultiAdapter( (obj, field), interfaces.IDataManager).query() if not (value is field.missing_value or value is interfaces.NO_VALUE): continue # Finally, set a default value if nothing is set so far default = queryMultiAdapter( ( obj, obj.REQUEST, # request None, # form field, None, # Widget ), interfaces.IValue, name="default", ) if schemata.__name__ == "IAllowDiscussion": default = item.get("allow_discusion", None) field.set(field.interface(obj), default) continue if default is not None: default = default.get() if default is None: default = getattr(field, "default", None) if default is None: try: default = field.missing_value except AttributeError: pass field.set(field.interface(obj), default) notify(ObjectModifiedEvent(obj)) yield item
def update_data_for_migration(self, item, obj): """Update serialized data to optimze use for migrations. 1. Drop unused data 2. Remove all relationfields (done with the serializer relationvalue_converter) 3. Change some default-fieldnames (AT to DX) 4. Fix issue with AT Text fields 5. Fix collection-criteria 6. Fix image links and scales 7. Fix view names on Folder, Collection, Topic CT's """ # 1. Drop unused data item.pop("@components", None) item.pop("next_item", None) item.pop("previous_item", None) item.pop("immediatelyAddableTypes", None) item.pop("locallyAllowedTypes", None) # 2. Remove all relationfields if HAS_AT and IBaseObject.providedBy(obj): for field in obj.schema.fields(): if isinstance(field, ReferenceField): item.pop(field.__name__, None) elif HAS_DX and HAS_RELATIONS and IDexterityContent.providedBy(obj): for schema in iterSchemata(obj): for name, field in getFields(schema).items(): if IRelationChoice.providedBy(field) or IRelationList.providedBy( field ): item.pop(name, None) # 3. Change default-fieldnames (AT to DX) item = migrate_field(item, "excludeFromNav", "exclude_from_nav") item = migrate_field(item, "allowDiscussion", "allow_discussion") item = migrate_field(item, "subject", "subjects") # Some Date fields item = migrate_field(item, "expirationDate", "expires") item = migrate_field(item, "effectiveDate", "effective") item = migrate_field(item, "creation_date", "created") item = migrate_field(item, "modification_date", "modified") # Event fields item = migrate_field(item, "startDate", "start") item = migrate_field(item, "endDate", "end") item = migrate_field(item, "openEnd", "open_end") item = migrate_field(item, "eventUrl", "event_url") # url cannot be a empty string if item.get("event_url", None) == "": item["event_url"] = None item = migrate_field(item, "wholeDay", "whole_day") item = migrate_field(item, "contactEmail", "contact_email") item = migrate_field(item, "contactName", "contact_name") item = migrate_field(item, "contactPhone", "contact_phone") # 4. Fix issue with AT Text fields # This is done in the ATTextFieldSerializer # 5. Fix collection-criteria # TODO # 6. Fix image links and scales # TODO # 7. Fix view names on Folders and Collection if self.safe_portal_type in ("collection", "topic", "folder"): old_layout = item.get("layout", "does_not_exist") if old_layout in LISTING_VIEW_MAPPING: item["layout"] = LISTING_VIEW_MAPPING[old_layout] return item
def get_export_data( self, portal_type, blob_format, richtext_format, blacklist, whitelist, query, ): """Return a list of dicts with a dict for each object. The key is the name of the field/value and the value the value. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) results = [] catalog = api.portal.get_tool('portal_catalog') if not query: query = dict() query['portal_type'] = portal_type if 'Language' not in query and HAS_MULTILINGUAL and \ 'Language' in catalog.indexes(): query['Language'] = 'all' brains = catalog.unrestrictedSearchResults(query) for brain in brains: obj = brain.getObject() item_dict = dict() for fieldname, field in all_fields: if fieldname in self.ADDITIONAL_MAPPING: # The way to access the value from this fields is # overridden in ADDITIONAL_MAPPING continue try: value = field.get(field.interface(obj)) except: print("Skipping object at {0}".format(obj.absolute_url())) break if not value: # set a value anyway to keep the dimensions of all value = '' # make sure we do no more transforms field = None if IRichTextValue.providedBy(value): value = transform_richtext(value, mimetype=richtext_format) if IRelationList.providedBy(field): rel_val = [] for relation in value: rel_val.append(get_url_for_relation(relation)) value = pretty_join(rel_val) if IRelationChoice.providedBy(field): value = get_url_for_relation(value) if INamed.providedBy(value): value = get_blob_url(value, brain, blob_format, fieldname) if ICollection.providedBy(field): r = [] for v in value: if INamed.providedBy(v): r.append(u'{0}/@@download/{1}'.format( obj.absolute_url(), fieldname)) # r.append(base64.b64encode(v.data)) else: r.append(v) value = r if IDatetime.providedBy(field) or IDate.providedBy(field): if value.year < 1000: if value.year < 16: year = value.year + 2000 else: year = value.year + 1900 if IDate.providedBy(field): value = datetime.date(month=value.month, day=value.day, year=year) elif IDatetime.providedBy(field): value = datetime.datetime(month=value.month, day=value.day, year=year, hour=value.hour, minute=value.minute, second=value.second) value = api.portal.get_localized_time(value, long_format=True) if safe_callable(value): value = value() if isinstance(value, list) or isinstance(value, tuple): value = pretty_join(value) item_dict[fieldname] = value else: # Update the data with additional info or overridden getters item_dict.update(self.additional_data(obj, blacklist)) results.append(item_dict) continue # executed if the loop ended normally (no break) break # executed if 'continue' was skipped (break) return results
def export_blobs(self, portal_type, blob_type, blacklist, whitelist): """Return a zip-file with file and/or images for the required export. """ all_fields = get_schema_info(portal_type, blacklist, whitelist) if blob_type == 'images': fields = [ i for i in all_fields if INamedImageField.providedBy(i[1]) or INamedBlobImageField.providedBy(i[1]) ] elif blob_type == 'files': fields = [ i for i in all_fields if INamedFileField.providedBy(i[1]) or INamedBlobFileField.providedBy(i[1]) ] elif blob_type == 'related': fields = [ i for i in all_fields if IRelationChoice.providedBy(i[1]) or IRelationList.providedBy(i[1]) ] tmp_file = NamedTemporaryFile() zip_file = zipfile.ZipFile(tmp_file, 'w') catalog = api.portal.get_tool('portal_catalog') query = {'portal_type': portal_type} query['path'] = {} query['path']['query'] = '/'.join(self.context.getPhysicalPath()) blobs_found = False if HAS_MULTILINGUAL and 'Language' in catalog.indexes(): query['Language'] = 'all' for brain in catalog(query): obj = brain.getObject() for fieldname, field in fields: # manually filter for fields # if fieldname not in ['primary_picture']: # continue blobs = [] value = field.get(field.interface(obj)) if not value: continue if blob_type != 'related': blobs = [value] elif IRelationChoice.providedBy(field) or \ IRelationList.providedBy(field): blobs = get_blobs_from_relations(value, field) for blob in blobs: if not blob: continue filename = str((blob.filename).encode('utf8')) zip_file.writestr( '{0}_{1}/{2}'.format( brain.UID, # or: brain.id.upper(), fieldname, filename), str(blob.data)) blobs_found = True zip_file.close() if not blobs_found: return 'No {0} found'.format(blob_type) data = file(tmp_file.name).read() response = self.request.response response.setHeader('content-type', 'application/zip') response.setHeader('content-length', len(data)) response.setHeader('content-disposition', 'attachment; filename="{0}.zip"'.format(blob_type)) return response.write(data)