示例#1
0
    def query_parent_objects(self, context, query=None):
        """Return the objects of the same type from the parent object

        :param query: Catalog query to narrow down the objects
        :type query: dict
        :returns: Content objects of the same portal type in the parent
        """

        # return the object values if we have no catalog query
        if query is None:
            return self.get_parent_objects(context)

        # avoid undefined reference of catalog in except...
        catalog = None

        # try to fetch the results via the catalog
        try:
            catalogs = api.get_catalogs_for(context)
            catalog = catalogs[0]
            return map(api.get_object, catalog(query))
        except (IndexError, UnicodeDecodeError, ParseError, APIError) as e:
            # fall back to the object values of the parent
            logger.warn("UniqueFieldValidator: Catalog query {} failed "
                        "for catalog {} ({}) -> returning object values of {}"
                        .format(query, repr(catalog), str(e),
                                repr(api.get_parent(context))))
            return self.get_parent_objects(context)
示例#2
0
    def query_parent_objects(self, context, query=None):
        """Return the objects of the same type from the parent object

        :param query: Catalog query to narrow down the objects
        :type query: dict
        :returns: Content objects of the same portal type in the parent
        """

        # return the object values if we have no catalog query
        if query is None:
            return self.get_parent_objects(context)

        # avoid undefined reference of catalog in except...
        catalog = None

        # try to fetch the results via the catalog
        try:
            catalogs = api.get_catalogs_for(context)
            catalog = catalogs[0]
            return map(api.get_object, catalog(query))
        except (IndexError, UnicodeDecodeError, ParseError, api.BikaLIMSError) as e:
            # fall back to the object values of the parent
            logger.warn("UniqueFieldValidator: Catalog query {} failed "
                        "for catalog {} ({}) -> returning object values of {}"
                        .format(query, repr(catalog), str(e),
                                repr(api.get_parent(context))))
            return self.get_parent_objects(context)
示例#3
0
    def __call__(self, value, *args, **kwargs):
        field = kwargs['field']
        fieldname = field.getName()
        instance = kwargs['instance']
        translate = getToolByName(instance, 'translation_service').translate

        # return directly if nothing changed
        if value == field.get(instance):
            return True

        # We want to use the catalog to speed things up, as using `objectValues`
        # is very expensive if the parent object contains many items
        parent_objects = []

        # 1. Get the right catalog for this object
        catalogs = api.get_catalogs_for(instance)
        catalog = catalogs[0]

        # 2. Check if the field accessor is indexed
        field_index = None
        accessor = field.getAccessor(instance)
        if accessor:
            field_index = accessor.__name__

        # 3. Check if the field index is in the indexes
        # Field is indexed, use the catalog instead of objectValues
        parent_path = api.get_parent_path(instance)
        portal_type = instance.portal_type
        catalog_query = {"portal_type": portal_type,
                            "path": {"query": parent_path, "depth": 1}}

        if field_index and field_index in catalog.indexes():
            # We use the field index to reduce the results list
            catalog_query[field_index] = value
            parent_objects = map(api.get_object, catalog(catalog_query))
        elif fieldname in catalog.indexes():
            # We use the fieldname as index to reduce the results list
            catalog_query[fieldname] = value
            parent_objects = map(api.get_object, catalog(catalog_query))
        else:
            # fall back to the objectValues :(
            parent_object = api.get_parent(instance)
            parent_objects = parent_object.objectValues()

        for item in parent_objects:
            if hasattr(item, 'UID') and item.UID() != instance.UID() and \
               fieldname in item.Schema() and \
               str(item.Schema()[fieldname].get(item)) == str(value):
                # We have to compare them as strings because
                # even if a number (as an  id) is saved inside
                # a string widget and string field, it will be
                # returned as an int. I don't know if it is
                # caused because is called with
                # <item.Schema()[fieldname].get(item)>,
                # but it happens...
                msg = _("Validation failed: '${value}' is not unique",
                        mapping={'value': safe_unicode(value)})
                return to_utf8(translate(msg))
        return True
示例#4
0
    def get_catalog_for(self, brain_or_object):
        """Return the primary catalog for the given brain or object
        """
        if not api.is_object(brain_or_object):
            raise TypeError("Invalid object type %r" % brain_or_object)
        catalogs = api.get_catalogs_for(brain_or_object, default="uid_catalog")

        return catalogs[0]
示例#5
0
    def make_catalog_query(self, context, field, value):
        """Create a catalog query for the field
        """

        # get the catalogs for the context
        catalogs = api.get_catalogs_for(context)
        # context not in any catalog?
        if not catalogs:
            logger.warn("UniqueFieldValidator: Context '{}' is not assigned"
                        "to any catalog!".format(repr(context)))
            return None

        # take the first catalog
        catalog = catalogs[0]

        # Check if the field accessor is indexed
        field_index = field.getName()
        accessor = field.getAccessor(context)
        if accessor:
            field_index = accessor.__name__

        # return if the field is not indexed
        if field_index not in catalog.indexes():
            return None

        # build a catalog query
        query = {
            "portal_type": api.get_portal_type(context),
            "path": {
                "query": api.get_parent_path(context),
                "depth": 1,
            }
        }
        query[field_index] = value
        logger.info("UniqueFieldValidator:Query={}".format(query))
        return query
示例#6
0
    def make_catalog_query(self, context, field, value):
        """Create a catalog query for the field
        """

        # get the catalogs for the context
        catalogs = api.get_catalogs_for(context)
        # context not in any catalog?
        if not catalogs:
            logger.warn("UniqueFieldValidator: Context '{}' is not assigned"
                        "to any catalog!".format(repr(context)))
            return None

        # take the first catalog
        catalog = catalogs[0]

        # Check if the field accessor is indexed
        field_index = field.getName()
        accessor = field.getAccessor(context)
        if accessor:
            field_index = accessor.__name__

        # return if the field is not indexed
        if field_index not in catalog.indexes():
            return None

        # build a catalog query
        query = {
            "portal_type": api.get_portal_type(context),
            "path": {
                "query": api.get_parent_path(context),
                "depth": 1,
            }
        }
        query[field_index] = value
        logger.info("UniqueFieldValidator:Query={}".format(query))
        return query
示例#7
0
    def __call__(self, value, *args, **kwargs):
        field = kwargs['field']
        fieldname = field.getName()
        instance = kwargs['instance']
        translate = getToolByName(instance, 'translation_service').translate

        # return directly if nothing changed
        if value == field.get(instance):
            return True

        # We want to use the catalog to speed things up, as using `objectValues`
        # is very expensive if the parent object contains many items
        parent_objects = []

        # 1. Get the right catalog for this object
        catalogs = api.get_catalogs_for(instance)
        catalog = catalogs[0]

        # 2. Check if the field accessor is indexed
        field_index = None
        accessor = field.getAccessor(instance)
        if accessor:
            field_index = accessor.__name__

        # 3. Check if the field index is in the indexes
        # Field is indexed, use the catalog instead of objectValues
        parent_path = api.get_parent_path(instance)
        portal_type = instance.portal_type
        catalog_query = {
            "portal_type": portal_type,
            "path": {
                "query": parent_path,
                "depth": 1
            }
        }

        if field_index and field_index in catalog.indexes():
            # We use the field index to reduce the results list
            catalog_query[field_index] = value
            parent_objects = map(api.get_object, catalog(catalog_query))
        elif fieldname in catalog.indexes():
            # We use the fieldname as index to reduce the results list
            catalog_query[fieldname] = value
            parent_objects = map(api.get_object, catalog(catalog_query))
        else:
            # fall back to the objectValues :(
            parent_object = api.get_parent(instance)
            parent_objects = parent_object.objectValues()

        for item in parent_objects:
            if hasattr(item, 'UID') and item.UID() != instance.UID() and \
               fieldname in item.Schema() and \
               str(item.Schema()[fieldname].get(item)) == str(value):
                # We have to compare them as strings because
                # even if a number (as an  id) is saved inside
                # a string widget and string field, it will be
                # returned as an int. I don't know if it is
                # caused because is called with
                # <item.Schema()[fieldname].get(item)>,
                # but it happens...
                msg = _("Validation failed: '${value}' is not unique",
                        mapping={'value': safe_unicode(value)})
                return to_utf8(translate(msg))
        return True