diff --git a/news/1875.bugfix b/news/1875.bugfix new file mode 100644 index 000000000..5ab79e6e4 --- /dev/null +++ b/news/1875.bugfix @@ -0,0 +1 @@ +Fixed block deserializers not running for control panel fields @JeffersonBledsoe \ No newline at end of file diff --git a/src/plone/restapi/deserializer/controlpanels/__init__.py b/src/plone/restapi/deserializer/controlpanels/__init__.py index e7f78d2e2..38409222a 100644 --- a/src/plone/restapi/deserializer/controlpanels/__init__.py +++ b/src/plone/restapi/deserializer/controlpanels/__init__.py @@ -15,8 +15,11 @@ from zope.schema import getFields from zope.schema.interfaces import ValidationError +from plone.restapi.behaviors import IBlocks +from Acquisition import ImplicitAcquisitionWrapper -@implementer(IDexterityContent) + +@implementer(IDexterityContent, IBlocks) class FakeDXContext: """Fake DX content class, so we can reuse the DX field deserializers""" @@ -47,6 +50,7 @@ def __call__(self, mask_validation_errors=True): # Make a fake context fake_context = FakeDXContext() + wrapped_context = ImplicitAcquisitionWrapper(fake_context, self.context) for name, field in getFields(self.schema).items(): field_data = schema_data.setdefault(self.schema, {}) @@ -56,7 +60,7 @@ def __call__(self, mask_validation_errors=True): if name in data: deserializer = queryMultiAdapter( - (field, fake_context, self.request), IFieldDeserializer + (field, wrapped_context, self.request), IFieldDeserializer ) try: diff --git a/src/plone/restapi/serializer/controlpanels/__init__.py b/src/plone/restapi/serializer/controlpanels/__init__.py index 86d377380..12fd0c468 100644 --- a/src/plone/restapi/serializer/controlpanels/__init__.py +++ b/src/plone/restapi/serializer/controlpanels/__init__.py @@ -1,5 +1,7 @@ +from Acquisition import ImplicitAcquisitionWrapper from plone.dexterity.interfaces import IDexterityContent from plone.registry.interfaces import IRegistry +from plone.restapi.behaviors import IBlocks from plone.restapi.controlpanels import IControlpanel from plone.restapi.interfaces import IFieldSerializer from plone.restapi.interfaces import ISerializeToJson @@ -18,6 +20,11 @@ SERVICE_ID = "@controlpanels" +# Same class is in deserializer. Should centralise it. +@implementer(IDexterityContent, IBlocks) +class FakeDXContext: + """Fake DX content class, so we can re-use the DX field deserializers""" + @implementer(ISerializeToJsonSummary) @adapter(IControlpanel) @@ -96,14 +103,22 @@ def __call__(self): proxy = self.registry.forInterface(self.schema, prefix=self.schema_prefix) - # Temporarily provide IDexterityContent, so we can use DX field - # serializers - alsoProvides(proxy, IDexterityContent) + # Make a fake context and copy registry values onto it + fake_context = FakeDXContext() + + + # Copy all field values from the proxy to the fake context + # so that field serializers can properly adapt the context + for name in zope.schema.getFields(self.schema).keys(): + setattr(fake_context, name, getattr(proxy, name, None)) + alsoProvides(fake_context, self.schema) + + wrapped_context = ImplicitAcquisitionWrapper(fake_context, self.controlpanel.context) json_data = {} for name, field in zope.schema.getFields(self.schema).items(): serializer = queryMultiAdapter( - (field, proxy, self.controlpanel.request), IFieldSerializer + (field, wrapped_context, self.controlpanel.request), IFieldSerializer ) if serializer: value = serializer()