Пример #1
0
class InterfaceData(object):
    """returns all properties data
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, object):
        self.object = object
        self.adapted = IMarkerInterfaces(self.object)

    security.declarePrivate('getData')
    def getData(self):
        """returns all important data"""
        return self.getInterfaceData()

    security.declarePrivate('getInterfaceData')
    def getInterfaceData(self):
        """
        Returns a list of directlyProvided interfaces.
        Example Return: [
            'foo.bar.IDemoInterface',
            ....
            ]

        @return:    list
        @rtype:     list
        """
        return self.adapted.getDirectlyProvidedNames()

    security.declarePrivate('setData')
    def setData(self, interfacedata, metadata):
        """
        Sets a list of properties on a object.
        Warning: all currently set properties which are not in the
        properties-list wille be removed!

        @param object:      Plone-Object to set the properties on
        @type object:       Plone-Object
        @param properties:  list of propertes.
                            See ftw.publisher.sender.extractor
                            for format details.
        @param type:        list
        @return:            None
        """
        self.logger.info('Updating interface data (UID %s)' %
                (self.object.UID())
        )

        current_ifaces = set(self.adapted.getDirectlyProvidedNames())
        desired_ifaces = set(interfacedata)

        for iface_dotted in current_ifaces - desired_ifaces:
            iface = resolve(iface_dotted)
            noLongerProvides(self.object, iface)

        for iface_dotted in desired_ifaces - current_ifaces:
            iface = resolve(iface_dotted)
            alsoProvides(self.object, iface)
Пример #2
0
class ShopItemVariations(object):
    """DataCollector adapter for Shop Item Variations.
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.object = obj

    security.declarePrivate('getData')
    def getData(self):
        variations_config = queryAdapter(self.object, IVariationConfig)
        if variations_config:
            data = deepcopy(variations_config.getVariationDict())
        else:
            data = PersistentMapping()
        data = make_serializable(data)
        data = serialize_decimals(data)
        return data

    security.declarePrivate('setData')
    def setData(self, data, metadata):
        variations_config = queryAdapter(self.object, IVariationConfig)
        self.logger.info('Updating variations config (UID %s)' %
                         (self.object.UID()))

        data = make_persistent(data)
        data = deserialize_decimals(data)
        if data in ({}, PersistentMapping()):
            variations_config.purge_dict()
        else:
            variations_config.updateVariationConfig(data)
Пример #3
0
class ShopCategorizableReferences(object):
    """DataCollector adapter for the category references of the categorizable shop types.
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.object = obj

    security.declarePrivate('getData')
    def getData(self):
        return [reference.UID() for reference in self.object.listCategories()]

    security.declarePrivate('setData')
    def setData(self, data, metadata):
        self.logger.info('Updating shop item category references (UID %s)' %
                         (self.object.UID()))

        uid_catalog = getToolByName(self.object, 'uid_catalog')

        # Add categories available on source.
        for category_uid in data:
            brains = uid_catalog(UID=category_uid)
            if brains:
                self.object.addToCategory(brains[0].getObject())

        # Remove categories no longer available on the source.
        existing_categories = [reference.UID() for reference in self.object.listCategories()]
        categories_to_be_removed = set(existing_categories) - set(data)
        for category in categories_to_be_removed:
            self.object.removeFromCategory(category)
Пример #4
0
class GeoData(object):
    """returns geo data
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.object = obj
        self.manager = queryAdapter(obj, IGeoManager)

    security.declarePrivate('getData')

    def getData(self):
        if self.manager:
            return self.manager.getCoordinates()
        else:
            return None

    security.declarePrivate('setData')

    def setData(self, geodata, metadata):
        self.logger.info('Updating geo data (UID %s)' % (self.object.UID()))

        if geodata == (None, None):
            self.manager.removeCoordinates()
        else:
            self.manager.setCoordinates(*geodata)
Пример #5
0
class CustomStyles(object):

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.obj = obj

    security.declarePrivate('getData')

    def getData(self):
        return ICustomStyles(self.obj).get_styles()

    security.declarePrivate('setData')

    def setData(self, themedata, metadata):
        ICustomStyles(self.obj).set_styles(themedata)
Пример #6
0
class ShopCategorizableRanks(object):
    """DataCollector adapter for the (category) ranks of the categorizable shop types.
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.object = obj

    security.declarePrivate('getData')
    def getData(self):
        return getattr(self.object, '_categoryRanks', PersistentMapping())

    security.declarePrivate('setData')
    def setData(self, data, metadata):
        self.logger.info('Updating shop item ranks (UID %s)' %
                         (self.object.UID()))

        self.object._categoryRanks = data
Пример #7
0
class BookLayoutRequestLayerCollector(object):
    """IDataCollector for supporting publishing books (ftw.publisher) with
    custom layouts and schema extender fields bound on layout request layer.

    When a custom layout is activated in the book, the request provides the
    layout interface as soon as traversing the book.
    The layout may add schema extender fields when the request provides the
    layout interface.
    In order to publish those field values correctly (with the standard
    FieldData collector), we need to provide the request layer before
    extracting data (sender) or setting data (receiver).

    Schema extender fields may be applied to not only the book itself but also
    to any content within the book. Therfore this collector should be used
    for all objects.

    The collector may be triggered when the book is traversed but also when
    it wasn't, therefore we cannot rely on the default book traversal adapter
    applying the layer interfaces to the request.
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, context):
        self.context = context

    security.declarePrivate('getData')

    def getData(self):
        book = self.get_parent_book()
        if not book:
            return None

        layers = [IWithinBookLayer]
        layout_layer_name = getattr(book, 'latex_layout', '')
        if layout_layer_name:
            layers.append(resolve(layout_layer_name))

        self.provide_request_layers(layers)
        self.flush_schemaextender_cache()
        return map(dottedname, layers)

    security.declarePrivate('setData')

    def setData(self, layers_dottednames, metadata):
        if not layers_dottednames:
            return

        self.logger.info(
            'BookLayoutRequestLayerCollector: provide request layers {0}'.
            format(layers_dottednames))

        layers = map(resolve, layers_dottednames)
        self.provide_request_layers(layers)
        self.flush_schemaextender_cache()

    def get_parent_book(self):
        context = self.context

        while context and not ISiteRoot.providedBy(context):
            if IBook.providedBy(context):
                return context
            context = aq_parent(aq_inner(context))

        return None

    def provide_request_layers(self, layers):
        """ Add a layer interface on the request
        """
        request = self.context.REQUEST
        layers = [iface for iface in layers if not iface.providedBy(request)]
        ifaces = layers + list(directlyProvidedBy(request))

        # Since we allow multiple markers here, we can't use
        # zope.publisher.browser.applySkin() since this filters out
        # IBrowserSkinType interfaces, nor can we use alsoProvides(), since
        # this appends the interface (in which case we end up *after* the
        # default Plone/CMF skin)
        directlyProvides(request, *ifaces)

    def flush_schemaextender_cache(self):
        """Flushes the schemaextender cache after conditions for
        schema extenders may have changed.
        """
        try:
            delattr(self.context.REQUEST, CACHE_KEY)
        except AttributeError:
            pass
class TopicCriteraData(object):
    """returns all properties data
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, object):
        self.object = object

    security.declarePrivate('getData')

    def getData(self):
        """returns all important data"""
        return self.getTopicCriterias()

    security.declarePrivate('getTopicCriterias')

    def getTopicCriterias(self):
        """
        extract data from topic criterions, like regular field adapter.
        but in a special way, because the topic criteras are no accessible
        by the catalog

        data = {'criteria_type':{field_data_adapter result}}

        """
        criterias = {}
        # Use contentValues for implicit ftw.trash compatibility.
        for criteria in self.object.contentValues():
            field_data_adapter = queryAdapter(criteria,
                                              IDataCollector,
                                              name="field_data_adapter")
            # this adapter must be available, otherwise we cannot go ahead
            if field_data_adapter is None:
                continue

            # dont add subcollections
            if isinstance(criteria, self.object.__class__):
                continue

            id = criteria.id
            data = field_data_adapter.getData()
            data['meta_type'] = criteria.meta_type
            criterias[id] = data

        return criterias

    security.declarePrivate('setData')

    def setData(self, topic_criteria_data, metadata):
        """
        creates criterias fro a topic from
        {'criteria_type':{field_data_adapter result}}
        """
        self.logger.info('Updating criterias for topic (UID %s)' %
                         (self.object.UID()))

        # easiest way - first delete all criterias
        self.object.manage_delObjects([
            i for i in self.object.objectIds()
            if i != 'syndication_information'
        ])

        for criteria_id, data in topic_criteria_data.items():
            # create criteria

            # sortCriteria behave a bit special
            if 'ATSortCriterion' not in criteria_id:
                criteria = self.object.addCriterion(data['field'],
                                                    data['meta_type'])

            # add/change sort criteria
            if 'ATSortCriterion' in criteria_id:
                self.object.setSortCriterion(data['field'], data['reversed'])

            # we don't have to update data for for ATSortCriterion
            # check topic.py line 293
            if 'ATSortCriterion' not in criteria_id:
                field_data_adapter = queryAdapter(criteria,
                                                  IDataCollector,
                                                  name="field_data_adapter")
                field_data_adapter.setData(data, metadata)
Пример #9
0
class Backreferences(object):
    """ Resets backreferences (pointing from another already released
    object to "me").
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, obj):
        self.context = obj

    security.declarePrivate('getData')
    def getData(self):
        """ Returns backreferences:
        {
            'uid-obj-a': {
                'the-field': [
                    'uid-of-another-unpublished-object',
                    'my-uid',
                    'uid-obj-b',
                ],
            },
            'uid-obj-b': {
                'ref-field': 'my-uid',
            },
        }
        """

        data = {}

        if hasattr(aq_base(self.context), 'getBackReferenceImpl'):
            referenceable = self.context

        else:
            try:
                referenceable = IReferenceable(self.context)

            except TypeError:
                # could not adapt
                # this means we have a dexterity object without
                # plone.app.referenceablebehavior activated.
                return data

        old_security_manager = getSecurityManager()
        newSecurityManager(self.context.REQUEST, SpecialUsers.system)
        try:
            references = referenceable.getBackReferenceImpl()
        finally:
            setSecurityManager(old_security_manager)

        for ref in references:
            # get source object
            src = ref.getSourceObject()
            if src is None:
                continue

            suid = src.UID()

            if suid not in data.keys():
                data[suid] = {}
            if getattr(ref, 'field', None) is None:
                continue

            if ref.field in data[suid]:
                # we already added this field
                continue
            else:
                # add the field value
                field = src.getField(ref.field)
                if field:
                    data[suid][ref.field] = field.getRaw(src)

        return data

    security.declarePrivate('setData')
    def setData(self, data, metadata):
        self.logger.info('Updating backreferences (UID %s)' %
                         metadata['UID'])
        cuid = self.context.UID()

        for suid, mapping in data.items():
            sobj = uuidToObject(suid)
            if not sobj:
                # source object is not published
                continue

            self.logger.info('... source-obj: %s' % '/'.join(
                    sobj.getPhysicalPath()))
            for fieldname, value in mapping.items():
                # value maybe uid (str) or list of uids (list)
                if isinstance(value, str):
                    value = [value]
                    single = True
                else:
                    single = False
                new_value = []

                # only set the targets that exist (=may be published)
                for tuid in value:
                    if tuid == cuid:
                        new_value.append(self.context)
                    else:
                        tobj = reference_catalog.lookupObject(tuid)
                        if tuid:
                            new_value.append(tobj)

                # set the new value on the field
                field = sobj.getField(fieldname)
                if single and new_value:
                    field.set(sobj, new_value[0])
                elif single:
                    field.set(sobj, None)
                else:
                    field.set(sobj, new_value)
class PropertiesData(object):
    """returns all properties data
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, object):
        self.object = object

    security.declarePrivate('getData')

    def getData(self):
        """returns all important data"""
        return self.getPropertyData()

    security.declarePrivate('getPropertyData')

    def getPropertyData(self):
        """
        Returns a list of dictonaries each representing a property.
        Example Return: [
        {
        'type' : 'string',
        'id' : 'title',
        'value' : 'test1',
        'mode' : 'wd',
        },
        {
        'type' : 'text',
        'id' : 'blubb',
        'value' : 'asdfsadf
        asdf',
        },
        ]

        @return:    list of properties
        @rtype:     list
        """

        properties = []
        for prop in self.object._propertyMap():
            # create a copy (we dont want to change the effective property)
            prop = prop.copy()
            # add the value

            if IPloneSiteRoot.providedBy(
                    self.object) and prop['id'] != 'layout':
                continue

            prop['value'] = self.object.getProperty(prop['id'])
            properties.append(prop)

        # property filter for special types
        # ex. date - we have to covert objects to strings
        for p in properties:
            if p['type'] == 'date':
                p['value'] = str(p['value'])

        return properties

    security.declarePrivate('setData')

    def setData(self, properties, metadata):
        """
        Sets a list of properties on a object.
        Warning: all currently set properties which are not in the
        properties-list wille be removed!

        @param object:      Plone-Object to set the properties on
        @type object:       Plone-Object
        @param properties:  list of propertes.
        See ftw.publisher.sender.extractor
        for format details.
        @param type:        list
        @return:            None
        """

        # plone root implementation
        root_path = '/'.join(self.object.getPhysicalPath())
        uid = hasattr(self.object, 'UID') and self.object.UID() or root_path
        self.logger.info('Updating properties (UID %s)' % (uid))

        # we need to cleanup the properties. remove all properties
        # from the object
        propertiesToUpdateOrCreate = [p['id'] for p in properties]
        currentProperties = self.object.propertyIds()
        # delete old properties
        propertiesToDelete = [
            id for id in currentProperties
            if id not in propertiesToUpdateOrCreate
        ]

        if not IPloneSiteRoot.providedBy(self.object):
            self.object.manage_delProperties(propertiesToDelete)
        elif 'layout' in currentProperties:
            # Delete layout property anyway - this supports removing the prop.
            self.object.manage_delProperties([
                'layout',
            ])

        # get cleaned up list of properties
        currentProperties = self.object.propertyIds()
        # update or create properites
        for prop in properties:

            # we have to check for some special prop types
            if prop['type'] == 'date':
                val = DateTime(prop['value'])
            else:
                val = prop['value']

            if prop['id'] in currentProperties:
                # update property if existing ...
                try:
                    self.object._updateProperty(id=prop['id'], value=val)
                except AttributeError:
                    self.logger.info(
                        'Could not set property "{0}" on {1}'.format(
                            prop['id'], uid))

            else:
                # ... otherwise
                self.object.manage_addProperty(id=prop['id'],
                                               value=val,
                                               type=prop['type'])
Пример #11
0
class PortletsData(object):
    """for plone's defautl portlet data, left and right area
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, object):
        self.object = object

    security.declarePrivate('getData')

    def getData(self):
        """returns all important data
        data form
        {'column':
        {portlet:
        {key:value}
        }
        .
        .
        .
        .
        {'blackliststatus':
        {category:True},

        {'order':
        ['portlet 1', 'portlet 2']}
        }
        }
        """

        data = {}
        plone_portlet_manager = []
        # gets all portlet managers used on this object
        annotations = getattr(self.object, '__annotations__', None)
        if not annotations:
            return data

        has_portlets = 'plone.portlets.contextassignments' in annotations
        has_blacklist = 'plone.portlets.categoryblackliststatus' in annotations
        if not has_portlets and not has_blacklist:
            return data

        if has_portlets:
            plone_portlet_manager += self.object.__annotations__[
                'plone.portlets.contextassignments'].keys()
        if has_blacklist:
            plone_portlet_manager += self.object.__annotations__[
                'plone.portlets.categoryblackliststatus'].keys()

        EXCLUDED_FIELDS = ['__name__', '__parent__']
        # XXX this is a static list, replace by a configlet option
        # the list contains all not serializable portlets (__module__)
        blacklisted_portlets = [
            'collective.dancing.browser.portlets.channelsubscribe'
        ]

        for manager_name in plone_portlet_manager:
            column = queryUtility(IPortletManager,
                                  name=manager_name,
                                  context=self.object)
            if column is None:
                continue

            # ok we have a portlet manager
            data[manager_name] = {}

            # get blackliststatus
            blacklist = getMultiAdapter((self.object, column),
                                        ILocalPortletAssignmentManager)
            data[manager_name]['blackliststatus'] = {}
            blacklistdata = data[manager_name]['blackliststatus']
            blacklistdata[GROUP_CATEGORY] = blacklist.getBlacklistStatus(
                GROUP_CATEGORY)
            blacklistdata[USER_CATEGORY] = blacklist.getBlacklistStatus(
                USER_CATEGORY)

            blacklistdata[CONTENT_TYPE_CATEGORY] = \
                blacklist.getBlacklistStatus(CONTENT_TYPE_CATEGORY)

            blacklistdata[CONTEXT_CATEGORY] = \
                blacklist.getBlacklistStatus(CONTEXT_CATEGORY)

            portlets = getMultiAdapter((
                self.object,
                column,
            ),
                                       IPortletAssignmentMapping,
                                       context=self.object)

            # portlets order - dicts are unsorted
            data[manager_name]['order'] = ','.join(portlets._order)

            for portlet_id in portlets.keys():
                portlet_assignment = portlets[portlet_id]
                # continue if portlet is blacklisted
                if portlet_assignment.__module__ in blacklisted_portlets:
                    continue

                # we habe a portlet
                data[manager_name][portlet_assignment.__name__] = {}
                data[manager_name][portlet_assignment.__name__]['module'] = \
                    portlet_assignment.__class__.__module__
                data[manager_name][portlet_assignment.__name__]['assignment_class_name'] = \
                    portlet_assignment.__class__.__name__

                # portlet settings (visibility)
                settings = IPortletAssignmentSettings(portlet_assignment).data
                data[manager_name][
                    portlet_assignment.__name__]['settings'] = settings

                # get all data
                for field in portlet_assignment.__dict__.keys():
                    if field not in EXCLUDED_FIELDS:
                        field_value = getattr(portlet_assignment, field, '')
                        # image field - image.portlet integration
                        if isinstance(field_value, OFSImage):
                            # same way as in AT field serializer

                            field_value = {
                                'module': OFSImage.__module__,
                                'klass_name': OFSImage.__name__,
                                'kwargs': {
                                    'file':
                                    base64.encodestring(field_value.data),
                                    'id': field_value.id(),
                                    'title': field_value.title
                                }
                            }

                        elif (HAS_NAMEDFILE
                              and INamedFile.providedBy(field_value)):
                            klass = type(field_value)
                            field_value = {
                                'module': klass.__module__,
                                'klass_name': klass.__name__,
                                'kwargs': {
                                    'data':
                                    base64.encodestring(field_value.data),
                                    'filename': field_value.filename,
                                    'contentType': field_value.contentType
                                }
                            }

                        data[manager_name][
                            portlet_assignment.__name__][field] = field_value

        return data

    security.declarePrivate('setData')

    def setData(self, portletsdata, metadata):
        """create or updates portlet informations
        """

        for manager_name in portletsdata.keys():
            column = queryUtility(IPortletManager,
                                  name=manager_name,
                                  context=self.object)
            if column is None:
                continue
            # ok we have a portlet manager
            # get all current assigned portlets
            portlets = getMultiAdapter((
                self.object,
                column,
            ),
                                       IPortletAssignmentMapping,
                                       context=self.object)
            p_ids = [p for p in portlets._data.keys()]
            # get new order
            order = portletsdata[manager_name]['order'] and \
                portletsdata[manager_name]['order'].split(',') or []

            # set blackliststatus
            blacklist = getMultiAdapter((self.object, column),
                                        ILocalPortletAssignmentManager)
            blacklistdata = portletsdata[manager_name]['blackliststatus']
            blacklist.setBlacklistStatus(GROUP_CATEGORY,
                                         blacklistdata[GROUP_CATEGORY])
            blacklist.setBlacklistStatus(USER_CATEGORY,
                                         blacklistdata[USER_CATEGORY])
            blacklist.setBlacklistStatus(CONTENT_TYPE_CATEGORY,
                                         blacklistdata[CONTENT_TYPE_CATEGORY])

            blacklist.setBlacklistStatus(CONTEXT_CATEGORY,
                                         blacklistdata[CONTEXT_CATEGORY])

            # bit clean up
            del portletsdata[manager_name]['blackliststatus']
            del portletsdata[manager_name]['order']

            # remove all currenlty assigned portlets from manager
            for p_id in p_ids:
                del portlets._data[p_id]

            for portlet_id in portletsdata[manager_name].keys():
                portletfielddata = portletsdata[manager_name][portlet_id]
                # get Assignment
                portlet_module = modules[portletfielddata['module']]
                portlet_class = getattr(
                    portlet_module, portletfielddata['assignment_class_name'])
                settings = portletfielddata.get('settings', None)
                # prepare data to pass as arguments
                del portletfielddata['module']
                del portletfielddata['assignment_class_name']
                del portletfielddata['settings']

                annotations = portletfielddata.get('__annotations__', None)
                if '__annotations__' in portletfielddata:
                    del portletfielddata['__annotations__']

                # check for dicts
                for k, v in portletfielddata.items():

                    if isinstance(v, dict):
                        # so we have one, now we have to turn the
                        # serialized data into an object
                        # this is generic, but currently only in use
                        # by the image portlet
                        klass = modules[v['module']].__dict__[v['klass_name']]

                        for argname in ('file', 'data'):
                            if argname in v['kwargs']:
                                v['kwargs'][argname] = base64.decodestring(
                                    v['kwargs'][argname])

                        imgobj = klass(**v['kwargs'])
                        portletfielddata[k] = imgobj

                portlets[portlet_id] = portlet_class(**portletfielddata)

                # XXX boolean value fix
                # for some reason boolean types cannpt be passed with **...
                # use setattr
                for k, v in portletfielddata.items():
                    if isinstance(v, bool):
                        setattr(portlets[portlet_id], k, v)

                if annotations:
                    portlets[portlet_id].__annotations__ = annotations

                # portlet settings (visibility)
                portlet_assignment = portlets[portlet_id]
                IPortletAssignmentSettings(portlet_assignment).data = settings

            # set new order afterwards
            portlets._order = PersistentList(order)
Пример #12
0
class FieldData(object):
    """returns all field data
    """

    implements(IDataCollector)
    logger = getLogger()
    security = ClassSecurityInformation()

    def __init__(self, object):
        self.object = object

    security.declarePrivate('getData')

    def getData(self):
        """returns all important data"""
        return self.getFieldData()

    security.declarePrivate('getFieldData')

    def getFieldData(self):
        """
        Extracts data from the object fields and creates / returns a dictionary
        with the data. Objects are converted to string.
        @return:    dictionary with extracetd data
        @rtype:     dict
        """
        data = {}

        fields = self.object.Schema().fields()

        for field in fields:
            # don't serialize AT ComputedFields
            if isinstance(field, ComputedField):
                continue
            name = field.getName()

            value = field.getRaw(self.object)
            value = self.fieldSerialization(field, value)
            data[name] = value

        return data

    security.declarePrivate('fieldSerialization')

    def fieldSerialization(self, field, value):
        """
        Custom serialization for fields which provide field values that are
        incompatible with json / JSON-standard.
        @param field:   Field-Object from Schema
        @type field:    Field
        @param value:   Return-Value of the Raw-Accessor of the Field on the
        current context
        @type value:    string or stream
        @return:        JSON-optimized value
        @rtype:         string
        """

        if isinstance(field, DateTimeField) and value:
            value = str(value)

        elif HAS_BLOBS and IBlobWrapper.providedBy(value):
            file_ = value.getBlob().open()
            value = {
                'filename': value.getFilename(),
                'data': base64.encodestring(file_.read()),
                'type': 'blob'
            }
            file_.close()

        elif isinstance(field, FileField) and isinstance(value, File):
            tmp = StringIO.StringIO(value.data)
            tmp.seek(0)
            value = {
                'filename': value.filename,
                'data': base64.encodestring(tmp.read())
            }

        elif isinstance(field, QueryField):
            query = field.getRaw(self.object)
            # Cast "ZPublisher.HTTPRequest.record" instance to dict
            value = [dict(item) for item in query]

        return value

    security.declarePrivate('setData')

    def setData(self, fielddata, metadata):
        """sets all important field data
        """

        # update with new values
        self.logger.info('Updating object values (UID %s)' % metadata['UID'])
        fields = self.object.Schema().fields()

        for field in fields:
            fieldname = field.getName()

            # do not update "id" field
            if fieldname == 'id':
                continue

            if fieldname in fielddata.keys():
                field_value = fielddata[fieldname]

                if field.mode == 'r':
                    continue

                field.getMutator(self.object)(field_value)