[Zope-CMF] transparent folder

Gregoire Weber gregoire.weber@switzerland.org
Fri, 07 Mar 2003 11:08:47 +0100


Hi,

IMO it's better to extend PortalFolder with the relevant methods,=20
as I've done it. Have a look at the code below.

Additional Resources:

  - Proposal:=
 <http://www.zope.org//Wikis/DevSite/Proposals/OrderedObjectManager>

  - Code: <http://www.zope.org/Members/mjablonski/OrderedObjectManager>

Gregoire

---------- OrderedPortalFolder.py start ----------
#####
##
# OrderedPortalFolder
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# This product uses modified codes from the OrderedFolder-Product
# written by Stephan Richter / copyrighted by iuveno AG
# Please read the LICENSE.txt!
#
# The code below is derived from OrderedObjectManager
# from maik.jablonski@uni-bielefeld.de
##
####

from types import StringType
from Globals import ImageFile, DTMLFile, InitializeClass
from AccessControl import ClassSecurityInfo
from Products.CMFCore import CMFCorePermissions

from Products.CMFCore.PortalFolder import PortalFolder

oomPermission =3D 'Copy or Move'

class OrderedPortalFolder(PortalFolder):

    security =3D ClassSecurityInfo()
    security.declareObjectProtected(CMFCorePermissions.View)

    # override the ZMI folder view
    manage_main =3D DTMLFile('dtml/manage_main', globals())

    misc_ =3D {'up'     : ImageFile('zmi/up.gif', globals()),
             'down'   : ImageFile('zmi/down.gif', globals()),
             'top'    : ImageFile('zmi/top.gif', globals()),
             'bottom' : ImageFile('zmi/bottom.gif', globals())}

    security.declareProtected(oomPermission, 'get_object_position')
    def get_object_position(self, id):
        """ Get the position of a particular object. """
   =20
        ids =3D map(lambda obj: obj['id'], self._objects)
        if id in ids:
            return ids.index(id)
        else:
            raise 'ObjectNotFound', self.aq_parent._objects           =20
   =20
    security.declareProtected(oomPermission, 'move_objects_by_positions')
    def move_objects_by_positions(self, ids, position_delta):
        """ moves objects with ids by position_delta """

        if type(ids) is StringType: ids =3D (ids,)

        # Interestingly enough, we need to switch the order when
        # moving done, so that the movements won't cancel each other
        if position_delta > 0:
            ids =3D list(ids)
            ids.reverse()
           =20
        moved_objects =3D 0
       =20
        for id in ids:
            old_position =3D self.get_object_position(id)
            new_position =3D old_position + position_delta
            object =3D self._objects[old_position]
            # Make sure the new position makes sense and is valid
            if not (old_position =3D=3D new_position  or
                    new_position > len(self._objects) or
                    new_position < 0):
           =20
                objects =3D list(self._objects)
                # now delete the entry ...
                objects =3D filter(lambda obj, id=3Did: obj['id'] !=3D id,=
 objects)
                # ... and now add it again
                objects.insert(new_position, object)
                self._objects =3D tuple(objects)

                moved_objects =3D moved_objects + 1

        return moved_objects

    security.declareProtected(oomPermission, 'move_objects_up')
    def move_objects_up(self, ids):
        """ moving the items up """
       =20
        return self.move_objects_by_positions(ids, -1)

    security.declareProtected(oomPermission, 'move_objects_down')
    def move_objects_down(self, ids):
        """ moving the items down """
=20
        return self.move_objects_by_positions(ids, +1)

    security.declareProtected(oomPermission, 'move_objects_to_top')
    def move_objects_to_top(self, ids):
        """ moving the items to the top """
              =20
        if type(ids) is StringType: ids =3D (ids,)

        position_delta =3D - self.get_object_position(ids[0])
        return self.move_objects_by_positions(ids, position_delta)

    security.declareProtected(oomPermission, 'move_objects_to_bottom')
    def move_objects_to_bottom(self, ids):
        """ moving the items to the bottom """

        if type(ids) is StringType: ids =3D (ids,)

        # We will do the reverse twice,
        # but for going to the bottom there is no other choice.
        ids =3D list(ids)
        ids.reverse()

        position_delta =3D len(self.objectIds()) -=
 self.get_object_position(ids[-1])
        return self.move_objects_by_positions(ids, position_delta)

    security.declareProtected(oomPermission, 'manage_move_objects_up')
    def manage_move_objects_up(self, ids=3DNone, REQUEST=3DNone):
        """ moves selected items up by one """

        if type(ids) is StringType: ids =3D (ids,)
           =20
        attempt =3D 0
        if ids: attempt =3D self.move_objects_up(ids)

        if REQUEST: REQUEST.RESPONSE.redirect('manage_main')
        return attempt

    security.declareProtected(oomPermission, 'manage_move_objects_down')
    def manage_move_objects_down(self, ids=3DNone, REQUEST=3DNone):
        """ moves selected items down by one """

        if type(ids) is StringType: ids =3D (ids,)

        attempt =3D 0
        if ids: attempt =3D self.move_objects_down(ids)

        if REQUEST: REQUEST.RESPONSE.redirect('manage_main')
        return attempt

    security.declareProtected(oomPermission, 'manage_move_objects_to_top')
    def manage_move_objects_to_top(self, ids=3DNone, REQUEST=3DNone):
        """ moves selected items to top """
   =20
        if type(ids) is StringType: ids =3D (ids,)

        attempt=3D0
        if ids: attempt=3Dself.move_objects_to_top(ids)

        if REQUEST: REQUEST.RESPONSE.redirect('manage_main')
        return attempt

    security.declareProtected(oomPermission,=
 'manage_move_objects_to_bottom')
    def manage_move_objects_to_bottom(self, ids=3DNone, REQUEST=3DNone):
        """ moves selected items to bottom """

        if type(ids) is StringType: ids =3D (ids,)

        attempt=3D0
        if ids: attempt =3D self.move_objects_to_bottom(ids)

        if REQUEST: REQUEST.RESPONSE.redirect('manage_main')
        return attempt

    security.declareProtected(oomPermission, 'manage_orderObjects')
    def manage_orderObjects(self, ids=3DNone, REQUEST=3DNone):
        """ orders a container with the ordered list 'ids' """

        if ids:
            for id in ids:
                old_position =3D self.get_object_position(id)
                new_position =3D ids.index(id)
                object =3D self._objects[old_position]
                # Make sure the new position makes sense and is valid
                if not (old_position =3D=3D new_position  or
                        new_position > len(self._objects) or
                        new_position < 0):
               =20
                    objects =3D list(self._objects)
                    # now delete the entry ...
                    objects =3D filter(lambda obj, id=3Did: obj['id'] !=3D=
 id, objects)
                    # ... and now add it again
                    objects.insert(new_position, object)
                    self._objects =3D tuple(objects)

        if REQUEST: REQUEST.RESPONSE.redirect('manage_main')
       =20
    # Override 'manage_renameObject' of CopyContainer -
    # manage_renameObject should preserve the order

    def manage_renameObject(self, id, new_id, REQUEST=3DNone):
        """ rename a particular sub-object """
   =20
        position =3D self.get_object_position(id)
        result =3D PortalFolder.manage_renameObject(self, id, new_id,=
 REQUEST)
        newposition =3D self.get_object_position(result)
        self.move_objects_by_positions(result, position - newposition)

        return result

InitializeClass(OrderedPortalFolder)
---------- OrderedPortalFolder.py end ----------

At 20:02 07.03.2003 +1100, David Hart wrote:
>Hi,
>
>Okay, I did a crazy thing: I patched PortalFolder to superclass=
 OrderedFolder instead of Folder:
>
>#pwd
>/opt/zope/Products/CMF-1.3/CMFCore
>#
>#diff PortalFolder.py.orig PortalFolder.py.Ordered
>25a26
>> from Products.OrderedFolder.OrderedFolder import OrderedFolder
>67c68
>< class PortalFolder(DynamicType, CMFCatalogAware, Folder):
>---
>> class PortalFolder(DynamicType, CMFCatalogAware, OrderedFolder):
>380c381
><         self.manage_addFolder( id=3Did, title=3D'' )
>---
>>         self.manage_addOrderedFolder( id=3Did, title=3D'' )
>463c464
><     def manage_addFolder( self
>---
>>     def manage_addOrderedFolder( self
>
>
>Now from the CMF interface (Plone, actually), all works fine. I can add new=
 PloneFolders, set the transparent flag, add other objects, like documents,=
 to them, etc.
>
>However, when I use invokeFactory from within a python script, the new=
 object is created in the parent folder:
>
>inline_content.invokeFactory(id=3Dobject_id, type_name=3D'Document')
>
>Now, I think this may have to do with util.py and acquisition within=
 getToolByName, but I'm not sure... Can anyone help shed any light on the=
 problem?
>
>Constructive comments only please.
>
>Thanks,
>
>Dave Hart

_____________________________________
Gr=E9goire Weber
mailto:gregoire.weber@switzerland.org