Skip to content

Commit 03e4279

Browse files
committed
fixup! Use the dexterity machinery in api.content.create
1 parent 5bead9f commit 03e4279

2 files changed

Lines changed: 31 additions & 15 deletions

File tree

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.WorkflowCore import WorkflowException
@@ -69,6 +68,12 @@ def create(
6968
if isinstance(fti, DexterityFTI):
7069
# For dexterity objects we want to not use the invokeFactory
7170
# method because we want to have the id generated by the name chooser
71+
if not fti.isConstructionAllowed(container):
72+
raise ValueError(f"Cannot create {type}")
73+
74+
container_fti = container.getTypeInfo()
75+
if container_fti is not None and not container_fti.allowType(type):
76+
raise ValueError(f"Disallowed subobject type: {type}")
7277
constraints = IConstrainTypes(container, None)
7378
if constraints and fti not in constraints.allowedContentTypes():
7479
raise ValueError(
@@ -78,18 +83,23 @@ def create(
7883
kwargs["id"] = id
7984
content = createContent(type, **kwargs)
8085

81-
if not content.id:
82-
content.id = INameChooser(container).chooseName(title, content)
83-
if not safe_id:
84-
content.id = INameChooser(container).chooseName(
85-
content.id or title, content
86-
)
87-
if id and id != content.id:
88-
raise BadRequest(
89-
"The id you provided conflicts with an existing object or it is reserved"
90-
)
91-
addContentToContainer(container, content)
92-
content_id = content.id
86+
name_chooser = INameChooser(container)
87+
if content.id:
88+
# Check that the id we picked is valid
89+
if not name_chooser.checkName(content.id, content):
90+
if safe_id:
91+
content.id = INameChooser(container).chooseName(
92+
content.id, content
93+
)
94+
else:
95+
raise BadRequest(
96+
"The id you provided conflicts with "
97+
"an existing object or it is reserved"
98+
)
99+
else:
100+
content.id = name_chooser.chooseName(title, content)
101+
102+
content_id = container._setObject(content.id, content)
93103
else:
94104
content_id = not safe_id and id or str(random.randint(0, 99999999))
95105
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
@@ -13,7 +12,6 @@
1312
from plone.app.linkintegrity.exceptions import LinkIntegrityNotificationException
1413
from plone.app.textfield import RichTextValue
1514
from plone.indexer import indexer
16-
from plone.namedfile import NamedBlobFile
1715
from plone.uuid.interfaces import IMutableUUID
1816
from plone.uuid.interfaces import IUUIDGenerator
1917
from Products.CMFCore.interfaces import IContentish
@@ -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)