Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions news/4278.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Allow to create content with `index_html` id on the site root.

The portal root has a `index_html` method which prevented content with the id
`index_html` to be created and used as a default page.

Fixes: https://github.com/plone/Products.CMFPlone/issues/4278

@thet
55 changes: 55 additions & 0 deletions src/plone/base/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,58 @@ def test_is_truthy(self):
self.assertFalse(is_truthy("NO"))
self.assertFalse(is_truthy("no"))
self.assertFalse(is_truthy("foo"))

def test_check_for_collision(self):
from plone.base.utils import _check_for_collision

class Container(dict):
def __getattribute__(self, name):
if name in self:
return self[name]
return object.__getattribute__(self, name)

def portal_type(self):
"""Necessary to fulfill protocol."""

def index_html(self):
"""Common attribute - content with id index_html should be
addable."""

def some_attr(self):
"""Random attribute - content with id some_attr should not be
addable."""

container = Container()
container["test"] = Container()

# "test" is already taken
self.assertIn(
"There is already an item named",
_check_for_collision(container, "test"),
)

# "tiptop" is not yet taken
self.assertEqual(
_check_for_collision(container, "tiptop"),
None,
)

# "index_html" is not yet taken
self.assertEqual(
_check_for_collision(container, "index_html"),
None,
)

container["index_html"] = Container()

# `False` as "index_html" is now taken
self.assertIn(
"There is already an item named",
_check_for_collision(container, "index_html"),
)

# Content ids are not addable, if the id is an container attribute.
self.assertIn(
"is reserved",
_check_for_collision(container, "some_attr"),
)
7 changes: 4 additions & 3 deletions src/plone/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,10 @@ def _check_for_collision(contained_by, cid, **kwargs):
mapping={"name": cid},
)

if cid == "index_html":
# always allow index_html
return

# containers may have a field / attribute of the same name
if base_hasattr(contained_by, cid):
return _("${name} is reserved.", mapping={"name": cid})
Expand Down Expand Up @@ -533,9 +537,6 @@ def _check_for_collision(contained_by, cid, **kwargs):
# However, we do want to allow overriding of *content* in the object's
# parent path, including the portal root.

if cid == "index_html":
# always allow index_html
return
portal = getSite()
if portal and cid in portal.contentIds():
# Fine to use the same id as a *content* item from the root.
Expand Down