Пример #1
0
    def upload(self):

        # Move uploaded files to their permanent location
        try:
            for member in self.upload_members:

                if schema.get(self.data, member) is None:
                    continue

                value = schema.get(self.instance, member)

                if isinstance(member, schema.Collection):
                    files = value
                else:
                    files = (value, )

                for i, file in enumerate(files):
                    temp_file = self.temp_paths[file]

                    if os.path.exists(temp_file):

                        dest = file.file_path

                        if os.path.exists(dest):
                            os.remove(dest)

                        move(temp_file, dest)

        # Remove the temporary folder
        finally:
            rmtree(self.temp_upload_folder)
Пример #2
0
    def adapt_object(self, context):

        context.consume("upload")
        upload = context.get("upload", None)

        if upload:
            context.set("file_name", schema.get(upload, "file_name"))
            context.set("mime_type", schema.get(upload, "mime_type"))
            context.set("file_size", schema.get(upload, "file_size"))
            context.set("file_hash", schema.get(upload, "file_hash"))
Пример #3
0
    def test_reference_relation_constraints(self):

        from cocktail.schema import Reference, Integer, exceptions, get

        foreign_field = Integer("foo")

        ref = Reference(relation_constraints=[
            foreign_field.not_equal(None),
            foreign_field.greater(3),
            foreign_field.lower(8),
            lambda owner, related: get(related, "foo", None) is None or get(
                related, "foo", None) % 5 != 0
        ])

        self._test_validation(ref, [None, {"foo": 4}, {"foo": 6}, {"foo": 7}])

        self._test_validation(
            ref,
            None,
            [{}, {
                "foo": None
            }],
            exceptions.RelationConstraintError,
            error_count=2  # Note that x > None is always True
        )

        self._test_validation(ref, None, [{
            "foo": -6
        }, {
            "foo": 1
        }, {
            "foo": 3
        }], exceptions.RelationConstraintError,
                              {"constraint": ref.relation_constraints[1]})

        self._test_validation(ref, None, [{
            "foo": 8
        }, {
            "foo": 12
        }, {
            "foo": 134
        }], exceptions.RelationConstraintError,
                              {"constraint": ref.relation_constraints[2]})

        self._test_validation(ref, None, [{
            "foo": 5
        }], exceptions.RelationConstraintError,
                              {"constraint": ref.relation_constraints[3]})
Пример #4
0
 def get_item_id(self, item):
     pm = self.schema.primary_member
     if pm is None:
         raise ValueError(
             "Selectable tables must have a schema with a primary member "
             "defined or override their get_item_id() method")
     return get(item, pm)
Пример #5
0
    def handle_processed(cls, event):

        controller = event.source
        rel = cherrypy.request.params.get("relation-select")

        # Open the item selector
        if rel:
            pos = rel.find("-")
            root_content_type_name = rel[:pos]
            selection_parameter = rel[pos + 1:]
            key = selection_parameter[len(controller.form_prefix):]

            # Push the relation as a new stack node
            current_node = controller.stack_node
            rel_node = RelationNode()
            rel_node.member = current_node.content_type[key]
            controller.edit_stack.push(rel_node)

            value = schema.get(current_node.form_data, key)

            raise cherrypy.HTTPRedirect(
                controller.context["cms"].contextual_uri("content") + "?" +
                view_state(
                    selection=value.id if value is not None else None,
                    edit_stack=controller.edit_stack.to_param(),
                    client_side_scripting=controller.client_side_scripting) +
                "#default")

        # Open an editor for a new nested item
        new = cherrypy.request.params.get("relation-new")

        if new:
            pos = new.find("-")
            member_name = new[:pos]
            content_type_name = new[pos + 1:]

            # Push the relation as a new stack node
            current_node = controller.stack_node
            rel_node = RelationNode()
            rel_node.member = current_node.content_type[member_name]
            controller.edit_stack.push(rel_node)

            raise cherrypy.HTTPRedirect(
                controller.context["cms"].contextual_uri(
                    "content",
                    "new",
                    item_type=content_type_name,
                    edit_stack=controller.edit_stack.to_param()))

        # Open an editor for an existing nested item
        edit = cherrypy.request.params.get("relation-edit")

        if edit:
            raise cherrypy.HTTPRedirect(
                controller.edit_uri(controller.stack_node.form_data[edit]))
Пример #6
0
    def iter_changes(self, source=None):

        for member, language in EditNode.iter_changes(self, source):

            # Ignore differences on the upload field if no file has been
            # uploaded
            if member.name == "upload":
                upload = schema.get(self.form_data, "upload", None)
                if (upload is None
                        or upload.get("file_hash") == self.item.file_hash):
                    continue

            yield (member, language)
Пример #7
0
    def _read_schema(self, member, target, languages, path):

        if target is None:
            if isinstance(member, type):
                target = member()
            else:
                target = {}

        path.append(member)

        try:
            for child_member in member.members().values():

                if child_member.editable != schema.EDITABLE:
                    continue

                if self._is_schema(child_member):
                    nested_target = schema.get(target, child_member, None)
                    if nested_target is None:
                        nested_target = self.create_nested_target(
                            member, child_member, target)
                        schema.set(target, child_member.name, nested_target)
                else:
                    nested_target = target

                value = self.read(
                    child_member, nested_target,
                    languages if child_member.translated else None, path)

            # Validate child members *after* all members have read their values
            # (this allows conditional validations based on other members in
            # the schema)
            if self.errors != "ignore":
                invalid_members = set()

                for error in member.get_errors(target):
                    error_member = error.member
                    if (error_member not in invalid_members
                            and error_member.editable == schema.EDITABLE):
                        invalid_members.add(error_member)
                        error_target = error.context.get_object()
                        fixed_value = self._fix_value(error_target,
                                                      error_member,
                                                      error.value, error)
                        if error_member.name:
                            schema.set(error_target, error_member.name,
                                       fixed_value)
        finally:
            path.pop()

        return target
Пример #8
0
    def unrelate(self, member, item):
        """Breaks the relation between the edited item and one of its related
        items.
        
        @param member: The member describing the relation between the two
            items. It should be the end nearer to the edited item.
        @type member: L{RelationMember<cocktail.schema.RelationMember>}

        @param item: The item to unrelate.
        @type item: L{Item<woost.models.item.Item>}
        """
        if isinstance(member, schema.Collection):
            collection = schema.get(self.form_data, member)
            schema.remove(collection, item)
        else:
            schema.set(self.form_data, member, None)
Пример #9
0
    def relate(self, member, item):
        """Adds a relation between the edited item and another item.
        
        @param member: The member describing the relation between the two
            items. It should be the end nearer to the edited item.
        @type member: L{RelationMember<cocktail.schema.RelationMember>}

        @param item: The item to relate.
        @type item: L{Item<woost.models.item.Item>}
        """
        if isinstance(member, schema.Collection):

            collection = schema.get(self.form_data, member)

            # Editing collections with duplicate entries is not allowed
            if item in collection:
                raise ValueError(
                    "Collections with duplicate entries are not allowed")

            schema.add(collection, item)
        else:
            schema.set(self.form_data, member, item)
Пример #10
0
    def _synchronize(self):
        cmp = self.comparision
        get_param = cherrypy.request.params.get
        file_downloads = set()
        selection = self.sync_selection

        with changeset_context(get_current_user()):

            for obj in cmp["incomming"]:
                if obj.global_id in selection:
                    obj.insert()

                    if isinstance(obj, File):
                        file_downloads.add(obj)

            for global_id, change in cmp["modified"].iteritems():
                if global_id in selection:
                    local = change["local"]
                    remote = change["remote"]

                    for member, lang in change["diff"]:
                        value = schema.get(remote, member, language=lang)
                        local.set(member, value, lang)

                        if member in (File.file_hash, File.file_size):
                            file_downloads.add(local)

        # Download files from the remote copy
        for file in file_downloads:
            self.synchronization.download_file(file)

        # Find importable content again
        self.comparision = self.synchronization.compare_content()

        notify_user(
            translations(
                "woost.controllers.InstallationSyncController.success"),
            "success")
Пример #11
0
 def collection(self):
     return schema.get(self.edit_node.form_data, self.member)
Пример #12
0
    def _handle_form_data(self):

        stack_node = self.stack_node
        form_data = stack_node.form_data
        translations = stack_node.translations

        section = self.params.read(schema.String("section", default="fields"))

        added_translation = self.params.read(
            schema.String("add_translation",
                          enumeration=self.available_languages))

        deleted_translation = self.params.read(
            schema.String("delete_translation", enumeration=translations))

        # Remove translations
        if deleted_translation:
            translations.remove(deleted_translation)
            for key, member in self.fields_schema.members().iteritems():
                if member.translated:
                    values = form_data.get(key)
                    if values:
                        values.pop(deleted_translation, None)

        get_method = cherrypy.request.method.upper() == "GET"

        # Load form data from the request
        get_parameter(self.fields_schema,
                      target=form_data,
                      languages=translations,
                      prefix=self.form_prefix,
                      errors="ignore",
                      implicit_booleans=not get_method,
                      undefined="skip" if get_method else "set_none")

        # Add translations
        if added_translation and added_translation not in translations:
            translations.append(added_translation)

            # Try to copy an existing fallback translation
            for fallback_language in iter_language_chain(added_translation,
                                                         include_self=False):
                if fallback_language in translations:
                    for key, member in self.fields_schema.members().iteritems(
                    ):
                        if member.translated:
                            value = schema.get(form_data,
                                               key,
                                               language=fallback_language)
                            schema.set(form_data,
                                       key,
                                       value,
                                       language=added_translation)
                    break
            # If there's no fallback translation to use, create a new
            # translation from scratch
            else:
                translation_data = {}
                stack_node.content_type.translation.init_instance(
                    translation_data)
                for key, value in translation_data.iteritems():
                    schema.set(form_data,
                               key,
                               value,
                               language=added_translation)

        # Drop references
        unlink = cherrypy.request.params.get("relation-unlink")

        if unlink:
            form_data[unlink] = None

        return form_data
Пример #13
0
    def user_collection(self):

        user_collection = BackOfficeUserCollection(self.root_content_type)

        if self.root_content_type:
            user = get_current_user()
            for role in user.roles:
                if role.default_content_type:
                    if issubclass(role.default_content_type,
                                  self.root_content_type):
                        user_collection.default_type = role.default_content_type
                    break

        if self.edit_stack and isinstance(self.stack_node, RelationNode):
            user_collection.default_type = \
                self.stack_node.member.selector_default_type

        user_collection.available_languages = self.available_languages
        user_collection.selection_mode = self.selection_mode
        user_collection.default_order = \
            [NegativeExpression(Item.last_update_time)]

        # Parameter persistence
        prefix = self.persistence_prefix
        duration = self.persistence_duration

        user_collection.set_parameter_source(
            "type", SessionParameterSource(key_prefix=prefix))

        type_prefix = user_collection.type.full_name
        if prefix:
            type_prefix += "-" + prefix

        user_collection.persistence_prefix = type_prefix
        user_collection.persistent_source = psource = SessionParameterSource(
            key_prefix=type_prefix)

        user_collection.set_parameter_source("content_view", psource)
        user_collection.set_parameter_source("members", psource)
        user_collection.set_parameter_source("order", psource)
        user_collection.set_parameter_source("grouping", psource)
        user_collection.set_parameter_source("filter", psource)
        user_collection.set_parameter_source("page", psource)
        user_collection.set_parameter_source("page_size", psource)
        user_collection.set_parameter_source("expanded", psource)
        user_collection.set_parameter_source(
            "language",
            CookieParameterSource(cookie_naming="visible_languages",
                                  cookie_duration=duration))

        # Exclude instances of invisible types
        def hide_invisible_types(content_type):
            if not content_type.visible:
                exclusion = ExclusionExpression(Self, content_type.keys)
                exclusion.by_key = True
                user_collection.add_base_filter(exclusion)
            else:
                for descendant_type \
                in content_type.derived_schemas(recursive = False):
                    hide_invisible_types(descendant_type)

        hide_invisible_types(user_collection.type)

        node = self.stack_node

        if node and isinstance(node, RelationNode):

            relation = node.member
            is_collection = isinstance(relation, schema.Collection)
            edit_node = self.edit_stack[-2]
            excluded_items = set()

            # Exclude items that are already contained on an edited collection
            if is_collection:
                excluded_items.update(schema.get(edit_node.form_data,
                                                 relation))

            if excluded_items:
                user_collection.add_base_filter(
                    ExclusionExpression(Self, excluded_items))

            # Add relation constraints
            if relation.enumeration:
                enumeration = relation.resolve_constraint(
                    relation.enumeration,
                    ValidationContext(edit_node.item.__class__,
                                      edit_node.item,
                                      persistent_object=edit_node.item))
                user_collection.add_base_filter(
                    InclusionExpression(Self, enumeration))

            for constraint in relation.get_constraint_filters(edit_node.item):
                user_collection.add_base_filter(constraint)

        # Filter unauthorized items
        user_collection.add_base_filter(
            PermissionExpression(get_current_user(), ReadPermission))

        return user_collection