def test_install_dx_type_if_needed(self): from plone.app.contenttypes.migration.utils import installTypeIfNeeded tt = self.portal.portal_types tt.manage_delObjects('Document') tt.manage_addTypeInformation( 'Factory-based Type Information with dynamic views', id='Document') applyProfile( self.portal, 'plone.app.contenttypes:default', blacklisted_steps=['typeinfo']) fti = tt.getTypeInfo('Document') self.assertFalse(IDexterityFTI.providedBy(fti)) installTypeIfNeeded('Document') fti = tt.getTypeInfo('Document') self.assertTrue(IDexterityFTI.providedBy(fti))
def __call__(self): req = self.request if req.REQUEST_METHOD != 'POST': return filedata = self.request.form.get("file", None) if filedata is None: return filename = filedata.filename content_type = mimetypes.guess_type(filename)[0] or "" if not filedata: return # Determine if the default file/image types are DX or AT based ctr = getToolByName(self.context, 'content_type_registry') type_ = ctr.findTypeName(filename.lower(), '', '') or 'File' DX_BASED = False if HAS_DEXTERITY: pt = getToolByName(self.context, 'portal_types') if IDexterityFTI.providedBy(getattr(pt, type_)): factory = IDXFileFactory(self.context) DX_BASED = True else: factory = IATCTFileFactory(self.context) else: factory = IATCTFileFactory(self.context) obj = factory(filename, content_type, filedata) if DX_BASED: if 'File' in obj.portal_type: size = obj.file.getSize() content_type = obj.file.contentType elif 'Image' in obj.portal_type: size = obj.image.getSize() content_type = obj.image.contentType result = { "type": content_type, "size": size } else: try: size = obj.getSize() except AttributeError: size = obj.getObjSize() result = { "type": obj.getContentType(), "size": size } result.update({ 'url': obj.absolute_url(), 'name': obj.getId(), 'uid': IUUID(obj), 'filename': filename }) return json.dumps(result)
def __call__(self, context): context = getattr(context, 'context', context) portal = getToolByName(context, 'portal_url').getPortalObject() flt = [_infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IFileContent)] ilt = [_infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IImageContent)] items = [SimpleTerm('auto', 'auto', context.translate('label_default_portaltype_configuration', default=u'Default configuration (Content Type Registry).', domain='collective.quickupload')),] all_portal_types = [] for t in flt+ilt: portal_type = t['portal_type'] if portal_type not in all_portal_types: items.append(SimpleTerm(portal_type, portal_type, t['type_ui_info'])) all_portal_types.append(portal_type) for fti in portal.portal_types.objectValues(): if HAS_DEXTERITY and IDexterityFTI.providedBy(fti): fields = getFieldsInOrder(fti.lookupSchema()) for fieldname, field in fields: if INamedFileField.providedBy(field) or INamedImageField.providedBy(field): items.append(SimpleTerm(fti.getId(), fti.getId(), fti.Title())) break return SimpleVocabulary(items)
def installTypeIfNeeded(type_name): """Make sure the dexterity-fti is already installed. If not we create a empty dexterity fti and load the information from the fti in the profile. """ if type_name not in DEFAULT_TYPES: raise KeyError('{0} is not one of the default types'.format(type_name)) portal = getSite() tt = getToolByName(portal, 'portal_types') fti = tt.getTypeInfo(type_name) if IDexterityFTI.providedBy(fti): # The dx-type is already installed, so keep it. But this # might be an old dexterity type of Collection, in which case # it is better to replace it. if type_name != 'Collection': return if fti.klass == 'plone.app.contenttypes.content.Collection': # If the klass is fine, we are happy. return if fti: tt.manage_delObjects(type_name) tt.manage_addTypeInformation('Dexterity FTI', id=type_name) dx_fti = tt.getTypeInfo(type_name) ps = getToolByName(portal, 'portal_setup') profile_info = ps.getProfileInfo('profile-plone.app.contenttypes:default') profile_path = os.path.join(profile_info['path']) environ = DirectoryImportContext(ps, profile_path) parent_path = 'types/' importObjects(dx_fti, parent_path, environ)
def fix_core_behaviors_in_ftis(context): # The behaviors for IRichText and ILeadImage have been renamed. # All FTIs that use them must be updated accordingly # See plone/plone.app.contenttypes#480 types_tool = getToolByName(context, 'portal_types') to_replace = { 'plone.app.contenttypes.behaviors.richtext.IRichText': 'plone.app.contenttypes.behaviors.richtext.IRichTextBehavior', 'plone.app.contenttypes.behaviors.leadimage.ILeadImage': 'plone.app.contenttypes.behaviors.leadimage.ILeadImageBehavior', } ftis = types_tool.listTypeInfo() for fti in ftis: # Since we're handling dexterity behaviors, we only care about # dexterity FTIs if not IDexterityFTI.providedBy(fti): continue behaviors = [] change_needed = False for behavior in fti.behaviors: if behavior in to_replace: behavior = to_replace[behavior] change_needed = True behaviors.append(behavior) if change_needed: fti.behaviors = tuple(behaviors)
def add_versioning_behavior(self, fti): if not IDexterityFTI.providedBy(fti): return behaviors = list(fti.behaviors) if self.behavior_name not in behaviors: behaviors.append(self.behavior_name) fti.behaviors = behaviors
def invalidate(self, fti): if fti is not None and not IDexterityFTI.providedBy(fti): # fti is a name, lookup fti = queryUtility(IDexterityFTI, name=fti) if fti is not None: invalidate_cache(fti) self.invalidations += 1
def remove_versioning_behavior(self, fti): if not IDexterityFTI.providedBy(fti): return behaviors = list(fti.behaviors) if self.behavior_name in behaviors: behaviors.remove(self.behavior_name) fti.behaviors = behaviors
def removeBehaviors(context): """Remove p.a.multilingual behaviors from p.a.contenttypes types.""" if context.readDataFile('plone.app.multilingual_uninstall.txt') is None: return portal = context.getSite() portal_types = getToolByName(portal, 'portal_types') behavior = 'plone.app.multilingual.dx.interfaces.IDexterityTranslatable' # plone.app.contenttype types typeNames = [ 'Document', 'File', 'Folder', 'Image', 'Link', 'News Item', ] for name in typeNames: type_ = portal_types.get(name) # safety first if not type_ or not IDexterityFTI.providedBy(type_): continue behaviors = list(type_.behaviors) behaviors.remove(behavior) type_.behaviors = tuple(behaviors)
def __call__(self, context): context = getattr(context, 'context', context) portal = getToolByName(context, 'portal_url').getPortalObject() items = [SimpleTerm('auto', 'auto', context.translate(_('label_default_portaltype_configuration', default=u'Default configuration (Content Type Registry).')))] archetype_tool = getToolByName(context, 'archetype_tool', None) if archetype_tool: flt = [_infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IFileContent)] ilt = [_infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IImageContent)] items.extend([SimpleTerm(t['portal_type'], t['portal_type'], t['type_ui_info']) for t in flt]) file_types = [t['portal_type'] for t in flt] items.extend([SimpleTerm(t['portal_type'], t['portal_type'], t['type_ui_info']) for t in ilt if t['portal_type'] not in file_types]) for fti in portal.portal_types.objectValues(): if HAS_DEXTERITY and IDexterityFTI.providedBy(fti): try: schema = fti.lookupSchema() except ImportError: # this dexterity type was changed/removed in an improper way # no need to punish, just fail gracefully continue fields = getFieldsInOrder(schema) for fieldname, field in fields: if INamedFileField.providedBy(field) or INamedImageField.providedBy(field): items.append(SimpleTerm(fti.getId(), fti.getId(), fti.Title())) break return SimpleVocabulary(items)
def remove_versioning_behavior(self, fti): if not IDexterityFTI.providedBy(fti): return behaviors = list(fti.behaviors) if self.behavior_name in behaviors: behaviors.remove(self.behavior_name) # TODO: remove locking if it wasn't set in first place fti.behaviors = behaviors
def ftiAdded(object, event): """When the FTI is created, install local components """ if not IDexterityFTI.providedBy(event.object): return register(event.object)
def ftiRemoved(object, event): """When the FTI is removed, uninstall local coponents """ if not IDexterityFTI.providedBy(event.object): return unregister(event.object)
def ftiModified(object, event): """When an FTI is modified, re-sync and invalidate the schema, if necessary. """ if not IDexterityFTI.providedBy(event.object): return fti = event.object portal_type = fti.getId() mod = {} for desc in event.descriptions: if IDexterityFTIModificationDescription.providedBy(desc): mod[desc.attribute] = desc.oldValue # If the factory utility name was modified, we may get an orphan if one # was registered as a local utility to begin with. If so, remove the # orphan. if 'factory' in mod: old_factory = mod['factory'] site = getUtility(ISiteRoot) site_manager = getSiteManager(site) # Remove previously registered factory, if no other type uses it. unregister_factory(old_factory, site_manager) # Register a new local factory if one doesn't exist already new_factory_utility = queryUtility(IFactory, name=fti.factory) if new_factory_utility is None: site_manager.registerUtility( DexterityFactory(portal_type), IFactory, fti.factory, info='plone.dexterity.dynamic' ) # Determine if we need to invalidate the schema at all if 'behaviors' in mod \ or 'schema' in mod \ or 'model_source' in mod \ or 'model_file' in mod \ or 'schema_policy' in mod: # Determine if we need to re-sync a dynamic schema if (fti.model_source or fti.model_file) \ and ('model_source' in mod or 'model_file' in mod or 'schema_policy' in mod): schemaName = portalTypeToSchemaName(portal_type) schema = getattr(plone.dexterity.schema.generated, schemaName) model = fti.lookupModel() sync_bases = 'schema_policy' in mod syncSchema(model.schema, schema, overwrite=True, sync_bases=sync_bases) notify(SchemaInvalidatedEvent(portal_type))
def check_translatable_foldertype(self): from plone.dexterity.interfaces import IDexterityFTI from plone.app.multilingual.dx.interfaces import IDexterityTranslatable pt = getToolByName(self.context, 'portal_types') fti = getattr(pt, self.folder_type) if IDexterityFTI.providedBy(fti): behaviors = list(fti.behaviors) behaviors.append(IDexterityTranslatable.__identifier__) fti.behaviors = behaviors
def getDexterityTypes(self): """ Returns a list of Dexterity FTIs. """ portal_types = getToolByName(self.context, 'portal_types') for fti in portal_types.listTypeInfo(): if IDexterityFTI.providedBy(fti): yield fti
def __call__(self): portal_types = getToolByName(self.context, 'portal_types') for fti in portal_types.objectValues(): if IDexterityFTI.providedBy(fti) and fti.id in TYPES_TO_FIX: add_view_expr = "python:object.restrictedTraverse('plone_context_state').folder().absolute_url() + '/++add++%s'" % fti.getId() fti._setPropValue('add_view_expr', add_view_expr) return 'Success!'
def ensure_translatable(self, type_): types_tool = getToolByName(self.context, 'portal_types') fti = getattr(types_tool, type_) if IDexterityFTI.providedBy(fti): behaviors = list(fti.behaviors) behaviors.append('plone.translatable') behaviors = tuple(set(behaviors)) fti._updateProperty('behaviors', behaviors)
def fti_modified(obj, event): """ When an FTI is modified, invalidate localrole fields list cache. """ return # cache is no more used because not necessary following timecall if not IDexterityFTI.providedBy(event.object): return cache_chooser = getUtility(ICacheChooser) thecache = cache_chooser('dexterity.localrolesfield.utils.get_localrole_fields') thecache.ramcache.invalidate('dexterity.localrolesfield.utils.get_localrole_fields')
def getDXFTIs(self): '''Returns the FTI's of all DX-Types (including default-types).''' results = [] portal = self.context ttool = getToolByName(portal, 'portal_types') for fti in ttool.listTypeInfo(): if IDexterityFTI.providedBy(fti): results.append({'id': fti.getId(), 'title': fti.Title()}) return results
def add_versioning_behavior(self, fti): if not IDexterityFTI.providedBy(fti): return behaviors = list(fti.behaviors) if self.behavior_name not in behaviors: behaviors.append(self.behavior_name) # locking must be turned on for versioning support on the type locking = 'plone.app.lockingbehavior.behaviors.ILocking' if locking not in behaviors: behaviors.append(locking) fti.behaviors = behaviors
def remove_behavior(context): """Remove the lineage.themeselection behavior from portal_types types. """ key = 'lineage.themeselection.behaviors.IThemeSelection' types_tool = getToolByName(context, 'portal_types') for item in types_tool.values(): if IDexterityFTI.providedBy(item): if key in getattr(item, 'behaviors', ''): item.behaviors = tuple( it for it in types_tool.Folder.behaviors if it not in key ) logger.info("Removed {0} from {1}".format(key, item.id))
def ftiRenamed(object, event): """When the FTI is modified, ensure local components are still valid """ if not IDexterityFTI.providedBy(event.object): return if event.oldParent is None or event.newParent is None or event.oldName == event.newName: return unregister(event.object, event.oldName) register(event.object)
def demarshall(obj, message): types_tool = api.portal.get_tool('portal_types') fti = types_tool.get(obj.portal_type) if IDexterityFTI.providedBy(fti): # DX payload = message._payload message._payload = None initializeObjectFromSchemata(DublinCore(obj), [IDublinCore], message) message._payload = payload initializeObjectFromSchemata(obj, iterSchemata(obj), message) elif HAS_ARCHETYPES: # AT initializeObject(obj, iterFields(obj), message)
def ftiModified(object, event): """When an FTI is modified, re-sync and invalidate the schema, if necessary. """ if not IDexterityFTI.providedBy(event.object): return fti = event.object portal_type = fti.getId() mod = {} for desc in event.descriptions: if IDexterityFTIModificationDescription.providedBy(desc): mod[desc.attribute] = desc.oldValue # If the factory utility name was modified, we may get an orphan if one # was registered as a local utility to begin with. If so, remove the # orphan. if 'factory' in mod: old_factory = mod['factory'] site = getUtility(ISiteRoot) site_manager = getSiteManager(site) # Remove previously registered factory, if no other type uses it. unregister_factory(old_factory, site_manager) # Register a new local factory if one doesn't exist already new_factory_utility = queryUtility(IFactory, name=fti.factory) if new_factory_utility is None: site_manager.registerUtility(DexterityFactory(portal_type), IFactory, fti.factory, info='plone.dexterity.dynamic') # Determine if we need to invalidate the schema at all if 'behaviors' in mod or 'schema' in mod or 'model_source' in mod or 'model_file' in mod: # Determine if we need to re-sync a dynamic schema if (fti.model_source or fti.model_file) and ('model_source' in mod or 'model_file' in mod): schemaName = utils.portalTypeToSchemaName(portal_type) schema = getattr(plone.dexterity.schema.generated, schemaName) model = fti.lookupModel() syncSchema(model.schema, schema, overwrite=True) notify(SchemaInvalidatedEvent(portal_type))
def demarshall(ob, message): types_tool = api.portal.get_tool('portal_types') fti = types_tool.get(ob.portal_type) if IDexterityFTI.providedBy(fti): # DX try: initializeObjectFromSchemata(ob, iterSchemata(ob), message) except Exception: raise # import pdb; pdb.set_trace() # initializeObjectFromSchemata(ob, iterSchemata(ob), message) elif HAS_ARCHETYPES: # AT initializeObject(ob, iterFields(ob), message)
def ensure_correct_class(ob): # TODO: Detect if class is changed into container type and initialize it types_tool = api.portal.get_tool('portal_types') fti = types_tool.get(ob.portal_type) if IDexterityFTI.providedBy(fti): module_name, class_name = fti.klass.rsplit('.', 1) module = importlib.import_module(module_name) klass = getattr(module, class_name) elif HAS_ARCHETYPES: key = '.'.join([fti.product, fti.id]) klass = _types.get(key, {}).get('klass', None) if klass is not None and ob.__class__ != klass: ob.__class__ = klass ob._p_changed = True
def ftiRenamed(object, event): """When the FTI is modified, ensure local components are still valid """ if not IDexterityFTI.providedBy(event.object): return if event.oldParent is None \ or event.newParent is None \ or event.oldName == event.newName: return unregister(event.object, event.oldName) register(event.object)
def add_content(self, typename, name, parent, **kwargs): kwargs['title'] = kwargs.get('title', name) tool = getToolByName(self.portal, 'portal_types') fti = tool.getTypeInfo(typename) if IDexterityFTI.providedBy(fti): o = createContent(typename, **kwargs) o.id = name parent._setObject(name, o) else: parent.invokeFactory(typename, name) o = parent[name] o.setTitle(kwargs.get('title')) o.reindexObject() return o
def _listTypesForInterface(context, iftype='file'): """ List of portal types that have File or Image interface @param portal: context @param iftype: Type of interface to query for, can be either 'file' or 'image' @return: ['Image', 'News Item'] """ archetype_tool = getToolByName(context, 'archetype_tool', None) types_tool = getToolByName(context, 'portal_types') all_types = [] if archetype_tool: if iftype == 'image': interface = IImageContent else: interface = IFileContent #plone4 try: all_types = [ tipe.getId() for tipe in archetype_tool.listPortalTypesWithInterfaces([interface]) ] #plone3 except: all_types = archetype_tool.listRegisteredTypes(inProject=True) all_types = [ tipe['portal_type'] for tipe in all_types if interface.isImplementedByInstancesOf(tipe['klass']) ] if HAS_DEXTERITY: if iftype == 'image': interface = INamedImageField else: interface = INamedFileField for fti in types_tool.objectValues(): if IDexterityFTI.providedBy(fti): fields = getFieldsInOrder(fti.lookupSchema()) for fieldname, field in fields: if interface.providedBy(field): all_types.append(fti.getId()) break # fix for bug in listRegisteredTypes which returns 2 'ATFolder' # when asking for IBaseFolder interface unik_types = dict.fromkeys(all_types).keys() return unik_types
def _listTypesForInterface(context, iftype='file'): """ List of portal types that have File or Image interface @param portal: context @param iftype: Type of interface to query for, can be either 'file' or 'image' @return: ['Image', 'News Item'] """ archetype_tool = getToolByName(context, 'archetype_tool', None) types_tool = getToolByName(context, 'portal_types') all_types = [] if archetype_tool: if iftype == 'image': interface = IImageContent else: interface = IFileContent # plone4 try: all_types = [ tipe.getId() for tipe in archetype_tool.listPortalTypesWithInterfaces([interface]) ] # plone3 except: all_types = archetype_tool.listRegisteredTypes(inProject=True) all_types = [ tipe['portal_type'] for tipe in all_types if interface.isImplementedByInstancesOf(tipe['klass']) ] if HAS_DEXTERITY: if iftype == 'image': interface = INamedImageField else: interface = INamedFileField for fti in types_tool.objectValues(): if IDexterityFTI.providedBy(fti): fields = getFieldsInOrder(fti.lookupSchema()) for fieldname, field in fields: if interface.providedBy(field): all_types.append(fti.getId()) break # fix for bug in listRegisteredTypes which returns 2 'ATFolder' # when asking for IBaseFolder interface unik_types = dict.fromkeys(all_types).keys() return unik_types
def get_mapped_types(self): """Returns the mapped types for this catalog """ pt = api.get_tool("portal_types") at = api.get_tool("archetype_tool") # Get all Archetypes which are mapped to this catalog at_types = [k for k, v in at.catalog_map.items() if self.id in v] # TODO: Discover the mapped catalogs for Dexterity types dx_ftis = filter(lambda fti: IDexterityFTI.providedBy(fti), pt.listTypeInfo()) dx_types = map(lambda fti: fti.getId(), dx_ftis) return at_types + dx_types
def marshall(ob): types_tool = api.portal.get_tool('portal_types') fti = types_tool.get(ob.portal_type) # noinspection PyUnresolvedReferences if HAS_DEXTERITY and IDexterityFTI.providedBy(fti): # DX message = constructMessageFromSchemata(ob, iterSchemata(ob)) elif HAS_ARCHETYPES and hasattr(Acquisition.aq_base(ob), 'schema'): # AT message = constructMessage(ob, iterFields(ob)) else: # Other schemata = tuple(ob.__provides__.interfaces()) message = constructMessageFromSchemata(ob, schemata) return message
def update(self): self.available = False if not HAS_ARCHETYPES: return self.context = aq_inner(self.context) replaced_types = [ 'ATFolder', 'ATDocument', 'ATFile', 'ATImage', 'ATNewsItem', 'ATLink', 'ATEvent', 'ATBlobImage', 'ATBlobFile', 'Collection' ] if self.context.meta_type not in replaced_types: return if not IBaseObject.providedBy(self.context): return context_fti = self.context.getTypeInfo() if IDexterityFTI.providedBy(context_fti): self.available = True
def getDexterityFolderTypes(): try: from plone.dexterity.interfaces import IDexterityFTI from plone.dexterity.utils import resolveDottedName except ImportError: return set([]) portal_types = getToolByName(portal, "portal_types") types = [fti for fti in portal_types.listTypeInfo() if IDexterityFTI.providedBy(fti)] ftypes = set([]) for _type in types: klass = resolveDottedName(_type.klass) if ISyndicatable.implementedBy(klass): ftypes.add(_type.getId()) return ftypes
def move_dotted_to_named_behaviors(context): """named behaviors are better then dotted behaviors > let's move them.""" from plone import api from plone.behavior.registration import lookup_behavior_registration from plone.dexterity.interfaces import IDexterityFTI ptt = api.portal.get_tool('portal_types') ftis = [fti for fti in ptt.objectValues() if IDexterityFTI.providedBy(fti)] for fti in ftis: behaviors = [] for behavior in fti.behaviors: behavior_registration = lookup_behavior_registration(behavior) named_behavior = behavior_registration.name if named_behavior: behaviors.append(named_behavior) if named_behavior == behavior: logger.info( 'Behavior "{behavior}" already named.'.format( behavior=behavior, ), ) else: logger.info( 'Moved "{dotted}" to "{named}"'.format( dotted=behavior, named=named_behavior, ), ) else: behaviors.append(behavior) logger.info( '"{dotted}" has no name registered. ' 'kept it dotted.'.format( dotted=behavior, ), ) fti.behaviors = tuple(behaviors) logger.info( 'Converted dotted behaviors of {ct} to named behaviors.'.format( ct=fti.title, ), ) logger.info('Done moving dotted to named behaviors.')
def _infoDictForType(portal, ptype): """ UI type infos @param ptype: a portal type name @return: {'portal_type': xxx, 'type_ui_info': UI type info} """ portal_types = getToolByName(portal, 'portal_types') type_info = getattr(portal_types, ptype) title = type_info.Title() if HAS_DEXTERITY and IDexterityFTI.providedBy(type_info): product = type_info.klass else: product = type_info.product type_ui_info = ("%s (portal type: %s, product: %s)" % (portal.translate(title, default=title), ptype, product)) return {'portal_type': ptype, 'type_ui_info': type_ui_info}
def add_content(self, typename, name, parent, **kwargs): kwargs['title'] = kwargs.get('title', name) tool = getToolByName(self.portal, 'portal_types') fti = tool.getTypeInfo(typename) if IDexterityFTI.providedBy(fti): o = createContent( typename, **kwargs ) o.id = name parent._setObject(name, o) else: parent.invokeFactory(typename, name) o = parent[name] o.setTitle(kwargs.get('title')) o.reindexObject() return o
def create_file_from_request(self, name): context = self.context filedata = self.request.form.get(name, None) if not filedata: return filename = filedata.filename content_type = mimetypes.guess_type(filename)[0] or "" # Determine if the default file/image types are DX or AT based ctr = api.portal.get_tool('content_type_registry') type_ = ctr.findTypeName(filename.lower(), content_type, '') if not type_ == 'Image': type_ = 'File' pt = api.portal.get_tool('portal_types') if IDexterityFTI.providedBy(getattr(pt, type_)): obj = self.create_dx_file(filename, content_type, filedata, type_) self.post_factory(obj) notify(ObjectCreatedEvent(obj)) if hasattr(obj, 'file'): size = obj.file.getSize() content_type = obj.file.contentType elif hasattr(obj, 'image'): size = obj.image.getSize() content_type = obj.image.contentType else: return result = {"type": content_type, "size": size} else: from Products.ATContentTypes.interfaces import IATCTFileFactory obj = IATCTFileFactory(context)(filename, content_type, filedata) self.post_factory(obj) try: size = obj.getSize() except AttributeError: size = obj.getObjSize() result = {"type": obj.getContentType(), "size": size} result.update({ 'url': obj.absolute_url(), 'name': obj.getId(), 'UID': IUUID(obj), 'filename': filename }) return result
def _getDexterityFolderTypes(portal): try: from plone.dexterity.interfaces import IDexterityFTI from plone.dexterity.utils import resolveDottedName from Products.CMFPlone.interfaces.syndication import ISyndicatable except ImportError: return set([]) portal_types = getToolByName(portal, 'portal_types') types = [fti for fti in portal_types.listTypeInfo() if IDexterityFTI.providedBy(fti)] ftypes = set([]) for _type in types: klass = resolveDottedName(_type.klass) if ISyndicatable.implementedBy(klass): ftypes.add(_type.getId()) return ftypes
def move_dotted_to_named_behaviors(context): """named behaviors are better then dotted behaviors > let's move them.""" from plone import api from plone.behavior.registration import lookup_behavior_registration from plone.dexterity.interfaces import IDexterityFTI ptt = api.portal.get_tool('portal_types') ftis = [fti for fti in ptt.objectValues() if IDexterityFTI.providedBy(fti)] for fti in ftis: behaviors = [] for behavior in fti.behaviors: behavior_registration = lookup_behavior_registration(behavior) named_behavior = behavior_registration.name if named_behavior: behaviors.append(named_behavior) if named_behavior == behavior: logger.info( 'Behavior "{behavior}" already named.'.format( behavior=behavior, ), ) else: logger.info( 'Moved "{dotted}" to "{named}"'.format( dotted=behavior, named=named_behavior, ), ) else: behaviors.append(behavior) logger.info( '"{dotted}" has no name registered. ' 'kept it dotted.'.format(dotted=behavior, ), ) fti.behaviors = tuple(behaviors) logger.info( 'Converted dotted behaviors of {ct} to named behaviors.'.format( ct=fti.title, ), ) logger.info('Done moving dotted to named behaviors.') # Make sure plone.staticresources is installed from Products.CMFPlone.utils import get_installer qi = get_installer(context) if not qi.is_product_installed('plone.staticresources'): qi.install_product('plone.staticresources')
def portal_types(self): """A list with info on all dexterity content types with existing items. """ catalog = api.portal.get_tool('portal_catalog') portal_types = api.portal.get_tool('portal_types') results = [] for fti in portal_types.listTypeInfo(): if not IDexterityFTI.providedBy(fti): continue number = len(catalog.unrestrictedSearchResults(portal_type=fti.id)) if number >= 1: results.append({ 'number': number, 'value': fti.id, 'title': translate(fti.title, domain='plone', context=self.request) }) return sorted(results, key=itemgetter('title'))
def move_dotted_to_named_behaviors(context): """ https://github.com/plone/plone.app.upgrade/blob/master/plone/app/upgrade/v52/alphas.py#L58 # noqa: E501 """ mapping = { IWorkspace.__identifier__: "collective.workspace.team_workspace" } ptt = api.portal.get_tool("portal_types") ftis = (fti for fti in ptt.objectValues() if IDexterityFTI.providedBy(fti)) for fti in ftis: behaviors = [] change_needed = False for behavior in fti.behaviors: if behavior in mapping: behavior = mapping[behavior] change_needed = True behaviors.append(behavior) if change_needed: fti.behaviors = tuple(behaviors) logger.info("Done moving dotted to named behaviors.")
def decorator(self, portal_type): """lookup fti from portal_type and cache """ if IDexterityFTI.providedBy(portal_type): fti = portal_type else: fti = queryUtility(IDexterityFTI, name=portal_type) if fti is not None and self.cache_enabled: key = '_v_schema_%s' % func.__name__ cache = getattr(fti, key, _MARKER) if cache is not _MARKER: mtime, value = cache if fti._p_mtime == mtime: return value value = func(self, fti) if fti is not None and self.cache_enabled: setattr(fti, key, (fti._p_mtime, value)) return value
def __call__(self, context): context = getattr(context, 'context', context) portal = getToolByName(context, 'portal_url').getPortalObject() flt = [ _infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IFileContent) ] ilt = [ _infoDictForType(portal, tipe) for tipe in _listTypesForInterface(portal, IImageContent) ] items = [ SimpleTerm( 'auto', 'auto', context.translate( _('label_default_portaltype_configuration', default=u'Default configuration (Content Type Registry).' ))) ] items.extend([ SimpleTerm(t['portal_type'], t['portal_type'], t['type_ui_info']) for t in flt ]) file_types = [t['portal_type'] for t in flt] items.extend([ SimpleTerm(t['portal_type'], t['portal_type'], t['type_ui_info']) for t in ilt if t['portal_type'] not in file_types ]) for fti in portal.portal_types.objectValues(): if HAS_DEXTERITY and IDexterityFTI.providedBy(fti): fields = getFieldsInOrder(fti.lookupSchema()) for fieldname, field in fields: if INamedFileField.providedBy( field) or INamedImageField.providedBy(field): items.append( SimpleTerm(fti.getId(), fti.getId(), fti.Title())) break return SimpleVocabulary(items)
def set_uuid(ob, uuid): types_tool = api.portal.get_tool('portal_types') fti = types_tool.get(ob.portal_type) if IDexterityFTI.providedBy(fti): # DX if HAS_DEXTERITY_REFERENCEABLE: if DX.IReferenceable.providedBy(ob): uid_catalog = api.portal.get_tool('uid_catalog') path = '/'.join(ob.getPhysicalPath()) uid_catalog.uncatalog_object(path) # noinspection PyArgumentList IMutableUUID(ob).set(str(uuid)) if HAS_DEXTERITY_REFERENCEABLE: if DX.IReferenceable.providedBy(ob): uid_catalog = api.portal.get_tool('uid_catalog') path = '/'.join(ob.getPhysicalPath()) uid_catalog.catalog_object(ob, path) elif HAS_ARCHETYPES: if AT.IReferenceable.providedBy(ob): # AT ob._uncatalogUID(api.portal.get()) ob._setUID(uuid)
def installTypeIfNeeded(type_name): """Make sure the dexterity-fti is already installed. If not we create a empty dexterity fti and load the information from the fti in the profile. """ if type_name not in DEFAULT_TYPES: raise KeyError("%s is not one of the default types" % type_name) portal = getSite() tt = getToolByName(portal, 'portal_types') fti = tt.getTypeInfo(type_name) if IDexterityFTI.providedBy(fti): # the dx-type is already installed return if fti: tt.manage_delObjects(type_name) tt.manage_addTypeInformation('Dexterity FTI', id=type_name) dx_fti = tt.getTypeInfo(type_name) ps = getToolByName(portal, 'portal_setup') profile_info = ps.getProfileInfo('profile-plone.app.contenttypes:default') profile_path = os.path.join(profile_info['path']) environ = DirectoryImportContext(ps, profile_path) parent_path = 'types/' importObjects(dx_fti, parent_path, environ)
def portal_types(self): """A list with info on all dexterity content types with existing items. """ catalog = api.portal.get_tool('portal_catalog') portal_types = api.portal.get_tool('portal_types') results = [] for fti in portal_types.listTypeInfo(): if not IDexterityFTI.providedBy(fti): continue query = {} query['portal_type'] = fti.id query['path'] = {} query['path']['query'] = '/'.join(self.context.getPhysicalPath()) number = len(catalog(query)) if number >= 1: results.append({ 'number': number, 'value': fti.id, 'title': translate(fti.title, domain='plone', context=self.request) }) return sorted(results, key=itemgetter('title'))
def __call__(self): req = self.request tusrequest = False if TUS_ENABLED: adapter = Zope2RequestAdapter(req) tus = Tus(adapter, **tus_settings) if tus.valid: tusrequest = True tus.handle() if not tus.upload_finished: return else: filename = req.getHeader('FILENAME') if tus.send_file: filedata = req._file filedata.filename = filename else: filepath = req._file.read() filedata = open(filepath) if not tusrequest: if req.REQUEST_METHOD != 'POST': return filedata = self.request.form.get("file", None) if filedata is None: return filename = filedata.filename content_type = mimetypes.guess_type(filename)[0] or "" if not filedata: return # Determine if the default file/image types are DX or AT based ctr = getToolByName(self.context, 'content_type_registry') type_ = ctr.findTypeName(filename.lower(), '', '') or 'File' DX_BASED = False if HAS_DEXTERITY: pt = getToolByName(self.context, 'portal_types') if IDexterityFTI.providedBy(getattr(pt, type_)): factory = IDXFileFactory(self.context) DX_BASED = True else: factory = IATCTFileFactory(self.context) else: factory = IATCTFileFactory(self.context) obj = factory(filename, content_type, filedata) if DX_BASED: if 'File' in obj.portal_type: size = obj.file.getSize() content_type = obj.file.contentType elif 'Image' in obj.portal_type: size = obj.image.getSize() content_type = obj.image.contentType result = {"type": content_type, "size": size} else: try: size = obj.getSize() except AttributeError: size = obj.getObjSize() result = {"type": obj.getContentType(), "size": size} if tusrequest: tus.cleanup_file() result.update({ 'url': obj.absolute_url(), 'name': obj.getId(), 'UID': IUUID(obj), 'filename': filename }) return json.dumps(result)
def listTypes(self): types = getToolByName(self, 'portal_types') dexterity = [(fti.id, fti.title) for fti in types.values() if IDexterityFTI.providedBy(fti)] return atapi.DisplayList(dexterity)
def __call__(self): portal = api.portal.get() tools = [ "portal_languages", "portal_tinymce", "kupu_library_tool", "portal_factory", "portal_atct", "uid_catalog", "archetype_tool", "reference_catalog", "portal_metadata", ] for tool in tools: try: portal.manage_delObjects([tool]) log.info("Deleted {}".format(tool)) except AttributeError: log.info("{} not found".format(tool)) # reapply uninstall to get rid of IATCTTool component try: loadMigrationProfile(portal, "profile-Products.ATContentTypes:uninstall") except KeyError: pass ptt = api.portal.get_tool("portal_types") ftis = [fti for fti in ptt.objectValues() if IDexterityFTI.providedBy(fti)] for fti in ftis: bad_behaviors = [] for behavior in fti.behaviors: try: lookup_behavior_registration(behavior) except Exception: bad_behaviors.append(behavior) if bad_behaviors: behaviors = [x for x in fti.behaviors if x not in bad_behaviors] fti.behaviors = behaviors log.warning("Removed {} for FTI {}".format(bad_behaviors, fti.id)) # Unregister persistent traces of collective.indexing try: from collective.indexing.indexer import IPortalCatalogQueueProcessor from collective.indexing.interfaces import IIndexingConfig except ImportError: pass else: cp = api.portal.get_tool("portal_controlpanel") cp.unregisterConfiglet("IndexingSettings") for iface, name in ( (IIndexingConfig, ""), (IPortalCatalogQueueProcessor, "portal-catalog"), ): unregisterUtility(portal, iface, name) # Remove yet more traces of c.indexing in the site manager sm = portal.getSiteManager() bad_ids = [ "collective.indexing.interfaces.IIndexingConfig", "collective.indexing.indexer.IPortalCatalogQueueProcessor-portal-catalog", ] for bad_id in bad_ids: if bad_id in sm.objectIds(): sm._delObject(bad_id) sm._p_changed = True # Also unregister collective.js.jquery util unregisterUtility(portal, ILocalBrowserLayerType, "collective.js.jqueryui")
def __call__(self): objects = {} # get all file in custom folder portal_skins = api.portal.get_tool('portal_skins') objects['custom'] = [] for obj_id, item in portal_skins.custom.items(): if item.meta_type in ['Image', 'File']: try: data = base64.b64encode(item.data) objects['custom'].append({ 'obj_id': obj_id, 'meta_type': item.meta_type, 'data': data }) except: logger.info('Not able to export {0}'.format('/'.join( item.getPhysicalPath()))) else: try: objects['custom'].append({ 'obj_id': obj_id, 'meta_type': item.meta_type, 'raw': item.raw }) except: logger.info('Not able to export {0}'.format('/'.join( item.getPhysicalPath()))) objects['default_skin'] = portal_skins.default_skin # get list of installed profile portal_quickinstaller = api.portal.get_tool('portal_quickinstaller') product_ids = [ product['id'] for product in portal_quickinstaller.listInstalledProducts() ] objects['products'] = product_ids portal_membership = api.portal.get_tool('portal_membership') list_members = portal_membership.listMembers() # groups groups = [] for site_group in api.group.get_groups(): group = {} group['id'] = site_group.getId() group['title'] = site_group.title group['description'] = site_group.description group['roles'] = site_group.getRoles() group['groups'] = site_group.getGroups() users = [ user.id for user in api.user.get_users(groupname=group['id']) if user in list_members ] # noqa group['users'] = users groups.append(group) objects['groups'] = groups # users pas = api.portal.get().acl_users passwords = dict(pas.source_users._user_passwords) users = [] for member in list_members: user = {} user['id'] = member.getId() user['name'] = member.getProperty('fullname', member.getUserName()) user['email'] = member.getProperty('email', None) user['fullname'] = member.getProperty('fullname', None) login_time = member.getProperty('login_time', None) if login_time == DateTime('2000/01/01'): user['login_date'] = '' else: user['login_date'] = login_time.strftime('%d/%m/%Y') last_login_time = member.getProperty('last_login_time', None) if last_login_time == DateTime('2000/01/01'): user['last_login_date'] = '' else: user['last_login_date'] = last_login_time.strftime('%d/%m/%Y') if user['login_date'] == user['last_login_date']: user['last_login_date'] = '' user['roles'] = member.getRoles() user['domains'] = member.getDomains() user['password'] = passwords.get(user['id']) users.append(user) objects['users'] = users # mail control panel mailhost = {} try: mail_host = getUtility(IMailHost) except ComponentLookupError: mail_host = getattr(api.portal.get(), 'MailHost') mailhost['smtp_host'] = mail_host.smtp_host mailhost['smtp_port'] = mail_host.smtp_port mailhost['smtp_userid'] = getattr(mail_host, 'smtp_userid', None) mailhost['smtp_uid'] = getattr(mail_host, 'smtp_uid', None) mailhost['smtp_pwd'] = mail_host.smtp_pwd mailhost['email_from_address'] = api.portal.get().email_from_address mailhost['email_from_name'] = api.portal.get().email_from_name objects['mailhost'] = mailhost # geo lat_key = 'collective.geo.settings.interfaces.IGeoSettings.latitude' lng_key = 'collective.geo.settings.interfaces.IGeoSettings.longitude' zoom_key = 'collective.geo.settings.interfaces.IGeoSettings.zoom' geo = {} geo['latitude'] = str(api.portal.get_registry_record(lat_key)) geo['longitude'] = str(api.portal.get_registry_record(lng_key)) geo['zoom'] = str(api.portal.get_registry_record(zoom_key)) objects['geo'] = geo # portal_languages portal_languages = api.portal.get_tool('portal_languages') objects['languages'] = portal_languages.supported_langs # discussion discussion = {} anonymous_comments = 'plone.app.discussion.interfaces.IDiscussionSettings.anonymous_comments' # bool anonymous_email_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.anonymous_email_enabled' # bool captcha = 'plone.app.discussion.interfaces.IDiscussionSettings.captcha' # choice edit_comment_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.edit_comment_enabled' # bool globally_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.globally_enabled' # bool moderation_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.moderation_enabled' # bool moderator_email = 'plone.app.discussion.interfaces.IDiscussionSettings.moderator_email' # textline moderator_notification_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.moderator_notification_enabled' # bool show_commenter_image = 'plone.app.discussion.interfaces.IDiscussionSettings.show_commenter_image' # bool user_notification_enabled = 'plone.app.discussion.interfaces.IDiscussionSettings.user_notification_enabled' # bool discussion['anonymous_comments'] = str( api.portal.get_registry_record(anonymous_comments)) discussion['anonymous_email_enabled'] = str( api.portal.get_registry_record(anonymous_email_enabled)) discussion['captcha'] = api.portal.get_registry_record(captcha) discussion['edit_comment_enabled'] = str( api.portal.get_registry_record(edit_comment_enabled)) discussion['globally_enabled'] = str( api.portal.get_registry_record(globally_enabled)) discussion['moderation_enabled'] = str( api.portal.get_registry_record(moderation_enabled)) discussion['moderator_email'] = str( api.portal.get_registry_record(moderator_email)) discussion['moderator_notification_enabled'] = str( api.portal.get_registry_record(moderator_notification_enabled)) discussion['show_commenter_image'] = str( api.portal.get_registry_record(show_commenter_image)) discussion['user_notification_enabled'] = str( api.portal.get_registry_record(user_notification_enabled)) objects['discussion'] = discussion portal_workflow = api.portal.get_tool('portal_workflow') objects['workflow'] = portal_workflow.getDefaultChain()[0] portal_resources = getUtility(IResourceDirectory, name='persistent') cpskin_resources_folder = portal_resources['cpskin'] if cpskin_resources_folder: resources = {} for res in cpskin_resources_folder.listDirectory(): resources[res] = cpskin_resources_folder[res].data objects['resources'] = resources # abonnes brains = api.content.find(portal_type='NewsletterTheme') newsletters = {} for brain in brains: obj = brain.getObject() path = brain.getPath() subscriber_brains = obj.getSubscribers() subscribers = [] for subscriber_brain in subscriber_brains: subscriber_obj = subscriber_brain.getObject() subs = {} subs['active'] = subscriber_obj.active subs['email'] = subscriber_obj.email subs['fullname'] = subscriber_obj.fullname subs['format'] = subscriber_obj.format subscribers.append(subs) newsletters[path] = subscribers objects['newsletters'] = newsletters # leadimage portal_properties = api.portal.get_tool('portal_properties') cli_properties = portal_properties.get('cli_properties', None) if cli_properties: leadimage_settings = {} leadimage_settings['allowed_types'] = cli_properties.allowed_types objects['leadimage'] = leadimage_settings # behaviors portal_types = api.portal.get_tool('portal_types') behaviors = {} for portal_type in portal_types: fti = portal_types[portal_type] if IDexterityFTI.providedBy(fti): behaviors[portal_type] = fti.behaviors objects['behaviors'] = behaviors portal_catalog = api.portal.get_tool('portal_catalog') total_objects = len(portal_catalog({})) objects['total_objects'] = str(total_objects) response = self.request.response response.setHeader('Content-type', 'application/json') return json.dumps(objects)
def invalidate(self, fti): if not IDexterityFTI.providedBy(fti): fti = queryUtility(IDexterityFTI, name=fti) if fti is not None: invalidate_cache(fti) self.invalidations += 1
def migrateCustomAT(fields_mapping, src_type, dst_type, dry_run=False): """ Try to get types infos from archetype_tool, then set a migrator and pass it given values. There is a dry_run mode that allows to check the success of a migration without committing. """ portal = getSite() # if the type still exists get the src_meta_type from the portal_type portal_types = getToolByName(portal, 'portal_types') fti = portal_types.get(src_type, None) # Check if the fti was removed or replaced by a DX-implementation if fti is None or IDexterityFTI.providedBy(fti): # Get the needed info from an instance of the type catalog = portal.portal_catalog brains = catalog(portal_type=src_type, sort_limit=1) if not brains: # no item? assume stuff is_folderish = False src_meta_type = src_type else: src_obj = brains[0].getObject() if IDexterityContent.providedBy(src_obj): logger.error('%s should not be dexterity object!', src_obj.absolute_url()) is_folderish = getattr(src_obj, 'isPrincipiaFolderish', False) src_meta_type = src_obj.meta_type else: # Get info from at-fti src_meta_type = fti.content_meta_type archetype_tool = getToolByName(portal, 'archetype_tool', None) for info in archetype_tool.listRegisteredTypes(): # lookup registered type in archetype_tool with meta_type # because several portal_types can use same meta_type if info.get('meta_type') == src_meta_type: klass = info.get('klass', None) is_folderish = klass.isPrincipiaFolderish migrator = makeCustomATMigrator(context=portal, src_type=src_type, dst_type=dst_type, fields_mapping=fields_mapping, is_folderish=is_folderish, dry_run=dry_run) if migrator: migrator.src_meta_type = src_meta_type migrator.dst_meta_type = '' walker_settings = { 'portal': portal, 'migrator': migrator, 'src_portal_type': src_type, 'dst_portal_type': dst_type, 'src_meta_type': src_meta_type, 'dst_meta_type': '', 'use_savepoint': True } if dry_run: walker_settings['limit'] = 1 walker = CustomQueryWalker(**walker_settings) walker.go() walker_infos = { 'errors': walker.errors, 'msg': walker.getOutput().splitlines(), 'counter': walker.counter } for error in walker.errors: logger.error(error.get('message')) if dry_run: transaction.abort() return walker_infos
def __call__(self): # Check if user has permission to add content here sm = getSecurityManager() if not sm.checkPermission(AddPortalContent, self.context): response = self.request.RESPONSE response.setStatus(403) return "You are not authorized to add content to this folder." req = self.request tusrequest = False if TUS_ENABLED: adapter = Zope2RequestAdapter(req) tus = Tus(adapter, **tus_settings) if tus.valid: tusrequest = True tus.handle() if not tus.upload_finished: return else: filename = req.getHeader('FILENAME') if tus.send_file: filedata = req._file filedata.filename = filename else: filepath = req._file.read() filedata = open(filepath) if not tusrequest: if req.REQUEST_METHOD != 'POST': return filedata = self.request.form.get("file", None) if filedata is None: return filename = filedata.filename content_type = mimetypes.guess_type(filename)[0] or "" if not filedata: return # Determine if the default file/image types are DX or AT based ctr = getToolByName(self.context, 'content_type_registry') type_ = ctr.findTypeName(filename.lower(), '', '') or 'File' # Now check that the object is not restricted to be added in the # current context allowed_ids = [ fti.getId() for fti in self.context.allowedContentTypes() ] if type_ not in allowed_ids: response = self.request.RESPONSE response.setStatus(403) if type_ == 'File': return "You cannot add a File to this folder, try another one" if type_ == 'Image': return "You cannot add an Image to this folder, try another one" dx_based = False pt = getToolByName(self.context, 'portal_types') if IDexterityFTI.providedBy(getattr(pt, type_)): factory = IDXFileFactory(self.context) dx_based = True else: from Products.ATContentTypes.interfaces import IATCTFileFactory factory = IATCTFileFactory(self.context) obj = factory(filename, content_type, filedata) if dx_based: if 'File' in obj.portal_type: size = obj.file.getSize() content_type = obj.file.contentType elif 'Image' in obj.portal_type: size = obj.image.getSize() content_type = obj.image.contentType result = {"type": content_type, "size": size} else: try: size = obj.getSize() except AttributeError: size = obj.getObjSize() result = {"type": obj.getContentType(), "size": size} if tusrequest: tus.cleanup_file() result.update({ 'url': obj.absolute_url(), 'name': obj.getId(), 'UID': IUUID(obj), 'filename': filename }) return json.dumps(result)
def jupload__call__(self): authenticator = getMultiAdapter((self.context, self.request), name=u"authenticator") if not authenticator.verify() or \ self.request['REQUEST_METHOD'] != 'POST': raise Unauthorized filedata = self.request.form.get("files[]", None) if filedata is None: return filename = filedata.filename content_type = mimetypes.guess_type(filename)[0] or "" if not filedata: return ctr = getToolByName(self.context, 'content_type_registry') type_ = ctr.findTypeName(filename.lower(), '', '') or 'File' # Determine if the default file/image types are DX or AT based DX_BASED = False context_state = getMultiAdapter((self.context, self.request), name=u'plone_context_state') if HAS_DEXTERITY: pt = getToolByName(self.context, 'portal_types') if IDexterityFTI.providedBy(getattr(pt, type_)): factory = IDXFileFactory(self.context) DX_BASED = True else: factory = IATCTFileFactory(self.context) # if the container is a DX type, get the available types from the behavior if IDexterityFTI.providedBy(getattr(pt, self.context.portal_type)): addable_types = ISelectableConstrainTypes( self.context).getLocallyAllowedTypes() elif context_state.is_portal_root(): allowed_types = _allowedTypes(self.request, self.context) addable_types = [fti.getId() for fti in allowed_types] else: addable_types = self.context.getLocallyAllowedTypes() else: factory = IATCTFileFactory(self.context) if context_state.is_portal_root(): allowed_types = _allowedTypes(self.request, self.context) addable_types = [fti.getId() for fti in allowed_types] else: addable_types = self.context.getLocallyAllowedTypes() # if the type_ is disallowed in this folder, return an error if type_ not in addable_types: msg = translate( _WF('disallowed_type_error', default='${filename}: adding of "${type}" \ type is disabled in this folder', mapping={'filename': filename, 'type': type_}), context=self.request ) return json.dumps({'files': [{'error': msg}]}) obj = factory(filename, content_type, filedata) if DX_BASED: if 'File' in obj.portal_type: size = obj.file.getSize() content_type = obj.file.contentType elif 'Image' in obj.portal_type: size = obj.image.getSize() content_type = obj.image.contentType result = { "url": obj.absolute_url(), "name": obj.getId(), "type": content_type, "size": size } else: try: size = obj.getSize() except AttributeError: size = obj.getObjSize() result = { "url": obj.absolute_url(), "name": obj.getId(), "type": obj.getContentType(), "size": size } if 'Image' in obj.portal_type: result['thumbnail_url'] = result['url'] + '/@@images/image/tile' return json.dumps({ 'files': [result] })