[CMF-checkins] CVS: CMF/CMFCore - CMFCatalogAware.py:1.10 MembershipTool.py:1.24 PortalContent.py:1.36 PortalFolder.py:1.38

Florent Guillaume fg@nuxeo.com
Sat, 20 Jul 2002 22:58:41 -0400


Update of /cvs-repository/CMF/CMFCore
In directory cvs.zope.org:/tmp/cvs-serv27923/CMFCore

Modified Files:
	CMFCatalogAware.py MembershipTool.py PortalContent.py 
	PortalFolder.py 
Log Message:
Allowed Portal Folders to be discussable.

(CMFCatalogAware has grown over time. It would be nice to split it into
separate mixins, unfortunately without a super() it would be hard to get
everything right for derived classes.)



=== CMF/CMFCore/CMFCatalogAware.py 1.9 => 1.10 ===
 from Acquisition import aq_base
 
 from AccessControl import ClassSecurityInfo
-from CMFCorePermissions import ModifyPortalContent
+from CMFCorePermissions import ModifyPortalContent, AccessContentsInformation
 from utils import getToolByName
 
 
@@ -30,18 +30,31 @@
 
     security.declareProtected(ModifyPortalContent, 'indexObject')
     def indexObject(self):
+        """
+            Index the object in the portal catalog.
+        """
         catalog = getToolByName(self, 'portal_catalog', None)
         if catalog is not None:
             catalog.indexObject(self)
 
     security.declareProtected(ModifyPortalContent, 'unindexObject')
     def unindexObject(self):
+        """
+            Unindex the object from the portal catalog.
+        """
         catalog = getToolByName(self, 'portal_catalog', None)
         if catalog is not None:
             catalog.unindexObject(self)
 
     security.declareProtected(ModifyPortalContent, 'reindexObject')
     def reindexObject(self, idxs=[]):
+        """
+            Reindex the object in the portal catalog.
+            If idxs is present, only those indexes are reindexed.
+            The metadata is always updated.
+
+            Also update the modification date of the object.
+        """
         if hasattr(aq_base(self), 'notifyModified'):
             # Update modification date.
             self.notifyModified()
@@ -49,56 +62,112 @@
         if catalog is not None:
             catalog.reindexObject(self, idxs=idxs)
 
+    security.declareProtected(ModifyPortalContent, 'reindexObjectSecurity')
+    def reindexObjectSecurity(self):
+        """
+            Reindex security-related indexes on the object
+            (and its descendants).
+        """
+        catalog = getToolByName(self, 'portal_catalog', None)
+        if catalog is not None:
+            path = '/'.join(self.getPhysicalPath())
+            for brain in catalog.searchResults(path=path):
+                ob = brain.getObject()
+                try: s = ob._p_changed
+                except: s = 0
+                catalog.reindexObject(ob, idxs=['allowedRolesAndUsers'])
+                if s is None: ob._p_deactivate()
+            # Reindex the object itself, as the PathIndex only gave us
+            # the descendants.
+            self.reindexObject(idxs=['allowedRolesAndUsers'])
+
+    # Workflow methods
+    # ----------------
+
+    security.declarePrivate('notifyWorkflowCreated')
+    def notifyWorkflowCreated(self):
+        """
+            Notify the workflow that self was just created.
+        """
+        wftool = getToolByName(self, 'portal_workflow', None)
+        if wftool is not None:
+            wftool.notifyCreated(self)
+
+    # Opaque subitems
+    # ---------------
+
+    security.declareProtected(AccessContentsInformation, 'opaqueItems')
+    def opaqueItems(self):
+        """
+            Return opaque items (subelements that are contained
+            using something that is not an ObjectManager).
+        """
+        # Since 'talkback' is the only opaque item on content
+        # right now, I will return that. Should be replaced with
+        # a list of tuples for every opaque item!
+        if hasattr(aq_base(self), 'talkback'):
+            talkback = self.talkback
+            if talkback is not None:
+                return ((talkback.id, talkback),)
+        return ()
+
+    security.declareProtected(AccessContentsInformation, 'opaqueIds')
+    def opaqueIds(self):
+        """
+            Return opaque ids (subelements that are contained
+            using something that is not an ObjectManager).
+        """
+        return [t[0] for t in self.opaqueItems()]
+
+    security.declareProtected(AccessContentsInformation, 'opaqueValues')
+    def opaqueValues(self):
+        """
+            Return opaque values (subelements that are contained
+            using something that is not an ObjectManager).
+        """
+        return [t[1] for t in self.opaqueItems()]
+
+    # Hooks
+    # -----
+
     def manage_afterAdd(self, item, container):
         """
             Add self to the catalog.
+            (Called when the object is created or moved.)
         """
-        #
-        #   Are we being added (or moved)?
-        #
         if aq_base(container) is not aq_base(self):
             self.indexObject()
-            # Recurse in opaque subitems (talkbacks for instance).
-            if hasattr(aq_base(self), 'opaqueValues'):
-                for subitem in self.opaqueValues():
-                    if hasattr(aq_base(subitem), 'manage_afterAdd'):
-                        subitem.manage_afterAdd(item, container)
+            self.__recurse('manage_afterAdd', item, container)
 
     def manage_afterClone(self, item):
         """
-            Add self to workflow, as we have just been cloned.
+            Add self to the workflow.
+            (Called when the object is cloned.)
         """
         self.notifyWorkflowCreated()
-        # Recurse in opaque subitems.
-        if hasattr(aq_base(self), 'opaqueValues'):
-            for subitem in self.opaqueValues():
-                if hasattr(aq_base(subitem), 'manage_afterClone'):
-                    subitem.manage_afterClone(item)
+        self.__recurse('manage_afterClone', item)
 
     def manage_beforeDelete(self, item, container):
         """
             Remove self from the catalog.
+            (Called when the object is deleted or moved.)
         """
-        #
-        #   Are we going away?
-        #
         if aq_base(container) is not aq_base(self):
+            self.__recurse('manage_beforeDelete', item, container)
             self.unindexObject()
-            # Recurse in opaque subitems.
-            if hasattr(aq_base(self), 'opaqueValues'):
-                for subitem in self.opaqueValues():
-                    if hasattr(aq_base(subitem), 'manage_beforeDelete'):
-                        subitem.manage_beforeDelete(item, container)
 
-    security.declarePrivate('notifyWorkflowCreated')
-    def notifyWorkflowCreated(self):
+    def __recurse(self, name, *args):
         """
-            Notify the workflow that self was just created.
+            Recurse in both normal and opaque subobjects.
         """
-        wftool = getToolByName(self, 'portal_workflow', None)
-        if wftool is not None:
-            wftool.notifyCreated(self)
-
+        values = self.objectValues()
+        opaque_values = self.opaqueValues()
+        for subobjects in values, opaque_values:
+            for ob in subobjects:
+                try: s = ob._p_changed
+                except: s = 0
+                if hasattr(aq_base(ob), name):
+                    getattr(ob, name)(*args)
+                if s is None: ob._p_deactivate()
 
 Globals.InitializeClass(CMFCatalogAware)
-


=== CMF/CMFCore/MembershipTool.py 1.23 => 1.24 ===
                     obj.manage_setLocalRoles( member_id, roles )
 
         if reindex:
-            self.reindexObjectSecurity(obj)
+            # It is assumed that all objects have the method
+            # reindexObjectSecurity, which is in CMFCatalogAware and
+            # thus PortalContent and PortalFolder.
+            obj.reindexObjectSecurity()
 
     security.declareProtected(CMFCorePermissions.View, 'deleteLocalRoles')
     def deleteLocalRoles( self, obj, member_ids, reindex=1 ):
@@ -383,32 +386,7 @@
             obj.manage_delLocalRoles( userids=member_ids )
 
         if reindex:
-            self.reindexObjectSecurity(obj)
-
-    # This is not in CMFCatalogAware because all catalogged objects
-    # are not necessarily CatalogAware, especially folders.
-    security.declareProtected(CMFCorePermissions.ModifyPortalContent,
-                              'reindexObjectSecurity')
-    def reindexObjectSecurity(self, obj):
-        """
-            Reindex security-related indexes on the object
-            (and its descendants).
-        """
-        catalog = getToolByName(self, 'portal_catalog', None)
-        if catalog is not None:
-            path = '/'.join(obj.getPhysicalPath())
-            for brain in catalog.searchResults(path=path):
-                ob = brain.getObject()
-                catalog.reindexObject(ob, idxs=['allowedRolesAndUsers'])
-
-            # We must also reindex the object itself, as the PathIndex
-            # only gave us the descendants. We have no way to do it
-            # reliably, and we don't want to reindex objects that
-            # weren't indexed in the first place. As a heuristic, check
-            # if the object has a reindexObject method, and use it.
-
-            if hasattr(aq_base(obj), 'reindexObject'):
-                obj.reindexObject(idxs=['allowedRolesAndUsers'])
+            obj.reindexObjectSecurity()
 
     security.declarePrivate('addMember')
     def addMember(self, id, password, roles, domains, properties=None):


=== CMF/CMFCore/PortalContent.py 1.35 => 1.36 ===
         '''
         return self()
 
-    # Methods to support items that might be stored in attributes
-    # unknown to the content object, such as the DiscussionItemContainer
-    # "talkback".
-
-    security.declareProtected(AccessContentsInformation, 'opaqueItems')
-    def opaqueItems(self):
-        """
-        Returns opaque items (subelements that are contained
-        using something that is not an ObjectManager).
-        """
-        # Since 'talkback' is the only opaque item on content
-        # right now, I will return that. Should be replaced with
-        # a list of tuples for every opaque item!
-        if hasattr(aq_base(self), 'talkback'):
-            talkback = self.talkback
-            if talkback is not None:
-                return ((talkback.id, talkback),)
-        return ()
-
-    security.declareProtected(AccessContentsInformation, 'opaqueIds')
-    def opaqueIds(self):
-        """
-        Returns opaque ids (subelements that are contained
-        using something that is not an ObjectManager).
-        """
-        return [t[0] for t in self.opaqueItems()]
-
-    security.declareProtected(AccessContentsInformation, 'opaqueValues')
-    def opaqueValues(self):
-        """
-        Returns opaque values (subelements that are contained
-        using something that is not an ObjectManager).
-        """
-        return [t[1] for t in self.opaqueItems()]
-
 InitializeClass(PortalContent)


=== CMF/CMFCore/PortalFolder.py 1.37 => 1.38 ===
 
 from CMFCorePermissions import View, ManageProperties, ListFolderContents
 from CMFCorePermissions import AddPortalFolders, AddPortalContent
+from CMFCatalogAware import CMFCatalogAware
 from OFS.Folder import Folder
 from OFS.ObjectManager import REPLACEABLE
 from Globals import DTMLFile
@@ -67,7 +68,7 @@
                            )
 
 
-class PortalFolder( Folder, DynamicType ):
+class PortalFolder(DynamicType, CMFCatalogAware, Folder):
     """
         Implements portal content management, but not UI details.
     """
@@ -270,10 +271,10 @@
         """
              Implement dublin core type
         """
-        portal_types = getToolByName(self, 'portal_types')
-        ti = portal_types.getTypeInfo(self)
-        if ti is not None:
-            return ti.Title()
+        if hasattr(aq_base(self), 'getTypeInfo'):
+            ti = self.getTypeInfo()
+            if ti is not None:
+                return ti.Title()
         return self.meta_type
 
     security.declarePublic('encodeFolderFilter')
@@ -305,10 +306,16 @@
         """
         return None
 
-    def reindexObject( self, idxs=[] ):
-        """
-            Make content-assuming factory mechanism happy.
-        """
+    # Ensure pure PortalFolders don't get cataloged.
+    # XXX We may want to revisit this.
+
+    def indexObject(self):
+        pass
+
+    def unindexObject(self):
+        pass
+
+    def reindexObject(self, idxs=[]):
         pass
 
     def PUT_factory( self, name, typ, body ):