Skip to content

Commit 6a1f39b

Browse files
committed
fixup! Use the dexterity machinery in api.content.create
1 parent 6f536b5 commit 6a1f39b

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

src/plone/api/content.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
from plone.app.linkintegrity.exceptions import LinkIntegrityNotificationException
1010
from plone.app.uuid.utils import uuidToObject
1111
from plone.dexterity.fti import DexterityFTI
12-
from plone.dexterity.utils import addContentToContainer
1312
from plone.dexterity.utils import createContent
1413
from plone.uuid.interfaces import IUUID
1514
from Products.CMFCore.DynamicType import DynamicType
@@ -76,6 +75,12 @@ def create(
7675
if isinstance(fti, DexterityFTI):
7776
# For dexterity objects we want to not use the invokeFactory
7877
# method because we want to have the id generated by the name chooser
78+
if not fti.isConstructionAllowed(container):
79+
raise ValueError(f"Cannot create {type}")
80+
81+
container_fti = container.getTypeInfo()
82+
if container_fti is not None and not container_fti.allowType(type):
83+
raise ValueError(f"Disallowed subobject type: {type}")
7984
constraints = IConstrainTypes(container, None)
8085
if constraints and fti not in constraints.allowedContentTypes():
8186
raise ValueError(
@@ -85,18 +90,23 @@ def create(
8590
kwargs["id"] = id
8691
content = createContent(type, **kwargs)
8792

88-
if not content.id:
89-
content.id = INameChooser(container).chooseName(title, content)
90-
if not safe_id:
91-
content.id = INameChooser(container).chooseName(
92-
content.id or title, content
93-
)
94-
if id and id != content.id:
95-
raise BadRequest(
96-
"The id you provided conflicts with an existing object or it is reserved"
97-
)
98-
addContentToContainer(container, content)
99-
content_id = content.id
93+
name_chooser = INameChooser(container)
94+
if content.id:
95+
# Check that the id we picked is valid
96+
if not name_chooser.checkName(content.id, content):
97+
if safe_id:
98+
content.id = INameChooser(container).chooseName(
99+
content.id, content
100+
)
101+
else:
102+
raise BadRequest(
103+
"The id you provided conflicts with "
104+
"an existing object or it is reserved"
105+
)
106+
else:
107+
content.id = name_chooser.chooseName(title, content)
108+
109+
content_id = container._setObject(content.id, content)
100110
else:
101111
content_id = not safe_id and id or str(random.randint(0, 99999999))
102112
container.invokeFactory(type, content_id, **kwargs)

src/plone/api/tests/test_content.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
from Acquisition import aq_base
44
from contextlib import AbstractContextManager
5-
from gc import callbacks
65
from OFS.CopySupport import CopyError
76
from OFS.event import ObjectWillBeMovedEvent
87
from OFS.interfaces import IObjectWillBeMovedEvent
@@ -14,7 +13,6 @@
1413
from plone.app.textfield import RichTextValue
1514
from plone.base.interfaces import INavigationRoot
1615
from plone.indexer import indexer
17-
from plone.namedfile import NamedBlobFile
1816
from plone.uuid.interfaces import IMutableUUID
1917
from plone.uuid.interfaces import IUUIDGenerator
2018
from Products.CMFCore.WorkflowCore import WorkflowException
@@ -381,6 +379,14 @@ def test_create_with_safe_id(self):
381379
self.assertEqual(second_page.id, "test-document-1")
382380
self.assertEqual(second_page.portal_type, "Document")
383381

382+
def test_create_with_not_lowercase_id(self):
383+
obj = api.content.create(
384+
container=self.portal,
385+
type="Dexterity Item",
386+
id="Doc1",
387+
)
388+
self.assertEqual(obj.id, "Doc1")
389+
384390
def test_create_raises_unicodedecodeerror(self):
385391
"""Test that the create method raises UnicodeDecodeErrors correctly."""
386392
site = getGlobalSiteManager()

0 commit comments

Comments
 (0)