Back to index

plone3  3.1.7
BaseFolder.py
Go to the documentation of this file.
00001 from Products.Archetypes import WebDAVSupport
00002 from Products.Archetypes.CatalogMultiplex  import CatalogMultiplex
00003 from Products.Archetypes.ExtensibleMetadata import ExtensibleMetadata
00004 from Products.Archetypes.BaseObject import BaseObject
00005 from Products.Archetypes.interfaces import IBaseFolder
00006 from Products.Archetypes.interfaces import IBaseObject
00007 from Products.Archetypes.interfaces import IReferenceable
00008 from Products.Archetypes.interfaces.base import IBaseFolder as z2IBaseFolder
00009 from Products.Archetypes.interfaces.referenceable import IReferenceable as z2IReferenceable
00010 from Products.Archetypes.interfaces.metadata import IExtensibleMetadata
00011 
00012 from AccessControl import ClassSecurityInfo
00013 from AccessControl import Unauthorized
00014 from Globals import InitializeClass
00015 from Products.CMFCore import permissions
00016 from Products.CMFCore.interfaces import IContentish
00017 from Products.CMFCore.PortalFolder import PortalFolderBase as PortalFolder
00018 from Products.CMFCore.PortalContent import PortalContent
00019 from Products.CMFCore.utils import _checkPermission
00020 
00021 from zope.interface import implements
00022 
00023 class BaseFolderMixin(CatalogMultiplex,
00024                       BaseObject,
00025                       PortalFolder,
00026                       ):
00027     """A not-so-basic Folder implementation, with no Dublin Core
00028     Metadata"""
00029 
00030     __implements__ = (z2IBaseFolder, z2IReferenceable, BaseObject.__implements__,
00031                       PortalFolder.__implements__)
00032     implements(IBaseFolder, IBaseObject, IReferenceable, IContentish)
00033 
00034     security = ClassSecurityInfo()
00035 
00036     # Fix permissions set by CopySupport.py
00037     __ac_permissions__ = (
00038         (permissions.ModifyPortalContent,
00039          ('manage_cutObjects', 'manage_pasteObjects',
00040           'manage_renameObject', 'manage_renameObjects',)),
00041         )
00042     security.declareProtected('Copy or Move', 'manage_copyObjects')
00043 
00044     manage_options = PortalFolder.manage_options
00045     content_icon = "folder_icon.gif"
00046     use_folder_tabs = 1
00047     isPrincipiaFolderish = 1
00048     isAnObjectManager = 1
00049     __dav_marshall__ = False
00050 
00051 
00052     __call__ = PortalContent.__call__.im_func
00053 
00054     # This special value informs ZPublisher to use __call__
00055     index_html = None
00056 
00057     def __init__(self, oid, **kwargs):
00058         # Call skinned first cause baseobject will set new defaults on
00059         # those attributes anyway
00060         PortalFolder.__init__(self, oid, self.Title())
00061         BaseObject.__init__(self, oid, **kwargs)
00062 
00063     def _notifyOfCopyTo(self, container, op=0):
00064         """In the case of a move (op=1) we need to make sure
00065         references are mainained for all referencable objects within
00066         the one being moved.
00067 
00068         manage_renameObject calls _notifyOfCopyTo so that the
00069         object being renamed doesn't lose its references. But
00070         manage_renameObject calls _delObject which calls
00071         manage_beforeDelete on all the children of the object
00072         being renamed which deletes all references for children
00073         of the object being renamed. Here is a patch that does
00074         recursive calls for _notifyOfCopyTo to address that
00075         problem.
00076         """
00077         # XXX this doesn't appear to be necessary anymore, if it is
00078         # it needs to be used in BaseBTreeFolder as well, it currently
00079         # is not.
00080         BaseObject._notifyOfCopyTo(self, container, op=op)
00081         # keep reference info internally when op == 1 (move)
00082         # because in those cases we need to keep refs
00083         if op==1:
00084             self._v_cp_refs = 1
00085         for child in self.contentValues():
00086             if IReferenceable.providedBy(child):
00087                 child._notifyOfCopyTo(self, op)
00088 
00089     security.declarePrivate('manage_afterAdd')
00090     def manage_afterAdd(self, item, container):
00091         BaseObject.manage_afterAdd(self, item, container)
00092 
00093     security.declarePrivate('manage_afterClone')
00094     def manage_afterClone(self, item):
00095         BaseObject.manage_afterClone(self, item)
00096 
00097     security.declarePrivate('manage_beforeDelete')
00098     def manage_beforeDelete(self, item, container):
00099         BaseObject.manage_beforeDelete(self, item, container)
00100         #and reset the rename flag (set in Referenceable._notifyCopyOfCopyTo)
00101         self._v_cp_refs = None
00102 
00103     security.declareProtected(permissions.DeleteObjects,
00104                               'manage_delObjects')
00105     def manage_delObjects(self, ids=[], REQUEST=None):
00106         """We need to enforce security."""
00107         if isinstance(ids, basestring):
00108             ids = [ids]
00109         for id in ids:
00110             item = self._getOb(id)
00111             if not _checkPermission(permissions.DeleteObjects, item):
00112                 raise Unauthorized, (
00113                     "Do not have permissions to remove this object")
00114         return PortalFolder.manage_delObjects(self, ids, REQUEST=REQUEST)
00115 
00116     security.declareProtected(permissions.ListFolderContents,
00117                               'listFolderContents')
00118     def listFolderContents(self, contentFilter=None, suppressHiddenFiles=0):
00119         """Optionally you can suppress "hidden" files, or files that begin
00120         with a dot.
00121         """
00122         contents=PortalFolder.listFolderContents(self, contentFilter=contentFilter)
00123         if suppressHiddenFiles:
00124             contents=[obj for obj in contents if obj.getId()[:1]!='.']
00125 
00126         return contents
00127 
00128     security.declareProtected(permissions.AccessContentsInformation,
00129                               'folderlistingFolderContents')
00130     def folderlistingFolderContents(self, contentFilter=None,
00131                                     suppressHiddenFiles=0):
00132         """Calls listFolderContents in protected only by ACI so that
00133         folder_listing can work without the List folder contents permission,
00134         as in CMFDefault.
00135         """
00136         return self.listFolderContents(contentFilter=contentFilter,
00137                                        suppressHiddenFiles=suppressHiddenFiles)
00138 
00139     security.declareProtected(permissions.View, 'Title')
00140     def Title(self, **kwargs):
00141         """We have to override Title here to handle arbitrary arguments since
00142         PortalFolder defines it."""
00143         return self.getField('title').get(self, **kwargs)
00144 
00145     security.declareProtected(permissions.ModifyPortalContent,
00146                               'setTitle')
00147     def setTitle(self, value, **kwargs):
00148         """We have to override setTitle here to handle arbitrary
00149         arguments since PortalFolder defines it."""
00150         self.getField('title').set(self, value, **kwargs)
00151 
00152     def __getitem__(self, key):
00153         """Overwrite __getitem__.
00154 
00155         At first it's using the BaseObject version. If the element can't be
00156         retrieved from the schema it's using PortalFolder as fallback which
00157         should be the ObjectManager's version.
00158         """
00159         try:
00160             return BaseObject.__getitem__(self, key)
00161         except KeyError:
00162             return PortalFolder.__getitem__(self, key)
00163 
00164     # override "CMFCore.PortalFolder.PortalFolder.manage_addFolder"
00165     # as it insists on creating folders of type "Folder".
00166     # use instead "_at_type_subfolder" or our own type.
00167     security.declareProtected(permissions.AddPortalFolders,
00168                               'manage_addFolder')
00169     def manage_addFolder(self,
00170                          id,
00171                          title='',
00172                          REQUEST=None,
00173                          type_name=None):
00174         """Add a new folder-like object with id *id*.
00175 
00176         IF present, use the parent object's 'mkdir' alias; otherwise, just add
00177         a PortalFolder.
00178         """
00179         ti = self.getTypeInfo()
00180         # BBB getMethodURL is part of CMF 1.5 but AT 1.3 should be compatible
00181         # with CMF 1.4
00182         try:
00183             method = ti and ti.getMethodURL('mkdir') or None
00184         except AttributeError:
00185             method = None
00186         if method is not None:
00187             # call it
00188             getattr(self, method)(id=id)
00189         else:
00190             if type_name is None:
00191                 type_name = getattr(self, '_at_type_subfolder', None)
00192             if type_name is None:
00193                 type_name = ti and ti.getId() or 'Folder'
00194             self.invokeFactory(type_name, id=id)
00195 
00196         ob = self._getOb(id)
00197         try:
00198             ob.setTitle(title)
00199         except AttributeError:
00200             pass
00201         try:
00202             ob.reindexObject()
00203         except AttributeError:
00204             pass
00205 
00206     def MKCOL_handler(self, id, REQUEST=None, RESPONSE=None):
00207         """Hook into the MKCOL (make collection) process to call
00208         manage_afterMKCOL.
00209         """
00210         result = PortalFolder.MKCOL_handler(self, id, REQUEST, RESPONSE)
00211         self.manage_afterMKCOL(id, result, REQUEST, RESPONSE)
00212         return result
00213 
00214     security.declarePrivate('manage_afterMKCOL')
00215     def manage_afterMKCOL(self, id, result, REQUEST=None, RESPONSE=None):
00216         """After MKCOL handler.
00217         """
00218         pass
00219 
00220     security.declareProtected(permissions.ModifyPortalContent, 'PUT')
00221     PUT = WebDAVSupport.PUT
00222 
00223     security.declareProtected(permissions.View, 'manage_FTPget')
00224     manage_FTPget = WebDAVSupport.manage_FTPget
00225 
00226     security.declarePrivate('manage_afterPUT')
00227     manage_afterPUT = WebDAVSupport.manage_afterPUT
00228 
00229 InitializeClass(BaseFolderMixin)
00230 
00231 
00232 class BaseFolder(BaseFolderMixin, ExtensibleMetadata):
00233     """A not-so-basic Folder implementation, with Dublin Core
00234     Metadata included"""
00235 
00236     __implements__ = BaseFolderMixin.__implements__, IExtensibleMetadata
00237     implements(IBaseFolder, IBaseObject, IReferenceable, IContentish)
00238 
00239     schema = BaseFolderMixin.schema + ExtensibleMetadata.schema
00240 
00241     security = ClassSecurityInfo()
00242 
00243     def __init__(self, oid, **kwargs):
00244         # Call skinned first cause baseobject will set new defaults on
00245         # those attributes anyway
00246         BaseFolderMixin.__init__(self, oid, **kwargs)
00247         ExtensibleMetadata.__init__(self)
00248 
00249     security.declareProtected(permissions.View,
00250                               'Description')
00251     def Description(self, **kwargs):
00252         """We have to override Description here to handle arbitrary
00253         arguments since PortalFolder defines it."""
00254         return self.getField('description').get(self, **kwargs)
00255 
00256     security.declareProtected(permissions.ModifyPortalContent,
00257                               'setDescription')
00258     def setDescription(self, value, **kwargs):
00259         """We have to override setDescription here to handle arbitrary
00260         arguments since PortalFolder defines it."""
00261         self.getField('description').set(self, value, **kwargs)
00262 
00263 InitializeClass(BaseFolder)
00264 
00265 BaseFolderSchema = BaseFolder.schema
00266 
00267 __all__ = ('BaseFolder', 'BaseFolderMixin', 'BaseFolderSchema')