We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Un-remove IContentish from site root class
On https://github.com/plone/Products.CMFPlone/blob/016459fd9d023017e9dc0a0b635bd66099826db1/Products/CMFPlone/Portal.py#L214 I remove IContentish, because having it broke tests and setup code in places that I didn't feel like touching.

Nowadays we have some test failures because of the removal. See https://github.com/plone/plone.restapi/pull/1674#issuecomment-1664193927 for additional details, but suffice to say that `conversation_view` is expected to exist on the site root, but isn't because it's bound to `IContentish`.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `Products/CMFPlone/Portal.py`
Content:
```
1 from AccessControl import ClassSecurityInfo
2 from AccessControl import Unauthorized
3 from AccessControl.class_init import InitializeClass
4 from Acquisition import aq_base
5 from ComputedAttribute import ComputedAttribute
6 from five.localsitemanager.registry import PersistentComponents
7 from OFS.ObjectManager import REPLACEABLE
8 from plone.base.interfaces.siteroot import IPloneSiteRoot
9 from plone.base.interfaces.syndication import ISyndicatable
10 from plone.base.permissions import AddPortalContent
11 from plone.base.permissions import AddPortalFolders
12 from plone.base.permissions import ListPortalMembers
13 from plone.base.permissions import ModifyPortalContent
14 from plone.base.permissions import ReplyToItem
15 from plone.base.permissions import View
16 from plone.dexterity.content import Container
17 from Products.CMFCore import permissions
18 from Products.CMFCore.interfaces import IContentish
19 from Products.CMFCore.interfaces import ISiteRoot
20 from Products.CMFCore.permissions import AccessContentsInformation
21 from Products.CMFCore.permissions import AddPortalMember
22 from Products.CMFCore.permissions import MailForgottenPassword
23 from Products.CMFCore.permissions import RequestReview
24 from Products.CMFCore.permissions import ReviewPortalContent
25 from Products.CMFCore.permissions import SetOwnPassword
26 from Products.CMFCore.permissions import SetOwnProperties
27 from Products.CMFCore.PortalFolder import PortalFolderBase
28 from Products.CMFCore.PortalObject import PortalObjectBase
29 from Products.CMFCore.Skinnable import SkinnableObjectManager
30 from Products.CMFCore.utils import _checkPermission
31 from Products.CMFCore.utils import getToolByName
32 from Products.CMFPlone import bbb
33 from Products.Five.component.interfaces import IObjectManagerSite
34 from zope.event import notify
35 from zope.interface import classImplementsOnly
36 from zope.interface import implementedBy
37 from zope.interface import implementer
38 from zope.interface.interfaces import ComponentLookupError
39 from zope.traversing.interfaces import BeforeTraverseEvent
40 
41 
42 if bbb.HAS_ZSERVER:
43     from webdav.NullResource import NullResource
44 
45 
46 @implementer(IPloneSiteRoot, ISiteRoot, ISyndicatable, IObjectManagerSite)
47 class PloneSite(Container, SkinnableObjectManager):
48     """The Plone site object."""
49 
50     security = ClassSecurityInfo()
51     meta_type = portal_type = "Plone Site"
52 
53     # Ensure certain attributes come from the correct base class.
54     _checkId = SkinnableObjectManager._checkId
55     manage_main = PortalFolderBase.manage_main
56 
57     def __getattr__(self, name):
58         try:
59             # Try DX
60             return super().__getattr__(name)
61         except AttributeError:
62             # Check portal_skins
63             return SkinnableObjectManager.__getattr__(self, name)
64 
65     def __setattr__(self, name, obj):
66         # handle re setting an item as an attribute
67         if self._tree is not None and name in self:
68             del self[name]
69             self[name] = obj
70         else:
71             super().__setattr__(name, obj)
72 
73     def __delattr__(self, name):
74         try:
75             return super().__delattr__(name)
76         except AttributeError:
77             return self.__delitem__(name)
78 
79     # Removes the 'Components Folder'
80 
81     manage_options = Container.manage_options[:2] + Container.manage_options[3:]
82 
83     __ac_permissions__ = (
84         (AccessContentsInformation, ()),
85         (AddPortalMember, ()),
86         (SetOwnPassword, ()),
87         (SetOwnProperties, ()),
88         (MailForgottenPassword, ()),
89         (RequestReview, ()),
90         (ReviewPortalContent, ()),
91         (AddPortalContent, ()),
92         (AddPortalFolders, ()),
93         (ListPortalMembers, ()),
94         (ReplyToItem, ()),
95         (View, ("isEffective",)),
96         (
97             ModifyPortalContent,
98             (
99                 "manage_cutObjects",
100                 "manage_pasteObjects",
101                 "manage_renameForm",
102                 "manage_renameObject",
103                 "manage_renameObjects",
104             ),
105         ),
106     )
107 
108     # Switch off ZMI ordering interface as it assumes a slightly
109     # different functionality
110     has_order_support = 0
111     management_page_charset = "utf-8"
112     _default_sort_key = "id"
113     _properties = (
114         {"id": "title", "type": "string", "mode": "w"},
115         {"id": "description", "type": "text", "mode": "w"},
116     )
117     title = ""
118     description = ""
119     icon = "misc_/CMFPlone/tool.gif"
120 
121     # From PortalObjectBase
122     def __init__(self, id, title=""):
123         super().__init__(id, title=title)
124         components = PersistentComponents("++etc++site")
125         components.__parent__ = self
126         self.setSiteManager(components)
127 
128     # From PortalObjectBase
129     def __before_publishing_traverse__(self, arg1, arg2=None):
130         """Pre-traversal hook."""
131         # XXX hack around a bug(?) in BeforeTraverse.MultiHook
132         REQUEST = arg2 or arg1
133 
134         try:
135             notify(BeforeTraverseEvent(self, REQUEST))
136         except ComponentLookupError:
137             # allow ZMI access, even if the portal's site manager is missing
138             pass
139         self.setupCurrentSkin(REQUEST)
140 
141         super().__before_publishing_traverse__(arg1, arg2)
142 
143     # Concept from OFS.OrderSupport
144     @security.protected(permissions.AccessContentsInformation)
145     def tpValues(self):
146         # Return a list of subobjects, used by ZMI tree tag (and only there).
147         # see also https://github.com/plone/Products.CMFPlone/issues/3323
148         return sorted(
149             (
150                 obj
151                 for obj in self.objectValues()
152                 if getattr(aq_base(obj), "isPrincipiaFolderish", False)
153             ),
154             key=lambda obj: obj.getId(),
155         )
156 
157     def __browser_default__(self, request):
158         """Set default so we can return whatever we want instead
159         of index_html"""
160         return getToolByName(self, "plone_utils").browserDefault(self)
161 
162     def index_html(self):
163         """Acquire if not present."""
164         request = getattr(self, "REQUEST", None)
165         if (
166             request is not None
167             and "REQUEST_METHOD" in request
168             and request.maybe_webdav_client
169         ):
170             method = request["REQUEST_METHOD"]
171             if bbb.HAS_ZSERVER and method in ("PUT",):
172                 # Very likely a WebDAV client trying to create something
173                 result = NullResource(self, "index_html")
174                 setattr(result, "__replaceable__", REPLACEABLE)
175                 return result
176             elif method not in ("GET", "HEAD", "POST"):
177                 raise AttributeError("index_html")
178         # Acquire from skin.
179         _target = self.__getattr__("index_html")
180         result = aq_base(_target).__of__(self)
181         setattr(result, "__replaceable__", REPLACEABLE)
182         return result
183 
184     index_html = ComputedAttribute(index_html, 1)
185 
186     def manage_beforeDelete(self, container, item):
187         # Should send out an Event before Site is being deleted.
188         self.removal_inprogress = 1
189         PloneSite.inheritedAttribute("manage_beforeDelete")(self, container, item)
190 
191     @security.protected(permissions.DeleteObjects)
192     def manage_delObjects(self, ids=None, REQUEST=None):
193         """We need to enforce security."""
194         if ids is None:
195             ids = []
196         if isinstance(ids, str):
197             ids = [ids]
198         for id in ids:
199             item = self._getOb(id)
200             if not _checkPermission(permissions.DeleteObjects, item):
201                 raise Unauthorized("Do not have permissions to remove this object")
202         return PortalObjectBase.manage_delObjects(self, ids, REQUEST=REQUEST)
203 
204     def view(self):
205         """Ensure that we get a plain view of the object, via a delegation to
206         __call__(), which is defined in BrowserDefaultMixin
207         """
208         return self()
209 
210     @security.protected(permissions.AccessContentsInformation)
211     def folderlistingFolderContents(self, contentFilter=None):
212         """Calls listFolderContents in protected only by ACI so that
213         folder_listing can work without the List folder contents permission.
214 
215         This is copied from Archetypes Basefolder and is needed by the
216         reference browser.
217         """
218         return self.listFolderContents(contentFilter)
219 
220     def isEffective(self, date):
221         # Override DefaultDublinCoreImpl's test, since we are always viewable.
222         return 1
223 
224 
225 # Remove the IContentish interface so we don't listen to events that won't
226 # apply to the site root, ie handleUidAnnotationEvent
227 classImplementsOnly(PloneSite, implementedBy(PloneSite) - IContentish)
228 
229 InitializeClass(PloneSite)
230
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/Products/CMFPlone/Portal.py b/Products/CMFPlone/Portal.py
--- a/Products/CMFPlone/Portal.py
+++ b/Products/CMFPlone/Portal.py
@@ -15,7 +15,6 @@
 from plone.base.permissions import View
 from plone.dexterity.content import Container
 from Products.CMFCore import permissions
-from Products.CMFCore.interfaces import IContentish
 from Products.CMFCore.interfaces import ISiteRoot
 from Products.CMFCore.permissions import AccessContentsInformation
 from Products.CMFCore.permissions import AddPortalMember
@@ -32,8 +31,6 @@
 from Products.CMFPlone import bbb
 from Products.Five.component.interfaces import IObjectManagerSite
 from zope.event import notify
-from zope.interface import classImplementsOnly
-from zope.interface import implementedBy
 from zope.interface import implementer
 from zope.interface.interfaces import ComponentLookupError
 from zope.traversing.interfaces import BeforeTraverseEvent
@@ -222,8 +219,4 @@
         return 1
 
 
-# Remove the IContentish interface so we don't listen to events that won't
-# apply to the site root, ie handleUidAnnotationEvent
-classImplementsOnly(PloneSite, implementedBy(PloneSite) - IContentish)
-
 InitializeClass(PloneSite)

{"golden_diff": "diff --git a/Products/CMFPlone/Portal.py b/Products/CMFPlone/Portal.py\n--- a/Products/CMFPlone/Portal.py\n+++ b/Products/CMFPlone/Portal.py\n@@ -15,7 +15,6 @@\n from plone.base.permissions import View\n from plone.dexterity.content import Container\n from Products.CMFCore import permissions\n-from Products.CMFCore.interfaces import IContentish\n from Products.CMFCore.interfaces import ISiteRoot\n from Products.CMFCore.permissions import AccessContentsInformation\n from Products.CMFCore.permissions import AddPortalMember\n@@ -32,8 +31,6 @@\n from Products.CMFPlone import bbb\n from Products.Five.component.interfaces import IObjectManagerSite\n from zope.event import notify\n-from zope.interface import classImplementsOnly\n-from zope.interface import implementedBy\n from zope.interface import implementer\n from zope.interface.interfaces import ComponentLookupError\n from zope.traversing.interfaces import BeforeTraverseEvent\n@@ -222,8 +219,4 @@\n         return 1\n \n \n-# Remove the IContentish interface so we don't listen to events that won't\n-# apply to the site root, ie handleUidAnnotationEvent\n-classImplementsOnly(PloneSite, implementedBy(PloneSite) - IContentish)\n-\n InitializeClass(PloneSite)\n", "issue": "Un-remove IContentish from site root class\nOn https://github.com/plone/Products.CMFPlone/blob/016459fd9d023017e9dc0a0b635bd66099826db1/Products/CMFPlone/Portal.py#L214 I remove IContentish, because having it broke tests and setup code in places that I didn't feel like touching.\r\n\r\nNowadays we have some test failures because of the removal. See https://github.com/plone/plone.restapi/pull/1674#issuecomment-1664193927 for additional details, but suffice to say that `conversation_view` is expected to exist on the site root, but isn't because it's bound to `IContentish`.\n", "before_files": [{"content": "from AccessControl import ClassSecurityInfo\nfrom AccessControl import Unauthorized\nfrom AccessControl.class_init import InitializeClass\nfrom Acquisition import aq_base\nfrom ComputedAttribute import ComputedAttribute\nfrom five.localsitemanager.registry import PersistentComponents\nfrom OFS.ObjectManager import REPLACEABLE\nfrom plone.base.interfaces.siteroot import IPloneSiteRoot\nfrom plone.base.interfaces.syndication import ISyndicatable\nfrom plone.base.permissions import AddPortalContent\nfrom plone.base.permissions import AddPortalFolders\nfrom plone.base.permissions import ListPortalMembers\nfrom plone.base.permissions import ModifyPortalContent\nfrom plone.base.permissions import ReplyToItem\nfrom plone.base.permissions import View\nfrom plone.dexterity.content import Container\nfrom Products.CMFCore import permissions\nfrom Products.CMFCore.interfaces import IContentish\nfrom Products.CMFCore.interfaces import ISiteRoot\nfrom Products.CMFCore.permissions import AccessContentsInformation\nfrom Products.CMFCore.permissions import AddPortalMember\nfrom Products.CMFCore.permissions import MailForgottenPassword\nfrom Products.CMFCore.permissions import RequestReview\nfrom Products.CMFCore.permissions import ReviewPortalContent\nfrom Products.CMFCore.permissions import SetOwnPassword\nfrom Products.CMFCore.permissions import SetOwnProperties\nfrom Products.CMFCore.PortalFolder import PortalFolderBase\nfrom Products.CMFCore.PortalObject import PortalObjectBase\nfrom Products.CMFCore.Skinnable import SkinnableObjectManager\nfrom Products.CMFCore.utils import _checkPermission\nfrom Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import bbb\nfrom Products.Five.component.interfaces import IObjectManagerSite\nfrom zope.event import notify\nfrom zope.interface import classImplementsOnly\nfrom zope.interface import implementedBy\nfrom zope.interface import implementer\nfrom zope.interface.interfaces import ComponentLookupError\nfrom zope.traversing.interfaces import BeforeTraverseEvent\n\n\nif bbb.HAS_ZSERVER:\n    from webdav.NullResource import NullResource\n\n\n@implementer(IPloneSiteRoot, ISiteRoot, ISyndicatable, IObjectManagerSite)\nclass PloneSite(Container, SkinnableObjectManager):\n    \"\"\"The Plone site object.\"\"\"\n\n    security = ClassSecurityInfo()\n    meta_type = portal_type = \"Plone Site\"\n\n    # Ensure certain attributes come from the correct base class.\n    _checkId = SkinnableObjectManager._checkId\n    manage_main = PortalFolderBase.manage_main\n\n    def __getattr__(self, name):\n        try:\n            # Try DX\n            return super().__getattr__(name)\n        except AttributeError:\n            # Check portal_skins\n            return SkinnableObjectManager.__getattr__(self, name)\n\n    def __setattr__(self, name, obj):\n        # handle re setting an item as an attribute\n        if self._tree is not None and name in self:\n            del self[name]\n            self[name] = obj\n        else:\n            super().__setattr__(name, obj)\n\n    def __delattr__(self, name):\n        try:\n            return super().__delattr__(name)\n        except AttributeError:\n            return self.__delitem__(name)\n\n    # Removes the 'Components Folder'\n\n    manage_options = Container.manage_options[:2] + Container.manage_options[3:]\n\n    __ac_permissions__ = (\n        (AccessContentsInformation, ()),\n        (AddPortalMember, ()),\n        (SetOwnPassword, ()),\n        (SetOwnProperties, ()),\n        (MailForgottenPassword, ()),\n        (RequestReview, ()),\n        (ReviewPortalContent, ()),\n        (AddPortalContent, ()),\n        (AddPortalFolders, ()),\n        (ListPortalMembers, ()),\n        (ReplyToItem, ()),\n        (View, (\"isEffective\",)),\n        (\n            ModifyPortalContent,\n            (\n                \"manage_cutObjects\",\n                \"manage_pasteObjects\",\n                \"manage_renameForm\",\n                \"manage_renameObject\",\n                \"manage_renameObjects\",\n            ),\n        ),\n    )\n\n    # Switch off ZMI ordering interface as it assumes a slightly\n    # different functionality\n    has_order_support = 0\n    management_page_charset = \"utf-8\"\n    _default_sort_key = \"id\"\n    _properties = (\n        {\"id\": \"title\", \"type\": \"string\", \"mode\": \"w\"},\n        {\"id\": \"description\", \"type\": \"text\", \"mode\": \"w\"},\n    )\n    title = \"\"\n    description = \"\"\n    icon = \"misc_/CMFPlone/tool.gif\"\n\n    # From PortalObjectBase\n    def __init__(self, id, title=\"\"):\n        super().__init__(id, title=title)\n        components = PersistentComponents(\"++etc++site\")\n        components.__parent__ = self\n        self.setSiteManager(components)\n\n    # From PortalObjectBase\n    def __before_publishing_traverse__(self, arg1, arg2=None):\n        \"\"\"Pre-traversal hook.\"\"\"\n        # XXX hack around a bug(?) in BeforeTraverse.MultiHook\n        REQUEST = arg2 or arg1\n\n        try:\n            notify(BeforeTraverseEvent(self, REQUEST))\n        except ComponentLookupError:\n            # allow ZMI access, even if the portal's site manager is missing\n            pass\n        self.setupCurrentSkin(REQUEST)\n\n        super().__before_publishing_traverse__(arg1, arg2)\n\n    # Concept from OFS.OrderSupport\n    @security.protected(permissions.AccessContentsInformation)\n    def tpValues(self):\n        # Return a list of subobjects, used by ZMI tree tag (and only there).\n        # see also https://github.com/plone/Products.CMFPlone/issues/3323\n        return sorted(\n            (\n                obj\n                for obj in self.objectValues()\n                if getattr(aq_base(obj), \"isPrincipiaFolderish\", False)\n            ),\n            key=lambda obj: obj.getId(),\n        )\n\n    def __browser_default__(self, request):\n        \"\"\"Set default so we can return whatever we want instead\n        of index_html\"\"\"\n        return getToolByName(self, \"plone_utils\").browserDefault(self)\n\n    def index_html(self):\n        \"\"\"Acquire if not present.\"\"\"\n        request = getattr(self, \"REQUEST\", None)\n        if (\n            request is not None\n            and \"REQUEST_METHOD\" in request\n            and request.maybe_webdav_client\n        ):\n            method = request[\"REQUEST_METHOD\"]\n            if bbb.HAS_ZSERVER and method in (\"PUT\",):\n                # Very likely a WebDAV client trying to create something\n                result = NullResource(self, \"index_html\")\n                setattr(result, \"__replaceable__\", REPLACEABLE)\n                return result\n            elif method not in (\"GET\", \"HEAD\", \"POST\"):\n                raise AttributeError(\"index_html\")\n        # Acquire from skin.\n        _target = self.__getattr__(\"index_html\")\n        result = aq_base(_target).__of__(self)\n        setattr(result, \"__replaceable__\", REPLACEABLE)\n        return result\n\n    index_html = ComputedAttribute(index_html, 1)\n\n    def manage_beforeDelete(self, container, item):\n        # Should send out an Event before Site is being deleted.\n        self.removal_inprogress = 1\n        PloneSite.inheritedAttribute(\"manage_beforeDelete\")(self, container, item)\n\n    @security.protected(permissions.DeleteObjects)\n    def manage_delObjects(self, ids=None, REQUEST=None):\n        \"\"\"We need to enforce security.\"\"\"\n        if ids is None:\n            ids = []\n        if isinstance(ids, str):\n            ids = [ids]\n        for id in ids:\n            item = self._getOb(id)\n            if not _checkPermission(permissions.DeleteObjects, item):\n                raise Unauthorized(\"Do not have permissions to remove this object\")\n        return PortalObjectBase.manage_delObjects(self, ids, REQUEST=REQUEST)\n\n    def view(self):\n        \"\"\"Ensure that we get a plain view of the object, via a delegation to\n        __call__(), which is defined in BrowserDefaultMixin\n        \"\"\"\n        return self()\n\n    @security.protected(permissions.AccessContentsInformation)\n    def folderlistingFolderContents(self, contentFilter=None):\n        \"\"\"Calls listFolderContents in protected only by ACI so that\n        folder_listing can work without the List folder contents permission.\n\n        This is copied from Archetypes Basefolder and is needed by the\n        reference browser.\n        \"\"\"\n        return self.listFolderContents(contentFilter)\n\n    def isEffective(self, date):\n        # Override DefaultDublinCoreImpl's test, since we are always viewable.\n        return 1\n\n\n# Remove the IContentish interface so we don't listen to events that won't\n# apply to the site root, ie handleUidAnnotationEvent\nclassImplementsOnly(PloneSite, implementedBy(PloneSite) - IContentish)\n\nInitializeClass(PloneSite)\n", "path": "Products/CMFPlone/Portal.py"}], "after_files": [{"content": "from AccessControl import ClassSecurityInfo\nfrom AccessControl import Unauthorized\nfrom AccessControl.class_init import InitializeClass\nfrom Acquisition import aq_base\nfrom ComputedAttribute import ComputedAttribute\nfrom five.localsitemanager.registry import PersistentComponents\nfrom OFS.ObjectManager import REPLACEABLE\nfrom plone.base.interfaces.siteroot import IPloneSiteRoot\nfrom plone.base.interfaces.syndication import ISyndicatable\nfrom plone.base.permissions import AddPortalContent\nfrom plone.base.permissions import AddPortalFolders\nfrom plone.base.permissions import ListPortalMembers\nfrom plone.base.permissions import ModifyPortalContent\nfrom plone.base.permissions import ReplyToItem\nfrom plone.base.permissions import View\nfrom plone.dexterity.content import Container\nfrom Products.CMFCore import permissions\nfrom Products.CMFCore.interfaces import ISiteRoot\nfrom Products.CMFCore.permissions import AccessContentsInformation\nfrom Products.CMFCore.permissions import AddPortalMember\nfrom Products.CMFCore.permissions import MailForgottenPassword\nfrom Products.CMFCore.permissions import RequestReview\nfrom Products.CMFCore.permissions import ReviewPortalContent\nfrom Products.CMFCore.permissions import SetOwnPassword\nfrom Products.CMFCore.permissions import SetOwnProperties\nfrom Products.CMFCore.PortalFolder import PortalFolderBase\nfrom Products.CMFCore.PortalObject import PortalObjectBase\nfrom Products.CMFCore.Skinnable import SkinnableObjectManager\nfrom Products.CMFCore.utils import _checkPermission\nfrom Products.CMFCore.utils import getToolByName\nfrom Products.CMFPlone import bbb\nfrom Products.Five.component.interfaces import IObjectManagerSite\nfrom zope.event import notify\nfrom zope.interface import implementer\nfrom zope.interface.interfaces import ComponentLookupError\nfrom zope.traversing.interfaces import BeforeTraverseEvent\n\n\nif bbb.HAS_ZSERVER:\n    from webdav.NullResource import NullResource\n\n\n@implementer(IPloneSiteRoot, ISiteRoot, ISyndicatable, IObjectManagerSite)\nclass PloneSite(Container, SkinnableObjectManager):\n    \"\"\"The Plone site object.\"\"\"\n\n    security = ClassSecurityInfo()\n    meta_type = portal_type = \"Plone Site\"\n\n    # Ensure certain attributes come from the correct base class.\n    _checkId = SkinnableObjectManager._checkId\n    manage_main = PortalFolderBase.manage_main\n\n    def __getattr__(self, name):\n        try:\n            # Try DX\n            return super().__getattr__(name)\n        except AttributeError:\n            # Check portal_skins\n            return SkinnableObjectManager.__getattr__(self, name)\n\n    def __setattr__(self, name, obj):\n        # handle re setting an item as an attribute\n        if self._tree is not None and name in self:\n            del self[name]\n            self[name] = obj\n        else:\n            super().__setattr__(name, obj)\n\n    def __delattr__(self, name):\n        try:\n            return super().__delattr__(name)\n        except AttributeError:\n            return self.__delitem__(name)\n\n    # Removes the 'Components Folder'\n\n    manage_options = Container.manage_options[:2] + Container.manage_options[3:]\n\n    __ac_permissions__ = (\n        (AccessContentsInformation, ()),\n        (AddPortalMember, ()),\n        (SetOwnPassword, ()),\n        (SetOwnProperties, ()),\n        (MailForgottenPassword, ()),\n        (RequestReview, ()),\n        (ReviewPortalContent, ()),\n        (AddPortalContent, ()),\n        (AddPortalFolders, ()),\n        (ListPortalMembers, ()),\n        (ReplyToItem, ()),\n        (View, (\"isEffective\",)),\n        (\n            ModifyPortalContent,\n            (\n                \"manage_cutObjects\",\n                \"manage_pasteObjects\",\n                \"manage_renameForm\",\n                \"manage_renameObject\",\n                \"manage_renameObjects\",\n            ),\n        ),\n    )\n\n    # Switch off ZMI ordering interface as it assumes a slightly\n    # different functionality\n    has_order_support = 0\n    management_page_charset = \"utf-8\"\n    _default_sort_key = \"id\"\n    _properties = (\n        {\"id\": \"title\", \"type\": \"string\", \"mode\": \"w\"},\n        {\"id\": \"description\", \"type\": \"text\", \"mode\": \"w\"},\n    )\n    title = \"\"\n    description = \"\"\n    icon = \"misc_/CMFPlone/tool.gif\"\n\n    # From PortalObjectBase\n    def __init__(self, id, title=\"\"):\n        super().__init__(id, title=title)\n        components = PersistentComponents(\"++etc++site\")\n        components.__parent__ = self\n        self.setSiteManager(components)\n\n    # From PortalObjectBase\n    def __before_publishing_traverse__(self, arg1, arg2=None):\n        \"\"\"Pre-traversal hook.\"\"\"\n        # XXX hack around a bug(?) in BeforeTraverse.MultiHook\n        REQUEST = arg2 or arg1\n\n        try:\n            notify(BeforeTraverseEvent(self, REQUEST))\n        except ComponentLookupError:\n            # allow ZMI access, even if the portal's site manager is missing\n            pass\n        self.setupCurrentSkin(REQUEST)\n\n        super().__before_publishing_traverse__(arg1, arg2)\n\n    # Concept from OFS.OrderSupport\n    @security.protected(permissions.AccessContentsInformation)\n    def tpValues(self):\n        # Return a list of subobjects, used by ZMI tree tag (and only there).\n        # see also https://github.com/plone/Products.CMFPlone/issues/3323\n        return sorted(\n            (\n                obj\n                for obj in self.objectValues()\n                if getattr(aq_base(obj), \"isPrincipiaFolderish\", False)\n            ),\n            key=lambda obj: obj.getId(),\n        )\n\n    def __browser_default__(self, request):\n        \"\"\"Set default so we can return whatever we want instead\n        of index_html\"\"\"\n        return getToolByName(self, \"plone_utils\").browserDefault(self)\n\n    def index_html(self):\n        \"\"\"Acquire if not present.\"\"\"\n        request = getattr(self, \"REQUEST\", None)\n        if (\n            request is not None\n            and \"REQUEST_METHOD\" in request\n            and request.maybe_webdav_client\n        ):\n            method = request[\"REQUEST_METHOD\"]\n            if bbb.HAS_ZSERVER and method in (\"PUT\",):\n                # Very likely a WebDAV client trying to create something\n                result = NullResource(self, \"index_html\")\n                setattr(result, \"__replaceable__\", REPLACEABLE)\n                return result\n            elif method not in (\"GET\", \"HEAD\", \"POST\"):\n                raise AttributeError(\"index_html\")\n        # Acquire from skin.\n        _target = self.__getattr__(\"index_html\")\n        result = aq_base(_target).__of__(self)\n        setattr(result, \"__replaceable__\", REPLACEABLE)\n        return result\n\n    index_html = ComputedAttribute(index_html, 1)\n\n    def manage_beforeDelete(self, container, item):\n        # Should send out an Event before Site is being deleted.\n        self.removal_inprogress = 1\n        PloneSite.inheritedAttribute(\"manage_beforeDelete\")(self, container, item)\n\n    @security.protected(permissions.DeleteObjects)\n    def manage_delObjects(self, ids=None, REQUEST=None):\n        \"\"\"We need to enforce security.\"\"\"\n        if ids is None:\n            ids = []\n        if isinstance(ids, str):\n            ids = [ids]\n        for id in ids:\n            item = self._getOb(id)\n            if not _checkPermission(permissions.DeleteObjects, item):\n                raise Unauthorized(\"Do not have permissions to remove this object\")\n        return PortalObjectBase.manage_delObjects(self, ids, REQUEST=REQUEST)\n\n    def view(self):\n        \"\"\"Ensure that we get a plain view of the object, via a delegation to\n        __call__(), which is defined in BrowserDefaultMixin\n        \"\"\"\n        return self()\n\n    @security.protected(permissions.AccessContentsInformation)\n    def folderlistingFolderContents(self, contentFilter=None):\n        \"\"\"Calls listFolderContents in protected only by ACI so that\n        folder_listing can work without the List folder contents permission.\n\n        This is copied from Archetypes Basefolder and is needed by the\n        reference browser.\n        \"\"\"\n        return self.listFolderContents(contentFilter)\n\n    def isEffective(self, date):\n        # Override DefaultDublinCoreImpl's test, since we are always viewable.\n        return 1\n\n\nInitializeClass(PloneSite)\n", "path": "Products/CMFPlone/Portal.py"}]}