Back to index

plone3  3.1.7
OrderedBaseFolder.py
Go to the documentation of this file.
00001 """
00002 OrderedBaseFolder derived from OrderedFolder by Stephan Richter, iuveno AG.
00003 OrderedFolder adapted to Zope 2.7 style interface by Jens.KLEIN@jensquadrat.de
00004 """
00005 from zope.interface import implements
00006 from types import StringType
00007 
00008 from Products.Archetypes.BaseFolder import BaseFolder
00009 from Products.Archetypes.ExtensibleMetadata import ExtensibleMetadata
00010 from DocumentTemplate import sequence
00011 
00012 from AccessControl import ClassSecurityInfo
00013 from Globals import InitializeClass
00014 
00015 from Products.CMFCore.utils import getToolByName
00016 from Products.CMFCore.interfaces.Dynamic import DynamicType
00017 #from Products.CMFDefault.SkinnedFolder import SkinnedFolder
00018 from Products.CMFCore import permissions
00019 
00020 from OFS.IOrderSupport import IOrderedContainer as IZopeOrderedContainer
00021 from OFS.interfaces import IOrderedContainer as IZ3OrderedContainer
00022     
00023 from zExceptions import NotFound
00024 
00025 # atm its safer defining an own so we need an ugly hack to make Archetypes
00026 # OrderedBaseFolder work without Plone 2.0
00027 try:
00028     from Products.CMFPlone.interfaces.OrderedContainer import IOrderedContainer
00029 except ImportError:
00030     from Products.Archetypes.interfaces.orderedfolder import IOrderedContainer
00031 
00032 
00033 class OrderedContainer:
00034 
00035     __implements__  = (IOrderedContainer, IZopeOrderedContainer)
00036     implements(IZ3OrderedContainer)
00037 
00038     security = ClassSecurityInfo()
00039 
00040     security.declareProtected(permissions.ModifyPortalContent, 'moveObject')
00041     def moveObject(self, id, position):
00042         obj_idx  = self.getObjectPosition(id)
00043         if obj_idx == position:
00044             return None
00045         elif position < 0:
00046             position = 0
00047 
00048         metadata = list(self._objects)
00049         obj_meta = metadata.pop(obj_idx)
00050         metadata.insert(position, obj_meta)
00051         self._objects = tuple(metadata)
00052 
00053     # here the implementing of IOrderedContainer starts
00054     # if plone sometime depends on zope 2.7 it should be replaced by mixing in
00055     # the 2.7 specific class OSF.OrderedContainer.OrderedContainer
00056 
00057     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectsByDelta')
00058     def moveObjectsByDelta(self, ids, delta, subset_ids=None):
00059         """ Move specified sub-objects by delta.
00060         """
00061         if type(ids) is StringType:
00062             ids = (ids,)
00063         min_position = 0
00064         objects = list(self._objects)
00065         if subset_ids == None:
00066             # OLD: subset_ids = [ obj['id'] for obj in objects ]
00067             subset_ids = self.getCMFObjectsSubsetIds(objects)
00068         else:
00069             subset_ids = list(subset_ids)
00070         # unify moving direction
00071         if delta > 0:
00072             ids = list(ids)
00073             ids.reverse()
00074             subset_ids.reverse()
00075         counter = 0
00076 
00077         for id in ids:
00078             try:
00079                 old_position = subset_ids.index(id)
00080             except ValueError:
00081                 continue
00082             new_position = max( old_position - abs(delta), min_position )
00083             if new_position == min_position:
00084                 min_position += 1
00085             if not old_position == new_position:
00086                 subset_ids.remove(id)
00087                 subset_ids.insert(new_position, id)
00088                 counter += 1
00089 
00090         if counter > 0:
00091             if delta > 0:
00092                 subset_ids.reverse()
00093             obj_dict = {}
00094             for obj in objects:
00095                 obj_dict[ obj['id'] ] = obj
00096             pos = 0
00097             for i in range( len(objects) ):
00098                 if objects[i]['id'] in subset_ids:
00099                     try:
00100                         objects[i] = obj_dict[ subset_ids[pos] ]
00101                         pos += 1
00102                     except KeyError:
00103                         raise ValueError('The object with the id "%s" does '
00104                                          'not exist.' % subset_ids[pos])
00105             self._objects = tuple(objects)
00106 
00107         return counter
00108 
00109     security.declarePrivate('getCMFObjectsSubsetIds')
00110     def getCMFObjectsSubsetIds(self, objs):
00111         """Get the ids of only cmf objects (used for moveObjectsByDelta)
00112         """
00113         ttool = getToolByName(self, 'portal_types')
00114         cmf_meta_types = [ti.Metatype() for ti in ttool.listTypeInfo()]
00115         return [obj['id'] for obj in objs if obj['meta_type'] in cmf_meta_types ]
00116 
00117     security.declareProtected(permissions.ModifyPortalContent, 'getObjectPosition')
00118     def getObjectPosition(self, id):
00119 
00120         objs = list(self._objects)
00121         om = [objs.index(om) for om in objs if om['id']==id ]
00122 
00123         if om: # only 1 in list if any
00124             return om[0]
00125 
00126         raise NotFound, 'Object %s was not found' % str(id)
00127 
00128     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectsUp')
00129     def moveObjectsUp(self, ids, delta=1, RESPONSE=None):
00130         """ Move an object up """
00131         self.moveObjectsByDelta(ids, -delta)
00132         if RESPONSE is not None:
00133             RESPONSE.redirect('manage_workspace')
00134 
00135     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectsDown')
00136     def moveObjectsDown(self, ids, delta=1, RESPONSE=None):
00137         """ move an object down """
00138         self.moveObjectsByDelta(ids, delta)
00139         if RESPONSE is not None:
00140             RESPONSE.redirect('manage_workspace')
00141 
00142     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectsToTop')
00143     def moveObjectsToTop(self, ids, RESPONSE=None):
00144         """ move an object to the top """
00145         self.moveObjectsByDelta( ids, -len(self._objects) )
00146         if RESPONSE is not None:
00147             RESPONSE.redirect('manage_workspace')
00148 
00149     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectsToBottom')
00150     def moveObjectsToBottom(self, ids, RESPONSE=None):
00151         """ move an object to the bottom """
00152         self.moveObjectsByDelta( ids, len(self._objects) )
00153         if RESPONSE is not None:
00154             RESPONSE.redirect('manage_workspace')
00155 
00156     security.declareProtected(permissions.ModifyPortalContent, 'moveObjectToPosition')
00157     def moveObjectToPosition(self, id, position):
00158         """ Move specified object to absolute position.
00159         """
00160         delta = position - self.getObjectPosition(id)
00161         return self.moveObjectsByDelta(id, delta)
00162 
00163     security.declareProtected(permissions.ModifyPortalContent, 'orderObjects')
00164     def orderObjects(self, key, reverse=None):
00165         """ Order sub-objects by key and direction.
00166         """
00167         ids = [ id for id, obj in sequence.sort( self.objectItems(),
00168                                         ( (key, 'cmp', 'asc'), ) ) ]
00169         if reverse:
00170             ids.reverse()
00171         return self.moveObjectsByDelta( ids, -len(self._objects) )
00172 
00173     # here the implementing of IOrderedContainer ends
00174 
00175     def manage_renameObject(self, id, new_id, REQUEST=None):
00176         " "
00177         objidx = self.getObjectPosition(id)
00178         method = OrderedContainer.inheritedAttribute('manage_renameObject')
00179         result = method(self, id, new_id, REQUEST)
00180         self.moveObject(new_id, objidx)
00181 
00182         return result
00183 
00184 InitializeClass(OrderedContainer)
00185 
00186 
00187 class OrderedBaseFolder(BaseFolder, OrderedContainer):
00188     """ An ordered base folder implementation """
00189 
00190     __implements__ = OrderedContainer.__implements__,\
00191                      BaseFolder.__implements__, DynamicType
00192 
00193     security = ClassSecurityInfo()
00194 
00195     def __init__(self, oid, **kwargs):
00196         #call skinned first cause baseobject will set new defaults on
00197         #those attributes anyway
00198         BaseFolder.__init__(self, oid, **kwargs)
00199         ExtensibleMetadata.__init__(self)
00200 
00201     security.declareProtected(permissions.ModifyPortalContent, 'manage_renameObject')
00202     def manage_renameObject(self, id, new_id, REQUEST=None):
00203         """ rename the object """
00204         objidx = self.getObjectPosition(id)
00205         result = BaseFolder.manage_renameObject(self, id, new_id, REQUEST)
00206         self.moveObject(new_id, objidx)
00207 
00208         return result
00209 
00210 InitializeClass(OrderedBaseFolder)
00211 
00212 OrderedBaseFolderSchema = OrderedBaseFolder.schema
00213 
00214 __all__ = ('OrderedBaseFolder', 'OrderedContainer', 'OrderedBaseFolderSchema',)