Example #1
0
class IContainerViews(Interface):
    """Define several container views for an `IContainer` implementation."""

    for_ = GlobalObject(title=u"The declaration this containerViews are for.",
                        description=u"""
        The containerViews will be available for all objects that
        provide this declaration.
        """,
                        required=True)

    contents = Permission(title=u"The permission needed for content page.",
                          required=False)

    index = Permission(title=u"The permission needed for index page.",
                       required=False)

    add = Permission(title=u"The permission needed for add page.",
                     required=False)

    layer = GlobalInterface(
        title=_("The layer the view is in."),
        description=_("""A skin is composed of layers. It is common to put
        skin specific views in a layer named after the skin. If the 'layer'
        attribute is not supplied, it defaults to 'default'."""),
        required=False)
Example #2
0
def containerViews(_context,
                   for_,
                   contents=None,
                   add=None,
                   index=None,
                   layer=IDefaultBrowserLayer):
    """Set up container views for a given content type."""

    if for_ is None:
        raise ValueError("A for interface must be specified.")

    if contents is not None:
        from zope.app.menus import zmi_views
        page(_context,
             name='contents.html',
             permission=contents,
             for_=for_,
             layer=layer,
             class_=Contents,
             attribute='contents',
             menu=zmi_views,
             title=_('Contents'))

    if index is not None:
        page(_context,
             name='index.html',
             permission=index,
             for_=for_,
             layer=layer,
             class_=Contents,
             attribute='index')

    if add is not None:
        from zope.app.menus import zmi_actions
        viewObj = view(_context,
                       name='+',
                       layer=layer,
                       for_=for_,
                       permission=add,
                       class_=Adding)
        menuItemDirective(
            _context,
            zmi_actions,
            for_,
            '+',
            _('Add'),
            permission=add,
            layer=layer,
            filter=
            'python:modules["zope.app.container.browser.metaconfigure"].menuFilter(context, request)'
        )
        viewObj.page(_context, name='index.html', attribute='index')
        viewObj.page(_context, name='action.html', attribute='action')
        viewObj()
Example #3
0
    def removeObjects(self):
        """Remove objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to remove.")
            return

        container = self.context
        for id in ids:
            del container[id]
Example #4
0
    def removeObjects(self):
        """Remove objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to remove.")
            return

        container = self.context
        for id in ids:
            del container[id]
Example #5
0
def containerViews(_context, for_, contents=None, add=None, index=None, layer=IDefaultBrowserLayer):
    """Set up container views for a given content type."""

    if for_ is None:
        raise ValueError("A for interface must be specified.")

    if contents is not None:
        from zope.app.menus import zmi_views

        page(
            _context,
            name="contents.html",
            permission=contents,
            for_=for_,
            layer=layer,
            class_=Contents,
            attribute="contents",
            menu=zmi_views,
            title=_("Contents"),
        )

    if index is not None:
        page(_context, name="index.html", permission=index, for_=for_, layer=layer, class_=Contents, attribute="index")

    if add is not None:
        from zope.app.menus import zmi_actions

        viewObj = view(_context, name="+", layer=layer, for_=for_, permission=add, class_=Adding)
        menuItemDirective(
            _context,
            zmi_actions,
            for_,
            "+",
            _("Add"),
            permission=add,
            layer=layer,
            filter='python:modules["zope.app.container.browser.metaconfigure"].menuFilter(context, request)',
        )
        viewObj.page(_context, name="index.html", attribute="index")
        viewObj.page(_context, name="action.html", attribute="action")
        viewObj()
Example #6
0
    def listContentInfo(self):
        request = self.request

        if "container_cancel_button" in request:
            if "type_name" in request:
                del request.form['type_name']
            if "rename_ids" in request and "new_value" in request:
                del request.form['rename_ids']
            if "retitle_id" in request and "new_value" in request:
                del request.form['retitle_id']

            return self._normalListContentsInfo()

        elif "container_rename_button" in request and not request.get("ids"):
            self.error = _("You didn't specify any ids to rename.")
        elif "container_add_button" in request:
            if "single_type_name" in request \
                   and "single_new_value" in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = request['single_new_value']
                self.addObject()
            elif 'single_type_name' in request \
                     and 'single_new_value' not in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = ""
                self.addObject()
        elif "type_name" in request and "new_value" in request:
            self.addObject()
        elif "rename_ids" in request and "new_value" in request:
            self.renameObjects()
        elif "retitle_id" in request and "new_value" in request:
            self.changeTitle()
        elif "container_cut_button" in request:
            self.cutObjects()
        elif "container_copy_button" in request:
            self.copyObjects()
        elif "container_paste_button" in request:
            self.pasteObjects()
        elif "container_delete_button" in request:
            self.removeObjects()
        else:
            return self._normalListContentsInfo()

        if self.error:
            return self._normalListContentsInfo()

        status = request.response.getStatus()
        if status not in (302, 303):
            # Only redirect if nothing else has
            request.response.redirect(request.URL)
        return ()
Example #7
0
    def listContentInfo(self):
        request = self.request

        if  "container_cancel_button" in request:
            if "type_name" in request:
                del request.form['type_name']
            if "rename_ids" in request and "new_value" in request:
                del request.form['rename_ids']
            if "retitle_id" in request and "new_value" in request:
                del request.form['retitle_id']

            return self._normalListContentsInfo()

        elif "container_rename_button" in request and not request.get("ids"):
            self.error = _("You didn't specify any ids to rename.")
        elif "container_add_button" in request:
            if "single_type_name" in request \
                   and "single_new_value" in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = request['single_new_value']
                self.addObject()
            elif 'single_type_name' in request \
                     and 'single_new_value' not in request:
                request.form['type_name'] = request['single_type_name']
                request.form['new_value'] = ""
                self.addObject()
        elif "type_name" in request and "new_value" in request:
            self.addObject()
        elif "rename_ids" in request and "new_value" in request:
            self.renameObjects()
        elif "retitle_id" in request and "new_value" in request:
            self.changeTitle()
        elif "container_cut_button" in request:
            self.cutObjects()
        elif "container_copy_button" in request:
            self.copyObjects()
        elif "container_paste_button" in request:
            self.pasteObjects()
        elif "container_delete_button" in request:
            self.removeObjects()
        else:
            return self._normalListContentsInfo()

        if self.error:
            return self._normalListContentsInfo()

        status = request.response.getStatus()
        if status not in (302, 303):
            # Only redirect if nothing else has
            request.response.redirect(request.URL)
        return ()
    def copyObjects(self):
        """Copy objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')

        if not ids:
            self.error = _("You didn't specify any ids to copy.")
            return

        container_path = getPath(self.context)

        # For each item, check that it can be copied; if so, save the
        # path of the object for later copying when a destination has
        # been selected; if not copyable, provide an error message
        # explaining that the object can't be copied.
        items = []
        for id in ids:
            ob = self.context[id]
            copier = IObjectCopier(ob)
            if not copier.copyable():
                m = {"name": id}
                title = getDCTitle(ob)
                if title:
                    m["title"] = title
                    self.error = _(
                        "Object '${name}' (${title}) cannot be copied",
                        mapping=m)
                else:
                    self.error = _("Object '${name}' cannot be copied",
                                   mapping=m)
                return
            items.append(joinPath(container_path, id))

        # store the requested operation in the principal annotations:
        clipboard = getPrincipalClipboard(self.request)
        clipboard.clearContents()
        clipboard.addItems('copy', items)
Example #9
0
    def cutObjects(self):
        """move objects specified in a list of object ids"""
        request = self.request
        ids = request.get('ids')
        if not ids:
            self.error = _("You didn't specify any ids to cut.")
            return

        container_path = getPath(self.context)

        # For each item, check that it can be moved; if so, save the
        # path of the object for later moving when a destination has
        # been selected; if not movable, provide an error message
        # explaining that the object can't be moved.
        items = []
        for id in ids:
            ob = self.context[id]
            mover = IObjectMover(ob)
            if not mover.moveable():
                m = {"name": id}
                title = getDCTitle(ob)
                if title:
                    m["title"] = title
                    self.error = _(
                        "Object '${name}' (${title}) cannot be moved",
                        mapping=m)
                else:
                    self.error = _("Object '${name}' cannot be moved",
                                   mapping=m)
                return
            items.append(joinPath(container_path, id))

        # store the requested operation in the principal annotations:
        clipboard = getPrincipalClipboard(self.request)
        clipboard.clearContents()
        clipboard.addItems('cut', items)
Example #10
0
    def pasteObjects(self):
        """Paste ojects in the user clipboard to the container
        """
        target = self.context
        clipboard = getPrincipalClipboard(self.request)
        items = clipboard.getContents()
        moved = False
        not_pasteable_ids = []
        for item in items:
            duplicated_id = False
            try:
                obj = traverse(target, item['target'])
            except TraversalError:
                pass
            else:
                if item['action'] == 'cut':
                    mover = IObjectMover(obj)
                    try:
                        mover.moveTo(target)
                        moved = True
                    except DuplicateIDError:
                        duplicated_id = True
                elif item['action'] == 'copy':
                    copier = IObjectCopier(obj)
                    try:
                        copier.copyTo(target)
                    except DuplicateIDError:
                        duplicated_id = True
                else:
                    raise

            if duplicated_id:
                not_pasteable_ids.append(getName(obj))

        if moved:
            # Clear the clipboard if we do a move, but not if we only do a copy
            clipboard.clearContents()

        if not_pasteable_ids != []:
            # Show the ids of objects that can't be pasted because
            # their ids are already taken.
            # TODO Can't we add a 'copy_of' or something as a prefix
            # instead of raising an exception ?
            raise UserError(
                _("The given name(s) %s is / are already being used" %
                  (str(not_pasteable_ids))))
Example #11
0
    def pasteObjects(self):
        """Paste ojects in the user clipboard to the container
        """
        target = self.context
        clipboard = getPrincipalClipboard(self.request)
        items = clipboard.getContents()
        moved = False
        not_pasteable_ids = []
        for item in items:
            duplicated_id = False
            try:
                obj = traverse(target, item['target'])
            except TraversalError:
                pass
            else:
                if item['action'] == 'cut':
                    mover = IObjectMover(obj)
                    try:
                        mover.moveTo(target)
                        moved = True
                    except DuplicateIDError:
                        duplicated_id = True
                elif item['action'] == 'copy':
                    copier = IObjectCopier(obj)
                    try:
                        copier.copyTo(target)
                    except DuplicateIDError:
                        duplicated_id = True
                else:
                    raise

            if duplicated_id:
                not_pasteable_ids.append(getName(obj))

        if moved:
            # Clear the clipboard if we do a move, but not if we only do a copy
            clipboard.clearContents()

        if not_pasteable_ids != []:
            # Show the ids of objects that can't be pasted because
            # their ids are already taken.
            # TODO Can't we add a 'copy_of' or something as a prefix
            # instead of raising an exception ?
            raise UserError(
                _("The given name(s) %s is / are already being used" %(
                str(not_pasteable_ids))))
Example #12
0
    def action(self, type_name='', id=''):
        if not type_name:
            raise UserError(_(u"You must select the type of object to add."))

        if type_name.startswith('@@'):
            type_name = type_name[2:]

        if '/' in type_name:
            view_name = type_name.split('/', 1)[0]
        else:
            view_name = type_name

        if queryMultiAdapter((self, self.request),
                                  name=view_name) is not None:
            url = "%s/%s=%s" % (
                absoluteURL(self, self.request), type_name, id)
            self.request.response.redirect(url)
            return

        if not self.contentName:
            self.contentName = id

        # TODO: If the factory wrapped by LocationProxy is already a Proxy,
        #       then ProxyFactory does not do the right thing and the
        #       original's checker info gets lost. No factory that was
        #       registered via ZCML and was used via addMenuItem worked
        #       here. (SR)
        factory = getUtility(IFactory, type_name)
        if not type(factory) is zope.security.checker.Proxy:
            factory = LocationProxy(factory, self, type_name)
            factory = zope.security.checker.ProxyFactory(factory)
        content = factory()

        # Can't store security proxies.
        # Note that it is important to do this here, rather than
        # in add, otherwise, someone might be able to trick add
        # into unproxying an existing object,
        content = removeSecurityProxy(content)

        notify(ObjectCreatedEvent(content))

        self.add(content)
        self.request.response.redirect(self.nextURL())
    def action(self, type_name='', id=''):
        if not type_name:
            raise UserError(_(u"You must select the type of object to add."))

        if type_name.startswith('@@'):
            type_name = type_name[2:]

        if '/' in type_name:
            view_name = type_name.split('/', 1)[0]
        else:
            view_name = type_name

        if queryMultiAdapter((self, self.request),
                                  name=view_name) is not None:
            url = "%s/%s=%s" % (
                absoluteURL(self, self.request), type_name, id)
            self.request.response.redirect(url)
            return

        if not self.contentName:
            self.contentName = id

        # TODO: If the factory wrapped by LocationProxy is already a Proxy,
        #       then ProxyFactory does not do the right thing and the
        #       original's checker info gets lost. No factory that was
        #       registered via ZCML and was used via addMenuItem worked
        #       here. (SR)
        factory = getUtility(IFactory, type_name)
        if not type(factory) is zope.security.checker.Proxy:
            factory = LocationProxy(factory, self, type_name)
            factory = zope.security.checker.ProxyFactory(factory)
        content = factory()

        # Can't store security proxies.
        # Note that it is important to do this here, rather than
        # in add, otherwise, someone might be able to trick add
        # into unproxying an existing object,
        content = removeSecurityProxy(content)

        notify(ObjectCreatedEvent(content))

        self.add(content)
        self.request.response.redirect(self.nextURL())