Problem/Motivation
Some format encoders/decoders from Core are not detected by the Serialize and Unserialize actions (from the ECA Render module) when populating the options in the action configuration form.
This makes it difficult to select certain formats e.g. XML.
This is caused by the code in \Drupal\eca_render\Plugin\Action\Serialize::buildConfigurationForm
, where the available format encoders are collected by checking for a FORMAT
class constant, which may not exist in some encoders. See code snippet.
$format_options = [];
// Need to fetch available formats from the protected properties of
// the serialization service. This is an ugly approach, but the only one
// that is available. It is a valid approach since it's declared as
// a "public" API.
// @see \Drupal\serialization\RegisterSerializationClassesCompilerPass::process()
$encoders = (function () {
return (function () {
// @phpstan-ignore-next-line
return $this->encoders;
// @phpstan-ignore-next-line
})(...)->call($this->encoder);
})(...)->call($this->serializer);
foreach ($encoders as $encoder) {
$constant_name = get_class($encoder) . '::FORMAT';
if (defined($constant_name)) {
$format_options[constant($constant_name)] = constant($constant_name);
}
}
For example, the Drupal Core Serialization XML encoder \Drupal\serialization\Encoder\XmlEncoder
is not a subclass of the Symfony XmlEncoder
; it is implemented as a wrapper class instead. Hence, it doesn't follow the Symfony convention of having a FORMAT
constant. See code snippet.
/**
* Adds XML support for serializer.
*
* This acts as a wrapper class for Symfony's XmlEncoder so that it is not
* implementing NormalizationAwareInterface, and can be normalized externally.
*
* @internal
* This encoder should not be used directly. Rather, use the `serializer`
* service.
*/
class XmlEncoder implements SerializerAwareInterface, EncoderInterface, DecoderInterface {
Steps to reproduce
- On a fresh Drupal 10.x OR 11.x site, enable the modules REST, Serialization, ECA, ECA Render
- Create a new ECA flow
- Add "ECA Render: Unserialize" action to the ECA flow
- In the action configuration form, under the "format" option, note that only "json" or "defined by token" is selectable.
- Create a view, add a REST export display to the view.
- Note that Under the "Serializer" settings in the REST export view display, the formats "json" AND "xml" can be selected.
Proposed resolution
Use the same method that the core REST export views uses to detect serializer formats.
Specifically, in \Drupal\rest\Plugin\views\display\RestExport::create()
, it appears that the list of available formats can be retrieved through $container->getParameter('serializer.format_providers')
.
However, to be absolutely certain that a format actually supports a decode/encode operation, you will still need to call $serializer->supportsDecoding()
and $serializer->supportsEncoding()
respectively.
Remaining tasks
User interface changes
None expected.
API changes
None expected.
Data model changes
None expected.