예제 #1
0
 def migrate_schema_fields(self):
     for schemata in iterSchemataForType('DashboardPODTemplate'):
         for fieldName, field in getFieldsInOrder(schemata):
             # bypass interface methods
             if not IMethod.providedBy(field):
                 # special handling for file field
                 setattr(self.new, fieldName, getattr(self.old, fieldName, None))
예제 #2
0
    def mapFieldTiles(self, settings, config, kwargs):
        args = {
            'type': None,
            'context': None,
            'request': None,
        }
        args.update(kwargs)
        if args['type'] is None:
            return config
        prefixes = []

        registry_omitted = settings.get(
            '%s.omitted_fields.%s' %
            (self.prefix, args['type'].replace('.', '_')),
            default=None,
        )
        if registry_omitted is None:
            registry_omitted = settings.get(
                self.prefix + '.default_omitted_fields',
                default=[],
            )

        for index, schema in enumerate(iterSchemataForType(args['type'])):
            prefix = ''
            if index > 0:
                prefix = schema.__name__
                if prefix in prefixes:
                    prefix = schema.__identifier__
                prefixes.append(prefix)

            for fieldconfig in extractFieldInformation(schema, args['context'],
                                                       args['request'],
                                                       prefix):
                if fieldconfig['id'] not in registry_omitted:
                    label = translate(fieldconfig['title'],
                                      context=args['request'])
                    tileconfig = {
                        'id':
                        'formfield-form-widgets-%s' % (fieldconfig['name'], ),
                        'name':
                        fieldconfig['name'],
                        'label':
                        label,
                        'category':
                        'fields',
                        'tile_type':
                        'field',
                        'read_only':
                        fieldconfig['readonly'],
                        'favorite':
                        False,
                        'widget':
                        fieldconfig['widget'],
                        'available_actions':
                        self.actionsForWidget(settings, fieldconfig['widget']),
                    }
                    index = getCategoryIndex(config['tiles'], 'fields')
                    if index is not None:
                        config['tiles'][index]['tiles'].append(tileconfig)
        return config
예제 #3
0
def has_relation_fields(fti):
    for schema in iterSchemataForType(fti):
        for fieldname in schema:
            field = schema[fieldname]
            if (IRelationChoice.providedBy(field) or
                IRelationList.providedBy(field)):
                return True
    return False
예제 #4
0
 def migrate_schema_fields(self):
     for schemata in iterSchemataForType('DashboardPODTemplate'):
         for fieldName, field in getFieldsInOrder(schemata):
             # bypass interface methods
             if not IMethod.providedBy(field):
                 # special handling for file field
                 setattr(self.new, fieldName,
                         getattr(self.old, fieldName, None))
예제 #5
0
def has_relation_fields(fti):
    for schema in iterSchemataForType(fti):
        for fieldname in schema:
            field = schema[fieldname]
            if (IRelationChoice.providedBy(field)
                    or IRelationList.providedBy(field)):
                return True
    return False
예제 #6
0
def get_field_and_schema_for_fieldname(field_id, portal_type):
    """Get field and its schema from a portal_type."""
    # Turn form.widgets.IDublinCore.title into title
    field_id = field_id.split(".")[-1]
    for schema in iterSchemataForType(portal_type):
        field = schema.get(field_id, None)
        if field is not None:
            return (field, schema)
예제 #7
0
    def create_destination_document(self):
        # get all the metadata that will be set on the created file.
        # We blacklist some fields that should not be copied
        fields_to_skip = set(("file",
                              "archival_file",
                              "archival_file_state",
                              "thumbnail",
                              "preview",
                              "digitally_available",
                              "changeNote",
                              "changed",
                              "relatedItems",))
        metadata = {}
        for schema in iterSchemataForType(self.context.portal_type):
            for name, schema_field in getFieldsInOrder(schema):
                if name in fields_to_skip:
                    continue
                field_instance = schema_field.bind(self.context)
                metadata[name] = field_instance.get(self.context)

        command = CreateDocumentCommand(self.destination, None, None, **metadata)
        destination_document = command.execute()

        # We make it in shadow state until its file is set by the callback view
        destination_document.as_shadow_document()
        # Add marker interface. This should be useful in the future for
        # cleanup jobs, retries if the PDF was not delivered and so on.
        alsoProvides(destination_document, IDocumentSavedAsPDFMarker)
        # Add annotations needed for the SavePDFDocumentUnder view.
        annotations = IAnnotations(destination_document)
        annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context)
        annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id

        # The missing_value attribute of a z3c-form field is used
        # as soon as an object has no default_value i.e. after creating
        # an object trough the command-line.
        #
        # Because the relatedItems field needs a list as a missing_value,
        # we will fall into the "mutable keyword argument"-python gotcha.
        # The relatedItems will be shared between the object-instances.
        #
        # Unfortunately the z3c-form field does not provide a
        # missing_value-factory (like the defaultFactory) which would be
        # necessary to fix this issue properly.
        #
        # As a workaround we make sure that the new document's relatedItems
        # is different object from the source document's.
        IRelatedDocuments(destination_document).relatedItems = list(
            IRelatedDocuments(destination_document).relatedItems)

        IRelatedDocuments(destination_document).relatedItems.append(
            RelationValue(getUtility(IIntIds).getId(self.context)))

        msg = _(u'Document ${document} was successfully created in ${destination}',
                mapping={"document": destination_document.title, "destination": self.destination.title})
        api.portal.show_message(msg, self.request, type='info')

        return destination_document
예제 #8
0
    def __call__(self):
        fti = self.context
        result = {
            # '@context': 'http://www.w3.org/ns/hydra/context.jsonld',
            'title': fti.id,
            'type': 'object',
            '$schema': 'http://json-schema.org/draft-04/hyper-schema#',
            'fieldsets': [],
            'required': [],
            'schemas': {},
            'properties': {},
        }

        for schema in iterSchemataForType(fti.id):

            schema_serializer = getMultiAdapter((schema, fti, self.request),
                                                ISchemaSerializer)
            result['schemas'][schema_serializer.name] = schema_serializer()

            fieldsets = schema.queryTaggedValue(FIELDSETS_KEY, [])
            fieldset_fields = set()
            for fieldset in fieldsets:
                fields = fieldset.fields
                # Keep a list so we can figure out what doesn't belong
                # to a fieldset
                fieldset_fields.update(fields)

                # Write the fieldset and any fields it contains
                fieldset_serializer = getMultiAdapter(
                    (fieldset, schema, fti, self.request), IFieldsetSerializer)
                result['fieldsets'].append({
                    'id': fieldset_serializer.name,
                    'title': fieldset_serializer.name,
                    'fields': fieldset_serializer()
                })

            # Handle any fields that aren't part of a fieldset
            non_fieldset_fields = [
                name for name, field in sortedFields(schema)
                if name not in fieldset_fields
            ]

            for fieldName in non_fieldset_fields:
                field = schema[fieldName]
                if field.required:
                    result['required'].append(fieldName)
                serializer = getMultiAdapter(
                    (field, schema, fti, self.request), IFieldSerializer)
                result['properties'][fieldName] = serializer()

            invariants = []
            for i in schema.queryTaggedValue('invariants', []):
                invariants.append("%s.%s" % (i.__module__, i.__name__))
            result['invariants'] = invariants

        if len(result['fieldsets']) == 0:
            del result['fieldsets']
        return result
예제 #9
0
    def mapFieldTiles(self, settings, config, kwargs):
        args = {
            'type': None,
            'context': None,
            'request': None,
        }
        args.update(kwargs)
        if args['type'] is None:
            return config
        prefixes = []

        registry_omitted = settings.get(
            '%s.omitted_fields.%s' % (self.prefix,
                                      args['type'].replace('.', '_')),
            default=None,
        )
        if registry_omitted is None:
            registry_omitted = settings.get(
                self.prefix + '.default_omitted_fields',
                default=[],
            )

        for index, schema in enumerate(iterSchemataForType(args['type'])):
            prefix = ''
            if index > 0:
                prefix = schema.__name__
                if prefix in prefixes:
                    prefix = schema.__identifier__
                prefixes.append(prefix)

            for fieldconfig in extractFieldInformation(
                    schema, args['context'], args['request'], prefix):
                if fieldconfig['id'] not in registry_omitted:
                    label = translate(fieldconfig['title'],
                                      context=args['request'])
                    tileconfig = {
                        'id': 'formfield-form-widgets-%s' % (
                            fieldconfig['name'],
                        ),
                        'name': fieldconfig['name'],
                        'label': label,
                        'category': 'fields',
                        'tile_type': 'field',
                        'read_only': fieldconfig['readonly'],
                        'favorite': False,
                        'widget': fieldconfig['widget'],
                        'available_actions': self.actionsForWidget(
                            settings,
                            fieldconfig['widget']
                        ),
                    }
                    index = getCategoryIndex(config['tiles'], 'fields')
                    if index is not None:
                        config['tiles'][index]['tiles'].append(tileconfig)
        return config
예제 #10
0
 def set_field_language_independent(self, portal_type, field, value='1'):
     """Set the given field in the given portal type language independent
     or unset from being one
     """
     for schema in iterSchemataForType(portal_type):
         if field in schema:
             ob = schema[field]
             if ILanguageIndependentField.providedBy(ob):
                 if value.lower() not in ('true', 'on', 'yes', 'y', '1'):
                     noLongerProvides(schema[ob], ILanguageIndependentField)
             else:
                 if value.lower() in ('true', 'on', 'yes', 'y', '1'):
                     alsoProvides(ob, ILanguageIndependentField)
예제 #11
0
 def execute(self):
     obj = super(CreateDossierFromTemplateCommand, self).execute()
     schemas = iterSchemataForType(self.portal_type)
     for schema in schemas:
         schema_name = BEHAVIOR_INTERFACE_MAPPING.get(
             schema.getName(), schema.getName())
         if schema_name not in self.additional_fields:
             continue
         behavior = schema(obj)
         for prop_name in self.additional_fields[schema_name]:
             setattr(behavior, prop_name,
                     self.additional_fields[schema_name][prop_name])
     return obj
예제 #12
0
 def set_field_language_independent(self, portal_type, field, value="1"):
     """Set the given field in the given portal type language independent
     or unset from being one
     """
     for schema in iterSchemataForType(portal_type):
         if field in schema:
             ob = schema[field]
             if ILanguageIndependentField.providedBy(ob):
                 if value.lower() not in ("true", "on", "yes", "y", "1"):
                     noLongerProvides(schema[ob], ILanguageIndependentField)
             else:
                 if value.lower() in ("true", "on", "yes", "y", "1"):
                     alsoProvides(ob, ILanguageIndependentField)
예제 #13
0
 def set_field_language_independent(self, portal_type, field, value='1'):
     """Set the given field in the given portal type language independent
     or unset from being one
     """
     disableCSRFProtection()
     for schema in iterSchemataForType(portal_type):
         if field in schema:
             ob = schema[field]
             if ILanguageIndependentField.providedBy(ob):
                 if value.lower() not in ('true', 'on', 'yes', 'y', '1'):
                     noLongerProvides(schema[ob], ILanguageIndependentField)
             else:
                 if value.lower() in ('true', 'on', 'yes', 'y', '1'):
                     alsoProvides(ob, ILanguageIndependentField)
예제 #14
0
def get_schema_info(portal_type, blacklist=None, whitelist=None):
    """Get a flat list of all fields in all schemas for a content-type.
    """
    fields = []
    for schema in iterSchemataForType(portal_type):
        for fieldname in schema:
            if blacklist:
                if fieldname not in blacklist:
                    fields.append((fieldname, schema.get(fieldname)))
            elif whitelist:
                if fieldname in whitelist:
                    fields.append((fieldname, schema.get(fieldname)))
            elif not blacklist and not whitelist:
                fields.append((fieldname, schema.get(fieldname)))
    return fields
예제 #15
0
def get_schema_info(portal_type, blacklist=None, whitelist=None):
    """Get a flat list of all fields in all schemas for a content-type.
    """
    fields = []
    for schema in iterSchemataForType(portal_type):
        for fieldname in schema:
            if blacklist:
                if fieldname not in blacklist:
                    fields.append((fieldname, schema.get(fieldname)))
            elif whitelist:
                if fieldname in whitelist:
                    fields.append((fieldname, schema.get(fieldname)))
            elif not blacklist and not whitelist:
                fields.append((fieldname, schema.get(fieldname)))
    return fields
def fields_list(context):
    portal = api.portal.get()
    ttool = api.portal.getToolByName(portal, 'translation_service')

    #annotations = IAnnotations(portal.request)
    #value = annotations.get(FIELD_LIST_CACHE, None)
    #if value is not None:
    #    return value

    terms = []

    # need to look up all the possible fields we can set on all the content
    # types we might update in the given folder
    found = {}
    terms = [
        SimpleVocabulary.createTerm('', '', ''),
        SimpleVocabulary.createTerm('_path', '_path', 'Path'),
        SimpleVocabulary.createTerm('_url', '_url', 'URL of Item')
    ]
    # path is special and allows us to import to dirs and export resulting path

    allowed_types = [
        IText, IBytes, IInt, IFloat, IDecimal, IChoice, IDatetime, ITime,
        IDate, IList, IRichText, INamedImageField
    ]

    for fti in get_allowed_types(context):
        portal_type = fti.getId()
        schemas = iterSchemataForType(portal_type)
        for _schema in schemas:
            for fieldid, field in getFieldsInOrder(_schema):

                if not any(
                    [ftype.providedBy(field) for ftype in allowed_types]):
                    continue

                if fieldid not in found:
                    found[fieldid] = 1
                    title = ttool.translate(field.title)
                    if not title:
                        continue
                    terms.append(
                        SimpleVocabulary.createTerm(fieldid, fieldid, title))

    value = SimpleVocabulary(terms)
    #annotations[FIELD_LIST_CACHE] = value
    return value
    def get_field_names_for_type(self, portal_type):
        names = []
        for schema in iterSchemataForType(self.portal_type):
            for name, field in getFieldsInOrder(schema):
                if name == 'changeNote':
                    # The changeNote field from p.a.versioningbehavior
                    # is a "fake" field - it never gets persisted, but
                    # written to request annotations instead
                    continue

                if name == 'reference_number':
                    # reference_number is a special field. It never gets
                    # set directly, but instead acts as a computed field
                    # for all intents and purposes.
                    continue

                names.append(name)
        return names
    def get_field_names_for_type(self, portal_type):
        names = []
        for schema in iterSchemataForType(self.portal_type):
            for name, field in getFieldsInOrder(schema):
                if name == 'changeNote':
                    # The changeNote field from p.a.versioningbehavior
                    # is a "fake" field - it never gets persisted, but
                    # written to request annotations instead
                    continue

                if name == 'reference_number':
                    # reference_number is a special field. It never gets
                    # set directly, but instead acts as a computed field
                    # for all intents and purposes.
                    continue

                names.append(name)
        return names
예제 #19
0
    def dump(self, portal_type):
        log.info("Dumping schemas for portal_type %r" % portal_type)
        fti = self._get_fti(portal_type)
        type_title = translate_de(fti.title, domain=fti.i18n_domain)

        schemas = []
        schema_dumper = SchemaDumper()

        for schema in iterSchemataForType(portal_type):
            schema_dump = schema_dumper.dump(schema)
            schemas.append(schema_dump)

        type_dump = OrderedDict((
            ('portal_type', portal_type),
            ('title', type_title),
            ('schemas', schemas),
        ))

        return type_dump
예제 #20
0
    def dump(self, portal_type):
            log.info("Dumping schemas for portal_type %r" % portal_type)
            fti = self._get_fti(portal_type)
            type_title = translate_de(fti.title, domain=fti.i18n_domain)

            schemas = []
            schema_dumper = SchemaDumper()

            for schema in iterSchemataForType(portal_type):
                schema_dump = schema_dumper.dump(schema)
                schemas.append(schema_dump)

            type_dump = OrderedDict((
                ('portal_type', portal_type),
                ('title', type_title),
                ('schemas', schemas),
            ))

            return type_dump
def fields_list(context):
    portal = api.portal.get()
    ttool = api.portal.getToolByName(portal, 'translation_service')

    #annotations = IAnnotations(portal.request)
    #value = annotations.get(FIELD_LIST_CACHE, None)
    #if value is not None:
    #    return value

    terms = []

    # need to look up all the possible fields we can set on all the content
    # types we might update in the given folder
    found = {}
    terms = [SimpleVocabulary.createTerm('', '', ''),
             SimpleVocabulary.createTerm('_path', '_path', 'Path'),
             SimpleVocabulary.createTerm('_url', '_url', 'URL of Item')]
    # path is special and allows us to import to dirs and export resulting path

    allowed_types = [IText, IBytes, IInt, IFloat, IDecimal, IChoice, IDatetime,
                     ITime, IDate]

    for fti in get_allowed_types(context):
        portal_type = fti.getId()
        schemas = iterSchemataForType(portal_type)
        for _schema in schemas:
            for fieldid, field in getFieldsInOrder(_schema):

                if not any([ftype.providedBy(field) for ftype in allowed_types]):
                    continue

                if fieldid not in found:
                    found[fieldid] = 1
                    title = ttool.translate(field.title)
                    if not title:
                        continue
                    terms.append(SimpleVocabulary.createTerm(fieldid, fieldid,
                                                             title))

    value = SimpleVocabulary(terms)
    #annotations[FIELD_LIST_CACHE] = value
    return value
    def getFieldsForDXType(self, typename):
        '''Returns schema fields (name and type) for the given DX typename.'''
        results = []
        typesTool = getToolByName(self.context, 'portal_types')
        fti = typesTool.getTypeInfo(typename)
        if not fti:
            return results

        for schemata in iterSchemataForType(typename):
            for fieldName, field in schemata.namesAndDescriptions():
                # ignore Dublin Core fields
                if fieldName in self.dx_metadata_fields:
                    continue
                translated_title = translate(field.title)
                class_name = field.__class__.__name__
                results.append(
                    {'id': fieldName,
                     'title': '%s (%s)' % (translated_title, class_name),
                     'type': class_name})
        return results
예제 #23
0
    def getFieldsForDXType(self, typename):
        '''Returns schema fields (name and type) for the given DX typename.'''
        results = []
        typesTool = getToolByName(self.context, 'portal_types')
        fti = typesTool.getTypeInfo(typename)
        if not fti:
            return results

        for schemata in iterSchemataForType(typename):
            for fieldName, field in schemata.namesAndDescriptions():
                # ignore Dublin Core fields
                if fieldName in self.dx_metadata_fields:
                    continue
                translated_title = translate(field.title)
                class_name = field.__class__.__name__
                results.append(
                    {'id': fieldName,
                     'title': '%s (%s)' % (translated_title, class_name),
                     'type': class_name})
        return results
예제 #24
0
def inject_title_and_description_defaults(kw, portal_type, container):
    """If 'title' or 'description' fields have defaults, inject them into `kw`.

    These fields need special handling because they get set to an empty string
    in a hardcoded fashion in the P.CMFCore.PortalFolder.PortalFolderBase
    constructor if no *actual* value has been provided for them.

    This will later fool our set_default_values() because it thinks a
    legitimate value for these fields has already been persisted on the object,
    and will therefore not attempt to determine and set defaults for those
    fields.

    We therefore handle title and description differently by determining their
    defaults ahead of object construction time, and inject them into `kw` (
    unless *actual* values are already provided in `kw` of course).
    """
    to_check = ['title', 'description']

    # Don't do anything for fields that have an *actual* value provided
    for field_name in kw:
        if field_name in to_check:
            to_check.remove(field_name)

    schemas = iterSchemataForType(portal_type)
    for schema in schemas:
        for name, field in getFieldsInOrder(schema):
            # Return early if no more fields are left to check. No need to
            # iterate over dozens of irrelevant fields.
            if not to_check:
                return

            for fn_to_check in to_check:
                if fn_to_check == name:
                    dv = determine_default_value(field, container)
                    # If there is a default, and there is no *actual* value
                    # in `kw` that should be set, inject the default into `kw`
                    if dv is not NO_DEFAULT_MARKER:
                        kw[fn_to_check] = dv
                        to_check.remove(name)
예제 #25
0
def inject_title_and_description_defaults(kw, portal_type, container):
    """If 'title' or 'description' fields have defaults, inject them into `kw`.

    These fields need special handling because they get set to an empty string
    in a hardcoded fashion in the P.CMFCore.PortalFolder.PortalFolderBase
    constructor if no *actual* value has been provided for them.

    This will later fool our set_default_values() because it thinks a
    legitimate value for these fields has already been persisted on the object,
    and will therefore not attempt to determine and set defaults for those
    fields.

    We therefore handle title and description differently by determining their
    defaults ahead of object construction time, and inject them into `kw` (
    unless *actual* values are already provided in `kw` of course).
    """
    to_check = ['title', 'description']

    # Don't do anything for fields that have an *actual* value provided
    for field_name in kw:
        if field_name in to_check:
            to_check.remove(field_name)

    schemas = iterSchemataForType(portal_type)
    for schema in schemas:
        for name, field in getFieldsInOrder(schema):
            # Return early if no more fields are left to check. No need to
            # iterate over dozens of irrelevant fields.
            if not to_check:
                return

            for fn_to_check in to_check:
                if fn_to_check == name:
                    dv = determine_default_value(field, container)
                    # If there is a default, and there is no *actual* value
                    # in `kw` that should be set, inject the default into `kw`
                    if dv is not NO_DEFAULT_MARKER:
                        kw[fn_to_check] = dv
                        to_check.remove(name)
예제 #26
0
    def mapFieldTiles(self, settings, config, kwargs):
        args = {"type": None, "context": None, "request": None}
        args.update(kwargs)
        if args["type"] is None:
            return config
        prefixes = []

        for index, schema in enumerate(iterSchemataForType(args["type"])):
            prefix = ""
            if index > 0:
                prefix = schema.__name__
                if prefix in prefixes:
                    prefix = schema.__identifier__
                prefixes.append(prefix)
            registry_omitted = settings.get(
                "%s.omitted_fields.%s" % (self.prefix, args["type"].replace(".", "_")), default=None
            )
            if registry_omitted is None:
                registry_omitted = settings.get(self.prefix + ".default_omitted_fields", default=[])
            for fieldconfig in extractFieldInformation(schema, args["context"], args["request"], prefix):
                if fieldconfig["id"] not in registry_omitted:
                    label = translate(fieldconfig["title"], context=args["request"])
                    tileconfig = {
                        "id": "formfield-form-widgets-%s" % (fieldconfig["name"],),
                        "name": fieldconfig["name"],
                        "label": label,
                        "category": "fields",
                        "tile_type": "field",
                        "read_only": fieldconfig["readonly"],
                        "favorite": False,
                        "widget": fieldconfig["widget"],
                        "available_actions": self.actionsForWidget(settings, fieldconfig["widget"]),
                    }
                    index = getCategoryIndex(config["tiles"], "fields")
                    if index is not None:
                        config["tiles"][index]["tiles"].append(tileconfig)
        return config
예제 #27
0
    def execute(self):
        obj = super(CreateDossierFromTemplateCommand, self).execute()
        schemas = iterSchemataForType(self.portal_type)
        for schema in schemas:
            schema_name = BEHAVIOR_INTERFACE_MAPPING.get(
                schema.getName(), schema.getName())
            if schema_name not in self.additional_fields:
                continue
            behavior = schema(obj)
            for prop_name in self.additional_fields[schema_name]:
                setattr(behavior, prop_name,
                        self.additional_fields[schema_name][prop_name])

        # Set blocking of role inheritance based on the template object
        if self.block_role_inheritance is not None:
            obj.__ac_local_roles_block__ = self.block_role_inheritance

        # Copy the local roles assignations over from the template
        if self.role_assignments is not None:
            manager = RoleAssignmentManager(obj)
            # Passing an empty iterable in here creates an empty mapping
            manager.add_or_update_assignments(self.role_assignments)

        return obj
예제 #28
0
    def execute(self):
        obj = super(CreateDossierFromTemplateCommand, self).execute()
        schemas = iterSchemataForType(self.portal_type)
        for schema in schemas:
            schema_name = BEHAVIOR_INTERFACE_MAPPING.get(
                schema.getName(), schema.getName())
            if schema_name not in self.additional_fields:
                continue
            behavior = schema(obj)
            for prop_name in self.additional_fields[schema_name]:
                setattr(behavior, prop_name,
                        self.additional_fields[schema_name][prop_name])

        # Set blocking of role inheritance based on the template object
        if self.block_role_inheritance is not None:
            obj.__ac_local_roles_block__ = self.block_role_inheritance

        # Copy the local roles assignations over from the template
        if self.role_assignments is not None:
            manager = RoleAssignmentManager(obj)
            # Passing an empty iterable in here creates an empty mapping
            manager.add_or_update_assignments(self.role_assignments)

        return obj
예제 #29
0
    def __getattribute__(self, name):
        if name.startswith('_') or name.startswith(
                'portal_') or name.startswith('@@'):
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'id' and not self.sql_virtual:
            return super(SQLDexterityItem, self).__getattribute__(name)
        connection = queryUtility(ISQLConnectionsUtility,
                                  name=self.portal_type,
                                  default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI,
                               name=self.portal_type,
                               default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility,
                                      name=self.portal_type,
                                      default=None)
        if not connection:
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'UID':
            return self.portal_type + '-' + connection.sql_table + '-' + str(
                self.sql_id)
        if name == 'id' and 'id' not in connection.fieldnames.keys():
            fti = ISQLTypeSettings(
                getUtility(IDexterityFTI, name=self.portal_type))
            nameFromTitle = INameFromTitle(self, None)
            if nameFromTitle is not None and nameFromTitle.title:
                sql_folder_id = getattr(fti, 'sql_folder_id',
                                        'data-' + self.portal_type)
                title = nameFromTitle.title
                if IRelationValue.providedBy(name):
                    folder = sql_folder_id.to_object
                    if folder:
                        return INameChooser(folder).chooseName(title, self)
                return INameChooser(getSite()).chooseName(title, self)
        if name in connection.fieldnames.keys():
            sql_column = connection.fieldnames[name]
            sql_item = self.getSQLItem()
            fieldname = 'name'
            if sql_item and sql_column:
                while '.' in sql_column:
                    sql_item = getattr(sql_item,
                                       sql_column.split('.')[0], None)
                    if sql_item and (
                        (isinstance(sql_item, list) and len(sql_item) > 1)
                            or hasattr(sql_item, '_sa_instance_state')):
                        value = sql_item
                        fieldname = sql_column.split('.')[-1]
                        break
                    sql_column = '.'.join(sql_column.split('.')[1:])
                else:
                    value = getattr(sql_item, sql_column, None)
                #this is a relation
                if value and (isinstance(value, list)
                              or hasattr(value, '_sa_instance_state')):
                    sqlftis = [
                        a for a in getAllUtilitiesRegisteredFor(IDexterityFTI)
                        if
                        'collective.behavior.sql.behavior.behaviors.ISQLContent'
                        in a.behaviors and getattr(a, 'sql_table', None)
                    ]
                    if name == 'subject':
                        return tuple(
                            [getattr(a, fieldname, '') for a in value])
                    tableftis = []
                    for iface in iterSchemataForType(self.portal_type):
                        if name in iface.names():
                            field = iface[name]
                            if IList.providedBy(field):
                                return [
                                    getattr(a, fieldname, '') for a in value
                                ]  # hope it has name!
                            elif ITuple.providedBy(field):
                                return tuple(
                                    [getattr(a, fieldname, '') for a in value])
                            if IRelationChoice.providedBy(
                                    field) or IRelationList.providedBy(field):
                                if IRelationChoice.providedBy(field):
                                    allowed_types = field.source.query.get(
                                        'portal_type', [])
                                else:
                                    allowed_types = field.value_type.source.query.get(
                                        'portal_type', [])
                                tableftis = []
                                for sqlfti in sqlftis:
                                    adapted = ISQLTypeSettings(sqlfti, None)
                                    if isinstance(value, list):
                                        classname = value[0].__class__.__name__
                                    else:
                                        classname = value.__class__.__name__
                                    if adapted and getattr(
                                            adapted, 'sql_table',
                                            None) == classname:
                                        if not allowed_types or sqlfti.id in allowed_types:
                                            tableftis.append(adapted)

                                catalog = getToolByName(
                                    getSite(), 'portal_catalog')
                                relations = []
                                for tablefti in tableftis:
                                    sql_id_column = getattr(
                                        tablefti, 'sql_id_column', 'id')
                                    valueids = []
                                    if isinstance(value, list):
                                        valueids = [
                                            getattr(a, sql_id_column, None)
                                            for a in value
                                            if getattr(a, sql_id_column, None)
                                        ]
                                    else:
                                        valueids = getattr(
                                            value, sql_id_column, None)
                                    brains = catalog.searchResults(
                                        portal_type=tablefti.id,
                                        sql_id=valueids)
                                    for brain in brains:
                                        relations.append(
                                            SQLRelationValue(
                                                brain.portal_type,
                                                brain.sql_id))
                                if IRelationChoice.providedBy(
                                        field) and relations:
                                    return relations[0]
                                elif IRelationList.providedBy(
                                        field) and relations:
                                    return relations
                for iface in iterSchemataForType(self.portal_type):
                    if name == 'subject':
                        try:
                            return tuple([
                                a.decode('utf-8') for a in literal_eval(value)
                            ])
                        except:
                            return tuple([a.strip() for a in value.split(',')])
                    if name in iface.names():
                        field = iface[name]
                        if IRichText.providedBy(field):
                            return RichTextValue(value)
                        if INamedBlobImage.providedBy(field):
                            return NamedBlobImage(
                                base64.b64decode(value),
                                filename=unicode(self.portal_type + self.id +
                                                 ".jpg"))
                        if IList.providedBy(field):
                            try:
                                return [
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ]
                            except:
                                return [a.strip() for a in value.split(',')]
                        if ITuple.providedBy(field):
                            try:
                                return tuple([
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ])
                            except:
                                return tuple(
                                    [a.strip() for a in value.split(',')])

                if isinstance(value, unicode) or name == 'id':
                    try:
                        return str(value)
                    except:
                        pass
                return value
        return super(SQLDexterityItem, self).__getattribute__(name)
예제 #30
0
    def reply(self):
        if len(self.params) not in (1, 2):
            return self._error(
                400, "Bad Request",
                "Must supply either one (fieldname) or two (portal_type, fieldname) parameters"
            )

        if len(self.params) == 1:
            # Edit intent
            # - context is the object to be edited
            # - schemata need to be determined via context
            self.intent = 'edit'
            portal_type = None
            fieldname = self.params[0]
            schemata = iterSchemata(self.context)

        else:
            # Add intent
            # - context is the container where the object will be created
            # - portal_type is the type of object to be created
            # - schemata need to be determined via portal_type
            self.intent = 'add'
            portal_type = self.params[0]
            fieldname = self.params[1]
            schemata = iterSchemataForType(portal_type)
            alsoProvides(self.request, IDuringContentCreation)

        field = get_field_by_name(fieldname, schemata)
        if field is None:
            return self._error(404, "Not Found",
                               "No such field: %r" % fieldname)

        bound_field = field.bind(self.context)

        # Look for a source directly on the field first
        source = getattr(bound_field, 'source', None)

        # Handle ICollections (like Tuples, Lists and Sets). These don't have
        # sources themselves, but instead are multivalued, and their
        # items are backed by a value_type of Choice with a source
        if ICollection.providedBy(bound_field):
            source = self._get_value_type_source(bound_field)
            if not source:
                ftype = bound_field.__class__.__name__
                return self._error(
                    404, "Not Found",
                    "%r Field %r does not have a value_type of Choice with "
                    "an ISource" % (ftype, fieldname))

        if not ISource.providedBy(source):
            return self._error(404, "Not Found",
                               "Field %r does not have a source" % fieldname)

        if not IIterableSource.providedBy(source):
            return self._error(
                400, "Bad Request",
                "Source for field %r is not iterable. " % fieldname)

        serializer = getMultiAdapter((source, self.request),
                                     interface=ISerializeToJson)
        return serializer("{}/@sources/{}".format(self.context.absolute_url(),
                                                  fieldname))
    def __getattribute__(self, name):
        if name.startswith('_') or name.startswith('portal_') or name.startswith('@@') or name == 'sql_id':
            return super(SQLDexterityItem, self).__getattribute__(name)
        connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
        if name == 'view':
            #be sure session and sqlitem are up to date
            self._v_sql_item = None
            connection.session.close()
        if not connection:
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'UID' and self.sql_virtual:
            return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id)
        if name == 'id' and 'id' not in connection.fieldnames.keys():
            if not self.sql_virtual:
                return super(SQLDexterityItem, self).__getattribute__(name)
            fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type))
            nameFromTitle = INameFromTitle(self, None)
            if nameFromTitle is not None and nameFromTitle.title:
                sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type)
                title = nameFromTitle.title
                folder = None
                if IRelationValue.providedBy(sql_folder_id):
                    folder = sql_folder_id.to_object
                elif sql_folder_id and sql_folder_id.startswith('/'):
                    portal = getToolByName(getSite(), 'portal_url').getPortalObject()
                    folder = portal.restrictedTraverse(sql_folder_id)
                if folder:
                    name = INameChooser(folder).chooseName(title, self)
                    return name
#                return INameChooser(getSite()).chooseName(title, self)
#                return getUtility(IURLNormalizer).normalize(title)
                return self.sql_id
        if name in connection.fieldnames.keys():
            sql_column = connection.fieldnames[name]
            sql_item = self.getSQLItem()
            try:
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            except orm_exc.DetachedInstanceError:
                self._v_sql_item = None
                sql_item = self.getSQLItem()
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            fieldname = 'name'
            if sql_item and sql_column:
                while '.' in sql_column:
                    sql_key = sql_column.split('.')[0]
                    sql_item = getattr(sql_item, sql_key, None)
                    if isinstance(sql_item, list):
                        value = sql_item
                        fieldname = sql_column.split('.')[-1]
                        break
                    sql_column = '.'.join(sql_column.split('.')[1:])
                else:
                    if not isinstance(sql_item, list):
                        value = getattr(sql_item, sql_column, None)
                if not value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')):
                    value = ''
                elif (isinstance(value, list) or hasattr(value, '_sa_instance_state')):
                    sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)]
                    if name == 'subject':
                        return tuple([getattr(a, fieldname, '') for a in value])
                    tableftis = []
                    for iface in iterSchemataForType(self.portal_type):
                        if name in iface.names():
                            field = iface[name]
                            if IRelationChoice.providedBy(field) or IRelationList.providedBy(field):
                                if IRelationChoice.providedBy(field):
                                    allowed_types = field.source.query.get('portal_type', [])
                                else:
                                    allowed_types = field.value_type.source.query.get('portal_type', [])
                                tableftis = []
                                for sqlfti in sqlftis:
                                    adapted = ISQLTypeSettings(sqlfti, None)
                                    if isinstance(value, list):
                                        classname = value[0].__class__.__name__
                                    else:
                                        classname = value.__class__.__name__
                                    if adapted and getattr(adapted, 'sql_table', None) == classname:
                                        if not allowed_types or sqlfti.id in allowed_types:
                                            tableftis.append(adapted)
                                catalog = getToolByName(getSite(), 'portal_catalog')
                                relations = []
                                for tablefti in tableftis:
                                    sql_id_column = getattr(tablefti, 'sql_id_column', 'id')
                                    valueids = []
                                    if isinstance(value, list):
                                        valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)]
                                    else:
                                        valueids = getattr(value, sql_id_column, None)
                                    valueids = [str(a) for a in valueids]
                                    brains = catalog.unrestrictedSearchResults(portal_type=tablefti.id, sql_id=valueids)
                                    for brain in brains:
                                        relations.append(SQLRelationValue(brain.portal_type, brain.UID, self))
                                if IRelationChoice.providedBy(field) and relations:
                                    return relations[0]
                                elif IRelationList.providedBy(field) and relations:
                                    return relations
                            elif ITuple.providedBy(field):
                                return tuple([getattr(a, fieldname, '') for a in value])
                            elif IList.providedBy(field):
                                return [getattr(a, fieldname, '') for a in value]
                            elif value and isinstance(value, list):
                                value = getattr(value[0], fieldname, '')
                for iface in iterSchemataForType(self.portal_type):
                    if name == 'subject':
                        try:
                            return tuple([a.decode('utf-8') for a in literal_eval(value)])
                        except:
                            return tuple([a.strip() for a in value.split(',')])
                    if name in iface.names():
                        field = iface[name]
                        if IRichText.providedBy(field):
                            if not value:
                                return ''
                            if not '<p' in value or not '<br' in value:
                                value = '<p>'+'</p><p>'.join([a for a in value.split('\n') if a.strip()])+'</p>'
#                            try:
#                                value = str(value)
#                            except:
#                                try:
#                                    value = value.decode('utf-8')
#                                except:
#                                    try:
#                                        value = value.encode('utf-8')
#                                    except:
#                                        pass
                            return RichTextValue(unidecode(value))
                        elif INamedBlobImage.providedBy(field):
                            return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg"))
                        elif ITuple.providedBy(field):
                            if not value:
                                return tuple([])
                            try:
                                return tuple([a.decode('utf-8') for a in literal_eval(value)])
                            except:
                                return tuple([a.strip() for a in value.split(',')])
                        elif IList.providedBy(field):
                            if not value:
                                return []
                            try:
                                return [a.decode('utf-8') for a in literal_eval(value)]
                            except:
                                return [a.strip() for a in value.split(',')]
                        elif IDatetime.providedBy(field) and hasattr(value, 'day') and not hasattr(value, 'hour'):
                            value = datetime.datetime.combine(value, datetime.datetime.min.time())
                if name in ['expiration_date','effective_date', 'effective', 'expires'] and hasattr(value, 'day') and not hasattr(value, 'hour'):
                    value = datetime.datetime.combine(value, datetime.datetime.min.time())
                if isinstance(value, unicode) or name == 'id':
                    try:
                        value = str(value)
                    except:
                        pass
                return value
        return super(SQLDexterityItem, self).__getattribute__(name)
예제 #32
0
    def reply(self):
        if len(self.params) not in (1, 2):
            return self._error(
                400, "Bad Request",
                "Must supply either one (fieldname) or two (portal_type, fieldname) parameters"
            )

        if len(self.params) == 1:
            # Edit intent
            # - context is the object to be edited
            # - schemata need to be determined via context
            self.intent = 'edit'
            portal_type = None
            fieldname = self.params[0]
            schemata = iterSchemata(self.context)

        else:
            # Add intent
            # - context is the container where the object will be created
            # - portal_type is the type of object to be created
            # - schemata need to be determined via portal_type
            self.intent = 'add'
            portal_type = self.params[0]
            fieldname = self.params[1]
            schemata = iterSchemataForType(portal_type)
            alsoProvides(self.request, IDuringContentCreation)

        field = get_field_by_name(fieldname, schemata)
        if field is None:
            return self._error(
                404, "Not Found",
                "No such field: %r" % fieldname
            )
        bound_field = field.bind(self.context)

        # Look for a source directly on the field first
        source = getattr(bound_field, 'source', None)

        # Handle ICollections (like Tuples, Lists and Sets). These don't have
        # sources themselves, but instead are multivalued, and their
        # items are backed by a value_type of Choice with a source
        if ICollection.providedBy(bound_field):
            source = self._get_value_type_source(bound_field)
            if not source:
                ftype = bound_field.__class__.__name__
                return self._error(
                    404, "Not Found",
                    "%r Field %r does not have a value_type of Choice with "
                    "an IQuerySource" % (ftype, fieldname))

        if not IQuerySource.providedBy(source):
            return self._error(
                404, "Not Found",
                "Field %r does not have an IQuerySource" % fieldname
            )

        if 'query' not in self.request.form:
            return self._error(
                400, "Bad Request",
                u'Enumerating querysources is not supported. Please search '
                u'the source using the ?query= QS parameter'
            )

        query = self.request.form['query']

        result = source.search(query)

        terms = []
        for term in result:
            terms.append(term)

        batch = HypermediaBatch(self.request, terms)

        serialized_terms = []
        for term in batch:
            serializer = getMultiAdapter(
                (term, self.request), interface=ISerializeToJson
            )
            serialized_terms.append(serializer())

        result = {
            "@id": batch.canonical_url,
            "items": serialized_terms,
            "items_total": batch.items_total,
        }
        links = batch.links
        if links:
            result["batching"] = links
        return result
예제 #33
0
def link_items(  # noqa
    context,
    source_obj,
    target_obj,
    relationship=None,
    fieldname='relatedItems',
):
    """Add a relation between two content objects.

    This uses the field 'relatedItems' and works for Archetypes and Dexterity.
    By passing a fieldname and a relationship it can be used to create
    arbitrary relations.

    Note: for the relatedItems field, Products.ATContentTypes uses 'relatesTo'
    and plone.app.contenttypes uses 'relatedItems'.
    We switch between these two, based on the source object.
    """
    # relations from AT to DX and from DX to AT are only possible through
    # the referenceable-behavior:
    # plone.app.referenceablebehavior.referenceable.IReferenceable
    drop_msg = """Dropping reference from %s to %s since
    plone.app.referenceablebehavior is not enabled!"""

    if source_obj is target_obj:
        # Thou shalt not relate to yourself.
        return

    if IDexterityContent.providedBy(source_obj):
        source_type = 'DX'
    else:
        source_type = 'AT'

    if IDexterityContent.providedBy(target_obj):
        target_type = 'DX'
    else:
        target_type = 'AT'

    if relationship == referencedRelationship:
        # 'isReferencing' is the relationship for linkintegrity-relations.
        # Linkintegrity-relations should automatically be (re)created by
        # plone.app.linkintegrity.handlers.modifiedDexterity or
        # plone.app.linkintegrity.handlers.modifiedArchetype
        # when a ObjectModifiedEvent is thrown.
        # These relations are only created if the source has a richtext-field
        # with a link to the target and should not be created manually.
        if source_type == 'AT':
            modifiedArchetype(source_obj, None)
        if source_type == 'DX':
            modifiedDexterity(source_obj, None)
        return

    if source_type == 'AT':
        if relationship == 'relatedItems':
            relationship = 'relatesTo'
        # If there is any Archetypes-content there is also the
        # reference_catalog. For a site without AT content this
        # might not be there at all.
        reference_catalog = getToolByName(context, REFERENCE_CATALOG)
        uid_catalog = getToolByName(context, 'uid_catalog')
        if target_type == 'DX' and not is_referenceable(target_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return

        # Make sure both objects are properly indexed and referenceable
        # Some objects that werde just created (migrated) are not yet
        # indexed properly.
        source_uid = IUUID(source_obj)
        target_uid = IUUID(target_obj)
        _catalog = uid_catalog._catalog

        if not _catalog.indexes['UID']._index.get(source_uid):
            uid_catalog.catalog_object(source_obj, source_uid)
            modified(source_obj)

        if not _catalog.indexes['UID']._index.get(target_uid):
            uid_catalog.catalog_object(target_obj, target_uid)
            modified(target_obj)

        field = source_obj.getField(fieldname)
        if field is None:
            # we can't migrate if it doesn't actually have the field
            return
        accessor = field.getAccessor(source_obj)
        existing_at_relations = accessor()

        if not isinstance(existing_at_relations, list):
            existing_at_relations = [i for i in existing_at_relations]
        if not existing_at_relations:
            existing_at_relations = []
        if target_obj in existing_at_relations:
            # don't do anything
            return

        target_uid = IUUID(target_obj)
        targetUIDs = [
            ref.targetUID for ref in reference_catalog.getReferences(
                source_obj, relationship)
        ]
        if target_uid in targetUIDs:
            # Drop relation since the old ones are most likely broken.
            reference_catalog.deleteReference(source_obj, target_uid,
                                              relationship)

        existing_at_relations.append(target_obj)
        mutator = field.getMutator(source_obj)
        mutator(existing_at_relations)
        modified(source_obj)
        return

    if source_type is 'DX':
        if relationship == 'relatesTo':
            relationship = 'relatedItems'
        if target_type is 'AT' and not is_referenceable(source_obj):
            logger.info(drop_msg %
                        (source_obj.absolute_url(), target_obj.absolute_url()))
            return
        # handle dx-relation
        if relationship == 'translationOf':
            # LinguaPlone relations make no sense for Dexterity
            return

        intids = getUtility(IIntIds)
        to_id = intids.getId(target_obj)
        # Before we set the fieldname attribute on the source object,
        # we need to know if this should be a list or a single item.
        # Might be None at the moment.
        # We check the field definition.
        fti = getUtility(IDexterityFTI, name=source_obj.portal_type)
        field = None
        for schema in iterSchemataForType(fti):
            field = schema.get(fieldname, None)
            if field is not None:
                break
        if isinstance(field, RelationList):
            existing_relations = getattr(source_obj, fieldname, [])
            if existing_relations is None:
                existing_relations = []
            else:
                # purge broken relations
                existing_relations = [
                    i for i in existing_relations if i.to_id is not None
                ]
            if to_id not in [i.to_id for i in existing_relations]:
                existing_relations.append(RelationValue(to_id))
                setattr(source_obj, fieldname, existing_relations)
                modified(source_obj)
                return
            return
        elif isinstance(field, (Relation, RelationChoice)):
            setattr(source_obj, fieldname, RelationValue(to_id))
            modified(source_obj)
            return

        # We should never end up here!
        logger.warning(
            'Ignoring unknown fieldname %s when restoring relation %s from %s to %s',
            fieldname, relationship, source_obj.absolute_url(),
            target_obj.absolute_url())
 def __getattribute__(self, name):
     if name.startswith('_') or name.startswith('portal_') or name.startswith('@@'):
         return super(SQLDexterityItem, self).__getattribute__(name)
     if name == 'id' and not self.sql_virtual:
         return super(SQLDexterityItem, self).__getattribute__(name)
     connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
     if connection == None and self.portal_type:
         fti = queryUtility(IDexterityFTI, name=self.portal_type, default=None)
         if not fti:
             return None
         updateConnectionsForFti(fti)
         connection = queryUtility(ISQLConnectionsUtility, name=self.portal_type, default=None)
     if not connection:
         return super(SQLDexterityItem, self).__getattribute__(name)
     if name == 'UID':
         return self.portal_type+'-'+connection.sql_table+'-'+str(self.sql_id)
     if name == 'id' and 'id' not in connection.fieldnames.keys():
         fti = ISQLTypeSettings(getUtility(IDexterityFTI, name=self.portal_type))
         nameFromTitle = INameFromTitle(self, None)
         if nameFromTitle is not None and nameFromTitle.title:
             sql_folder_id = getattr(fti, 'sql_folder_id', 'data-'+self.portal_type)
             title = nameFromTitle.title
             if IRelationValue.providedBy(name):
                 folder = sql_folder_id.to_object
                 if folder:
                     return INameChooser(folder).chooseName(title, self)
             return INameChooser(getSite()).chooseName(title, self)
     if name in connection.fieldnames.keys():
         sql_column = connection.fieldnames[name]
         sql_item = self.getSQLItem()
         fieldname = 'name'
         if sql_item and sql_column:
             while '.' in sql_column:
                 sql_item = getattr(sql_item, sql_column.split('.')[0], None)
                 if sql_item and ((isinstance(sql_item, list) and len(sql_item)>1) or hasattr(sql_item, '_sa_instance_state')):
                     value = sql_item
                     fieldname = sql_column.split('.')[-1]
                     break
                 sql_column = '.'.join(sql_column.split('.')[1:])
             else:
                 value = getattr(sql_item, sql_column, None)
             #this is a relation
             if value and (isinstance(value, list) or hasattr(value, '_sa_instance_state')):
                 sqlftis = [a for a in getAllUtilitiesRegisteredFor(IDexterityFTI) if 'collective.behavior.sql.behavior.behaviors.ISQLContent' in a.behaviors and getattr(a, 'sql_table', None)]
                 if name == 'subject':
                     return tuple([getattr(a, fieldname, '') for a in value])
                 tableftis = []
                 for iface in iterSchemataForType(self.portal_type):
                     if name in iface.names():
                         field = iface[name]
                         if IList.providedBy(field):
                             return [getattr(a, fieldname, '') for a in value] # hope it has name!
                         elif ITuple.providedBy(field):
                             return tuple([getattr(a, fieldname, '') for a in value])
                         if IRelationChoice.providedBy(field) or IRelationList.providedBy(field):
                             if IRelationChoice.providedBy(field):
                                 allowed_types = field.source.query.get('portal_type', [])
                             else:
                                 allowed_types = field.value_type.source.query.get('portal_type', [])
                             tableftis = []
                             for sqlfti in sqlftis:
                                 adapted = ISQLTypeSettings(sqlfti, None)
                                 if isinstance(value, list):
                                     classname = value[0].__class__.__name__
                                 else:
                                     classname = value.__class__.__name__
                                 if adapted and getattr(adapted, 'sql_table', None) == classname:
                                     if not allowed_types or sqlfti.id in allowed_types:
                                         tableftis.append(adapted)
                     
                             catalog = getToolByName(getSite(), 'portal_catalog')
                             relations = []
                             for tablefti in tableftis:
                                 sql_id_column = getattr(tablefti, 'sql_id_column', 'id')
                                 valueids = []
                                 if isinstance(value, list):
                                     valueids = [getattr(a, sql_id_column, None) for a in value if getattr(a, sql_id_column, None)]
                                 else:
                                     valueids = getattr(value, sql_id_column, None)
                                 brains = catalog.searchResults(portal_type=tablefti.id, sql_id=valueids)
                                 for brain in brains:
                                     relations.append(SQLRelationValue(brain.portal_type, brain.sql_id))
                             if IRelationChoice.providedBy(field) and relations:
                                 return relations[0]
                             elif IRelationList.providedBy(field) and relations:
                                 return relations
             for iface in iterSchemataForType(self.portal_type):
                 if name == 'subject':
                     try:
                         return tuple([a.decode('utf-8') for a in literal_eval(value)])
                     except:
                         return tuple([a.strip() for a in value.split(',')])
                 if name in iface.names():
                     field = iface[name]
                     if IRichText.providedBy(field):
                         return RichTextValue(value)
                     if INamedBlobImage.providedBy(field):
                         return NamedBlobImage(base64.b64decode(value), filename=unicode(self.portal_type+self.id+".jpg"))
                     if IList.providedBy(field):
                         try:
                             return [a.decode('utf-8') for a in literal_eval(value)]
                         except:
                             return [a.strip() for a in value.split(',')]
                     if ITuple.providedBy(field):
                         try:
                             return tuple([a.decode('utf-8') for a in literal_eval(value)])
                         except:
                             return tuple([a.strip() for a in value.split(',')])
                         
             if isinstance(value, unicode) or name == 'id':
                 try:
                     return str(value)
                 except:
                     pass
             return value
     return super(SQLDexterityItem, self).__getattribute__(name)
예제 #35
0
    def create_destination_document(self):
        # get all the metadata that will be set on the created file.
        # We blacklist some fields that should not be copied
        fields_to_skip = set((
            "file",
            "archival_file",
            "archival_file_state",
            "thumbnail",
            "preview",
            "digitally_available",
            "changeNote",
            "changed",
            "relatedItems",
        ))
        metadata = {}
        for schema in iterSchemataForType(self.context.portal_type):
            for name, schema_field in getFieldsInOrder(schema):
                if name in fields_to_skip:
                    continue
                field_instance = schema_field.bind(self.context)
                metadata[name] = field_instance.get(self.context)

        command = CreateDocumentCommand(self.destination, None, None,
                                        **metadata)
        destination_document = command.execute()

        # We make it in shadow state until its file is set by the callback view
        destination_document.as_shadow_document()
        # Add marker interface. This should be useful in the future for
        # cleanup jobs, retries if the PDF was not delivered and so on.
        alsoProvides(destination_document, IDocumentSavedAsPDFMarker)
        # Add annotations needed for the SavePDFDocumentUnder view.
        annotations = IAnnotations(destination_document)
        annotations[PDF_SAVE_SOURCE_UUID_KEY] = IUUID(self.context)
        annotations[PDF_SAVE_SOURCE_VERSION_KEY] = self.version_id

        # The missing_value attribute of a z3c-form field is used
        # as soon as an object has no default_value i.e. after creating
        # an object trough the command-line.
        #
        # Because the relatedItems field needs a list as a missing_value,
        # we will fall into the "mutable keyword argument"-python gotcha.
        # The relatedItems will be shared between the object-instances.
        #
        # Unfortunately the z3c-form field does not provide a
        # missing_value-factory (like the defaultFactory) which would be
        # necessary to fix this issue properly.
        #
        # As a workaround we make sure that the new document's relatedItems
        # is different object from the source document's.
        IRelatedDocuments(destination_document).relatedItems = list(
            IRelatedDocuments(destination_document).relatedItems)

        IRelatedDocuments(destination_document).relatedItems.append(
            RelationValue(getUtility(IIntIds).getId(self.context)))

        msg = _(
            u'Document ${document} was successfully created in ${destination}',
            mapping={
                "document": destination_document.title,
                "destination": self.destination.title
            })
        api.portal.show_message(msg, self.request, type='info')

        return destination_document
예제 #36
0
    def createObjectOfType(self, root, pt):

        # Set return list
        rv = []

        # Get the it of the portal_type
        portal_type = pt.getId()

        # Check if type is allowed
        allowed_content_types = [x.getId() for x in root.getAllowedTypes()]

        # Override for root folder (only structures)
        if root.portal_type == 'Folder':
            allowed_content_types = [
                'atlas_category_level_1', 'atlas_county', 'directory'
            ]

        if portal_type in allowed_content_types:

            kwargs = {}

            for s in iterSchemataForType(portal_type):

                for (name, field) in getAllSchemaFieldsAndDescriptions(s):
                    if not isinstance(field, Method):
                        kwargs[name] = self.getDefaultForFieldType(field)

            # Set the id
            kwargs['id'] = 'X_%s_X' % portal_type

            # Debug output
            if self.debug:
                msg = "Creating %s in %s" % (portal_type, root.portal_type)
                LOG('API Sample Generator', INFO, msg)

            # Create a dummy object with default values
            try:
                o = createContentInContainer(root, portal_type, **kwargs)
            except WorkflowException:
                # For some reason, we're getting a workflow exception on article videos?
                return rv

            # Append to return list
            rv.append(o)

            # Get the allowed object types
            _allowed_content_types = pt.allowed_content_types

            # Override for category level 2 (no products!)
            if portal_type == 'atlas_category_level_2':
                _allowed_content_types = ['atlas_category_level_3']

            # Create sub-objects
            for _pt_id in _allowed_content_types:

                # Prevent recursion... Don't create a type inside itself.
                if _pt_id == portal_type:
                    continue
                try:
                    _o = self.createObjectOfType(o, self.portal_types[_pt_id])
                    rv.extend(_o)
                except RuntimeError:
                    # Skip if something bombs out from recursive calls
                    pass
                except TypeError:
                    # Skip if something bombs out with a TypeError
                    pass

            return rv
예제 #37
0
    def __getattribute__(self, name):
        if name.startswith('_') or name.startswith(
                'portal_') or name.startswith('@@') or name == 'sql_id':
            return super(SQLDexterityItem, self).__getattribute__(name)
        connection = queryUtility(ISQLConnectionsUtility,
                                  name=self.portal_type,
                                  default=None)
        if connection == None and self.portal_type:
            fti = queryUtility(IDexterityFTI,
                               name=self.portal_type,
                               default=None)
            if not fti:
                return None
            updateConnectionsForFti(fti)
            connection = queryUtility(ISQLConnectionsUtility,
                                      name=self.portal_type,
                                      default=None)
        if name == 'view':
            #be sure session and sqlitem are up to date
            self._v_sql_item = None
            connection.session.close()
        if not connection:
            return super(SQLDexterityItem, self).__getattribute__(name)
        if name == 'UID' and self.sql_virtual:
            return self.portal_type + '-' + connection.sql_table + '-' + str(
                self.sql_id)
        if name == 'id' and 'id' not in connection.fieldnames.keys():
            if not self.sql_virtual:
                return super(SQLDexterityItem, self).__getattribute__(name)
            fti = ISQLTypeSettings(
                getUtility(IDexterityFTI, name=self.portal_type))
            nameFromTitle = INameFromTitle(self, None)
            if nameFromTitle is not None and nameFromTitle.title:
                sql_folder_id = getattr(fti, 'sql_folder_id',
                                        'data-' + self.portal_type)
                title = nameFromTitle.title
                folder = None
                if IRelationValue.providedBy(sql_folder_id):
                    folder = sql_folder_id.to_object
                elif sql_folder_id and sql_folder_id.startswith('/'):
                    portal = getToolByName(getSite(),
                                           'portal_url').getPortalObject()
                    folder = portal.restrictedTraverse(sql_folder_id)
                if folder:
                    name = INameChooser(folder).chooseName(title, self)
                    return name
#                return INameChooser(getSite()).chooseName(title, self)
#                return getUtility(IURLNormalizer).normalize(title)
                return self.sql_id
        if name in connection.fieldnames.keys():
            sql_column = connection.fieldnames[name]
            sql_item = self.getSQLItem()
            try:
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            except orm_exc.DetachedInstanceError:
                self._v_sql_item = None
                sql_item = self.getSQLItem()
                sql_id = getattr(sql_item, connection.sql_id_column, None)
            fieldname = 'name'
            if sql_item and sql_column:
                while '.' in sql_column:
                    sql_key = sql_column.split('.')[0]
                    sql_item = getattr(sql_item, sql_key, None)
                    if isinstance(sql_item, list):
                        value = sql_item
                        fieldname = sql_column.split('.')[-1]
                        break
                    sql_column = '.'.join(sql_column.split('.')[1:])
                else:
                    if not isinstance(sql_item, list):
                        value = getattr(sql_item, sql_column, None)
                if not value and (isinstance(value, list)
                                  or hasattr(value, '_sa_instance_state')):
                    value = ''
                elif (isinstance(value, list)
                      or hasattr(value, '_sa_instance_state')):
                    sqlftis = [
                        a for a in getAllUtilitiesRegisteredFor(IDexterityFTI)
                        if
                        'collective.behavior.sql.behavior.behaviors.ISQLContent'
                        in a.behaviors and getattr(a, 'sql_table', None)
                    ]
                    if name == 'subject':
                        return tuple(
                            [getattr(a, fieldname, '') for a in value])
                    tableftis = []
                    for iface in iterSchemataForType(self.portal_type):
                        if name in iface.names():
                            field = iface[name]
                            if IRelationChoice.providedBy(
                                    field) or IRelationList.providedBy(field):
                                if IRelationChoice.providedBy(field):
                                    allowed_types = field.source.query.get(
                                        'portal_type', [])
                                else:
                                    allowed_types = field.value_type.source.query.get(
                                        'portal_type', [])
                                tableftis = []
                                for sqlfti in sqlftis:
                                    adapted = ISQLTypeSettings(sqlfti, None)
                                    if isinstance(value, list):
                                        classname = value[0].__class__.__name__
                                    else:
                                        classname = value.__class__.__name__
                                    if adapted and getattr(
                                            adapted, 'sql_table',
                                            None) == classname:
                                        if not allowed_types or sqlfti.id in allowed_types:
                                            tableftis.append(adapted)
                                catalog = getToolByName(
                                    getSite(), 'portal_catalog')
                                relations = []
                                for tablefti in tableftis:
                                    sql_id_column = getattr(
                                        tablefti, 'sql_id_column', 'id')
                                    valueids = []
                                    if isinstance(value, list):
                                        valueids = [
                                            getattr(a, sql_id_column, None)
                                            for a in value
                                            if getattr(a, sql_id_column, None)
                                        ]
                                    else:
                                        valueids = getattr(
                                            value, sql_id_column, None)
                                    valueids = [str(a) for a in valueids]
                                    brains = catalog.unrestrictedSearchResults(
                                        portal_type=tablefti.id,
                                        sql_id=valueids)
                                    for brain in brains:
                                        relations.append(
                                            SQLRelationValue(
                                                brain.portal_type, brain.UID,
                                                self))
                                if IRelationChoice.providedBy(
                                        field) and relations:
                                    return relations[0]
                                elif IRelationList.providedBy(
                                        field) and relations:
                                    return relations
                            elif ITuple.providedBy(field):
                                return tuple(
                                    [getattr(a, fieldname, '') for a in value])
                            elif IList.providedBy(field):
                                return [
                                    getattr(a, fieldname, '') for a in value
                                ]
                            elif value and isinstance(value, list):
                                value = getattr(value[0], fieldname, '')
                for iface in iterSchemataForType(self.portal_type):
                    if name == 'subject':
                        try:
                            return tuple([
                                a.decode('utf-8') for a in literal_eval(value)
                            ])
                        except:
                            return tuple([a.strip() for a in value.split(',')])
                    if name in iface.names():
                        field = iface[name]
                        if IRichText.providedBy(field):
                            if not value:
                                return ''
                            if not '<p' in value or not '<br' in value:
                                value = '<p>' + '</p><p>'.join([
                                    a for a in value.split('\n') if a.strip()
                                ]) + '</p>'


#                            try:
#                                value = str(value)
#                            except:
#                                try:
#                                    value = value.decode('utf-8')
#                                except:
#                                    try:
#                                        value = value.encode('utf-8')
#                                    except:
#                                        pass
                            return RichTextValue(unidecode(value))
                        elif INamedBlobImage.providedBy(field):
                            return NamedBlobImage(
                                base64.b64decode(value),
                                filename=unicode(self.portal_type + self.id +
                                                 ".jpg"))
                        elif ITuple.providedBy(field):
                            if not value:
                                return tuple([])
                            try:
                                return tuple([
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ])
                            except:
                                return tuple(
                                    [a.strip() for a in value.split(',')])
                        elif IList.providedBy(field):
                            if not value:
                                return []
                            try:
                                return [
                                    a.decode('utf-8')
                                    for a in literal_eval(value)
                                ]
                            except:
                                return [a.strip() for a in value.split(',')]
                        elif IDatetime.providedBy(field) and hasattr(
                                value, 'day') and not hasattr(value, 'hour'):
                            value = datetime.datetime.combine(
                                value, datetime.datetime.min.time())
                if name in [
                        'expiration_date', 'effective_date', 'effective',
                        'expires'
                ] and hasattr(value, 'day') and not hasattr(value, 'hour'):
                    value = datetime.datetime.combine(
                        value, datetime.datetime.min.time())
                if isinstance(value, unicode) or name == 'id':
                    try:
                        value = str(value)
                    except:
                        pass
                return value
        return super(SQLDexterityItem, self).__getattribute__(name)