[Zope-Checkins] CVS: Zope/lib/python/OFS - IOrderSupport.py:1.2 OrderSupport.py:1.2 OrderedFolder.py:1.2 Folder.py:1.102
Yvo Schubbe
schubbe@web.de
Thu, 12 Jun 2003 06:21:30 -0400
Update of /cvs-repository/Zope/lib/python/OFS
In directory cvs.zope.org:/tmp/cvs-serv760/lib/python/OFS
Modified Files:
Folder.py
Added Files:
IOrderSupport.py OrderSupport.py OrderedFolder.py
Log Message:
Merged yuppie-ordersupport-branch:
- Added OrderSupport and OrderedFolder.
- Added optional 'id' argument to Folder constructor.
- Modified main.dtml to play well with Folder and OrderedFolder.
=== Zope/lib/python/OFS/IOrderSupport.py 1.1 => 1.2 ===
--- /dev/null Thu Jun 12 06:21:30 2003
+++ Zope/lib/python/OFS/IOrderSupport.py Thu Jun 12 06:20:59 2003
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+""" Order support interfaces.
+
+$Id$
+"""
+
+from Interface import Interface
+
+
+class IOrderedContainer(Interface):
+ """ Ordered Container interface.
+
+ This interface provides a common mechanism for maintaining ordered
+ collections.
+ """
+
+ def moveObjectsByDelta(ids, delta):
+ """ Move specified sub-objects by delta.
+
+ If delta is higher than the possible maximum, objects will be moved to
+ the bottom. If delta is lower than the possible minimum, objects will
+ be moved to the top.
+
+ The order of the objects specified by ids will always be preserved. So
+ if you don't want to change their original order, make sure the order
+ of ids corresponds to their original order.
+
+ If an object with id doesn't exist an error will be raised.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsUp(ids, delta=1):
+ """ Move specified sub-objects up by delta in container.
+
+ If no delta is specified, delta is 1. See moveObjectsByDelta for more
+ details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsDown(ids, delta=1):
+ """ Move specified sub-objects down by delta in container.
+
+ If no delta is specified, delta is 1. See moveObjectsByDelta for more
+ details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsToTop(ids):
+ """ Move specified sub-objects to top of container.
+
+ See moveObjectsByDelta for more details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def moveObjectsToBottom(ids):
+ """ Move specified sub-objects to bottom of container.
+
+ See moveObjectsByDelta for more details.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def orderObjects(key, reverse=None):
+ """ Order sub-objects by key and direction.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
+
+ def getObjectPosition(id):
+ """ Get the position of an object by its id.
+
+ Permission -- Access contents information
+
+ Returns -- Position
+ """
+
+ def moveObjectToPosition(id, position):
+ """ Moves specified object to absolute position.
+
+ Permission -- Manage properties
+
+ Returns -- Number of moved sub-objects
+ """
=== Zope/lib/python/OFS/OrderSupport.py 1.1 => 1.2 ===
--- /dev/null Thu Jun 12 06:21:30 2003
+++ Zope/lib/python/OFS/OrderSupport.py Thu Jun 12 06:20:59 2003
@@ -0,0 +1,251 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+""" Order support for 'Object Manager'.
+
+$Id$
+"""
+
+from types import StringType
+
+from AccessControl import ClassSecurityInfo
+from AccessControl.Permissions import access_contents_information
+from AccessControl.Permissions import manage_properties
+from DocumentTemplate.sequence import sort
+from Globals import InitializeClass
+
+from IOrderSupport import IOrderedContainer
+from ObjectManager import ObjectManager
+
+
+class OrderSupport:
+ """ Ordered container mixin class.
+
+ This is an extension to the regular ObjectManager. It saves the objects in
+ order and lets you change the order of the contained objects. This is
+ particular helpful, if the order does not depend on object attributes, but
+ is totally user-specific.
+ """
+
+ __implements__ = IOrderedContainer
+ security = ClassSecurityInfo()
+
+ has_order_support = 1
+ _default_sort_key = 'position'
+ _default_sort_reverse = 0
+
+ manage_options = ( { 'label':'Contents',
+ 'action':'manage_main',
+ 'help':('OFSP','OrderSupport_Contents.stx') }
+ ,
+ )
+
+ #
+ # ZMI Methods
+ #
+
+ security.declareProtected(manage_properties, 'manage_move_objects_up')
+ def manage_move_objects_up(self, REQUEST, ids=None, delta=None):
+ """ Move specified sub-objects up by delta in container.
+ """
+ if ids:
+ try:
+ attempt = self.moveObjectsUp(ids, delta)
+ message = '%d item%s moved up.' % ( attempt,
+ ( (attempt!=1) and 's' or '' ) )
+ except ValueError, errmsg:
+ message = 'Error: %s' % (errmsg)
+ else:
+ message = 'Error: No items were specified!'
+ return self.manage_main(self, REQUEST, skey='position',
+ manage_tabs_message=message)
+
+ security.declareProtected(manage_properties, 'manage_move_objects_down')
+ def manage_move_objects_down(self, REQUEST, ids=None, delta=None):
+ """ Move specified sub-objects down by delta in container.
+ """
+ if ids:
+ try:
+ attempt = self.moveObjectsDown(ids, delta)
+ message = '%d item%s moved down.' % ( attempt,
+ ( (attempt!=1) and 's' or '' ) )
+ except ValueError, errmsg:
+ message = 'Error: %s' % (errmsg)
+ else:
+ message = 'Error: No items were specified!'
+ return self.manage_main(self, REQUEST, skey='position',
+ manage_tabs_message=message)
+
+ security.declareProtected(manage_properties, 'manage_move_objects_to_top')
+ def manage_move_objects_to_top(self, REQUEST, ids=None):
+ """ Move specified sub-objects to top of container.
+ """
+ if ids:
+ try:
+ attempt = self.moveObjectsToTop(ids)
+ message = '%d item%s moved to top.' % ( attempt,
+ ( (attempt!=1) and 's' or '' ) )
+ except ValueError, errmsg:
+ message = 'Error: %s' % (errmsg)
+ else:
+ message = 'Error: No items were specified!'
+ return self.manage_main(self, REQUEST, skey='position',
+ manage_tabs_message=message)
+
+ security.declareProtected(manage_properties, 'manage_move_objects_to_bottom')
+ def manage_move_objects_to_bottom(self, REQUEST, ids=None):
+ """ Move specified sub-objects to bottom of container.
+ """
+ if ids:
+ try:
+ attempt = self.moveObjectsToBottom(ids)
+ message = '%d item%s moved to bottom.' % ( attempt,
+ ( (attempt!=1) and 's' or '' ) )
+ except ValueError, errmsg:
+ message = 'Error: %s' % (errmsg)
+ else:
+ message = 'Error: No items were specified!'
+ return self.manage_main(self, REQUEST, skey='position',
+ manage_tabs_message=message)
+
+ security.declareProtected(manage_properties, 'manage_set_default_sorting')
+ def manage_set_default_sorting(self, REQUEST, key, reverse):
+ """ Set default sorting key and direction.
+ """
+ self.setDefaultSorting(key, reverse)
+ return self.manage_main(self, REQUEST)
+
+
+ #
+ # IOrderedContainer Interface Methods
+ #
+
+ security.declareProtected(manage_properties, 'moveObjectsByDelta')
+ def moveObjectsByDelta(self, ids, delta):
+ """ Move specified sub-objects by delta.
+ """
+ if type(ids) is StringType:
+ ids = (ids,)
+ min_position = 0
+ objects = list(self._objects)
+ obj_dict = {}
+ for obj in self._objects:
+ obj_dict[ obj['id'] ] = obj
+ # unify moving direction
+ if delta > 0:
+ ids = list(ids)
+ ids.reverse()
+ objects.reverse()
+ counter = 0
+
+ for id in ids:
+ try:
+ object = obj_dict[id]
+ except KeyError:
+ raise (ValueError,
+ 'The object with the id "%s" does not exist.' % id)
+ old_position = objects.index(object)
+ new_position = max( old_position - abs(delta), min_position )
+ if new_position == min_position:
+ min_position += 1
+ if not old_position == new_position:
+ objects.remove(object)
+ objects.insert(new_position, object)
+ counter += 1
+
+ if counter > 0:
+ if delta > 0:
+ objects.reverse()
+ self._objects = tuple(objects)
+
+ return counter
+
+ security.declareProtected(manage_properties, 'moveObjectsUp')
+ def moveObjectsUp(self, ids, delta=1):
+ """ Move specified sub-objects up by delta in container.
+ """
+ return self.moveObjectsByDelta(ids, -delta)
+
+ security.declareProtected(manage_properties, 'moveObjectsDown')
+ def moveObjectsDown(self, ids, delta=1):
+ """ Move specified sub-objects down by delta in container.
+ """
+ return self.moveObjectsByDelta(ids, delta)
+
+ security.declareProtected(manage_properties, 'moveObjectsToTop')
+ def moveObjectsToTop(self, ids):
+ """ Move specified sub-objects to top of container.
+ """
+ return self.moveObjectsByDelta( ids, -len(self._objects) )
+
+ security.declareProtected(manage_properties, 'moveObjectsToBottom')
+ def moveObjectsToBottom(self, ids):
+ """ Move specified sub-objects to bottom of container.
+ """
+ return self.moveObjectsByDelta( ids, len(self._objects) )
+
+ security.declareProtected(manage_properties, 'orderObjects')
+ def orderObjects(self, key, reverse=None):
+ """ Order sub-objects by key and direction.
+ """
+ ids = [ id for id, obj in sort( self.objectItems(),
+ ( (key, 'cmp', 'asc'), ) ) ]
+ if reverse:
+ ids.reverse()
+ return self.moveObjectsByDelta( ids, -len(self._objects) )
+
+ security.declareProtected(access_contents_information,
+ 'getObjectPosition')
+ def getObjectPosition(self, id):
+ """ Get the position of an object by its id.
+ """
+ ids = self.objectIds()
+ if id in ids:
+ return ids.index(id)
+ raise ValueError, 'The object with the id "%s" does not exist.' % id
+
+ security.declareProtected(manage_properties, 'moveObjectToPosition')
+ def moveObjectToPosition(self, id, position):
+ """ Move specified object to absolute position.
+ """
+ delta = position - self.getObjectPosition(id)
+ return self.moveObjectsByDelta(id, delta)
+
+ security.declareProtected(access_contents_information, 'getDefaultSorting')
+ def getDefaultSorting(self):
+ """ Get default sorting key and direction.
+ """
+ return self._default_sort_key, self._default_sort_reverse
+
+ security.declareProtected(manage_properties, 'setDefaultSorting')
+ def setDefaultSorting(self, key, reverse):
+ """ Set default sorting key and direction.
+ """
+ self._default_sort_key = key
+ self._default_sort_reverse = reverse and 1 or 0
+
+
+ #
+ # Override Inherited Method of ObjectManager Subclass
+ #
+
+ _old_manage_renameObject = ObjectManager.inheritedAttribute(
+ 'manage_renameObject')
+ def manage_renameObject(self, id, new_id, REQUEST=None):
+ """ Rename a particular sub-object without changing its position.
+ """
+ old_position = self.getObjectPosition(id)
+ result = self._old_manage_renameObject(id, new_id, REQUEST)
+ self.moveObjectToPosition(new_id, old_position)
+ return result
+
+InitializeClass(OrderSupport)
=== Zope/lib/python/OFS/OrderedFolder.py 1.1 => 1.2 ===
--- /dev/null Thu Jun 12 06:21:30 2003
+++ Zope/lib/python/OFS/OrderedFolder.py Thu Jun 12 06:20:59 2003
@@ -0,0 +1,71 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors. All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE
+#
+##############################################################################
+""" 'Folder' with order support.
+
+$Id$
+"""
+
+from AccessControl import getSecurityManager
+from AccessControl import Unauthorized
+from AccessControl.Permissions import add_page_templates
+from AccessControl.Permissions import add_user_folders
+from Globals import DTMLFile
+
+from Folder import Folder
+from OrderSupport import OrderSupport
+
+manage_addOrderedFolderForm = DTMLFile('dtml/addOrderedFolder', globals())
+
+def manage_addOrderedFolder(self, id, title='', createPublic=0, createUserF=0,
+ REQUEST=None):
+ """Add a new ordered Folder object with id *id*.
+
+ If the 'createPublic' and 'createUserF' parameters are set to any true
+ value, an 'index_html' and a 'UserFolder' objects are created respectively
+ in the new folder.
+ """
+ ob = OrderedFolder(id)
+ ob.title = title
+ self._setObject(id, ob)
+ ob = self._getOb(id)
+
+ checkPermission = getSecurityManager().checkPermission
+
+ if createUserF:
+ if not checkPermission(add_user_folders, ob):
+ raise Unauthorized, (
+ 'You are not authorized to add User Folders.'
+ )
+ ob.manage_addUserFolder()
+
+ if createPublic:
+ if not checkPermission(add_page_templates, ob):
+ raise Unauthorized, (
+ 'You are not authorized to add Page Templates.'
+ )
+ ob.manage_addProduct['PageTemplates'].manage_addPageTemplate(
+ id='index_html', title='')
+
+ if REQUEST:
+ return self.manage_main(self, REQUEST, update_menu=1)
+
+
+class OrderedFolder(OrderSupport, Folder):
+ """ Extends the default Folder by order support.
+ """
+ __implements__ = (OrderSupport.__implements__,
+ Folder.__implements__)
+ meta_type='Folder (Ordered)'
+
+ manage_options = ( OrderSupport.manage_options +
+ Folder.manage_options[1:] )
=== Zope/lib/python/OFS/Folder.py 1.101 => 1.102 ===
--- Zope/lib/python/OFS/Folder.py:1.101 Wed Aug 14 17:42:56 2002
+++ Zope/lib/python/OFS/Folder.py Thu Jun 12 06:20:59 2003
@@ -22,10 +22,11 @@
import Globals, SimpleItem, ObjectManager, PropertyManager
import AccessControl.Role, webdav.Collection, FindSupport
from webdav.WriteLockInterface import WriteLockInterface
+from AccessControl import getSecurityManager
from AccessControl import Unauthorized
-
+from AccessControl.Permissions import add_page_templates
+from AccessControl.Permissions import add_user_folders
from Globals import DTMLFile
-from AccessControl import getSecurityManager
manage_addFolderForm=DTMLFile('dtml/folderAdd', globals())
@@ -40,23 +41,22 @@
value, an 'index_html' and a 'UserFolder' objects are created respectively
in the new folder.
"""
- ob=Folder()
- ob.id=str(id)
- ob.title=title
+ ob = Folder(id)
+ ob.title = title
self._setObject(id, ob)
- ob=self._getOb(id)
+ ob = self._getOb(id)
checkPermission=getSecurityManager().checkPermission
if createUserF:
- if not checkPermission('Add User Folders', ob):
+ if not checkPermission(add_user_folders, ob):
raise Unauthorized, (
'You are not authorized to add User Folders.'
)
ob.manage_addUserFolder()
if createPublic:
- if not checkPermission('Add Page Templates', ob):
+ if not checkPermission(add_page_templates, ob):
raise Unauthorized, (
'You are not authorized to add Page Templates.'
)
@@ -67,7 +67,6 @@
return self.manage_main(self, REQUEST, update_menu=1)
-
class Folder(
ObjectManager.ObjectManager,
PropertyManager.PropertyManager,
@@ -100,5 +99,8 @@
__ac_permissions__=()
+ def __init__(self, id=None):
+ if id is not None:
+ self.id = str(id)
Globals.default__class_init__(Folder)