diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index be38431a..a54fd6f5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -615,11 +615,6 @@ parameters: count: 1 path: src/lib/Output/Generator/InMemory/Xml.php - - - message: "#^Parameter \\#1 \\$data of method Ibexa\\\\Rest\\\\Output\\\\Generator\\\\InMemory\\\\Xml\\:\\:transformDataForEncoder\\(\\) expects array, array\\|ArrayObject\\<\\(int\\|string\\), mixed\\>\\|bool\\|float\\|int\\|string\\|null given\\.$#" - count: 1 - path: src/lib/Output/Generator/InMemory/Xml.php - - message: "#^Access to an undefined property Ibexa\\\\Rest\\\\Output\\\\Generator\\\\Json\\\\JsonObject\\:\\:\\$\\#text\\.$#" count: 1 diff --git a/src/contracts/Output/Generator.php b/src/contracts/Output/Generator.php index 9f923670..ccb5c049 100644 --- a/src/contracts/Output/Generator.php +++ b/src/contracts/Output/Generator.php @@ -431,11 +431,4 @@ public function getData(): object * @return array */ abstract public function getEncoderContext(array $data): array; - - /** - * @param array $data - * - * @return array - */ - abstract public function transformDataForEncoder(array $data): array; } diff --git a/src/contracts/Output/VisitorAdapterNormalizer.php b/src/contracts/Output/VisitorAdapterNormalizer.php index 3f4f0851..43e26ecb 100644 --- a/src/contracts/Output/VisitorAdapterNormalizer.php +++ b/src/contracts/Output/VisitorAdapterNormalizer.php @@ -22,6 +22,8 @@ final class VisitorAdapterNormalizer implements NormalizerInterface, NormalizerA public const string ENCODER_CONTEXT = 'ENCODER_CONTEXT'; + public const string OUTER_ELEMENT = 'outer_element'; + public function __construct( private readonly ValueObjectVisitorResolverInterface $valueObjectVisitorResolver, ) { @@ -104,11 +106,28 @@ private function visitValueObject( $data = $generator->getData(); - $normalizedData = $this->normalizer->normalize($data, $format, $context + [ - self::CALLED_CONTEXT => true, - ]); - $normalizedData = $generator->transformDataForEncoder($normalizedData); + $normalizedData = $this->normalizer->normalize( + $data, + $format, + $this->buildContext($context, $format), + ); return $normalizedData + [self::ENCODER_CONTEXT => $generator->getEncoderContext(get_object_vars($data))]; } + + /** + * @param array $context + * + * @return array + */ + private function buildContext(array $context, ?string $format): array + { + $context += [self::CALLED_CONTEXT => true]; + + if ($format === 'xml') { + $context += [self::OUTER_ELEMENT => true, 'as_collection' => true]; + } + + return $context; + } } diff --git a/src/lib/Output/Generator/InMemory/Xml.php b/src/lib/Output/Generator/InMemory/Xml.php index df4453a7..e39981e0 100644 --- a/src/lib/Output/Generator/InMemory/Xml.php +++ b/src/lib/Output/Generator/InMemory/Xml.php @@ -8,6 +8,7 @@ namespace Ibexa\Rest\Output\Generator\InMemory; +use Ibexa\Contracts\Rest\Output\VisitorAdapterNormalizer; use Ibexa\Rest\Output\Generator\Data; use Ibexa\Rest\Output\Generator\Data\ArrayList; use Ibexa\Rest\Output\Generator\Json; @@ -91,6 +92,7 @@ public function endDocument(mixed $data): string $vars = get_object_vars($data); $encoderContext = $this->getEncoderContext($vars); $encoderContext['as_collection'] = true; + $encoderContext[VisitorAdapterNormalizer::OUTER_ELEMENT] = true; $normalizers = [ new ArrayListNormalizer(), @@ -101,10 +103,7 @@ public function endDocument(mixed $data): string $encoders = [new XmlEncoder()]; $serializer = new Serializer($normalizers, $encoders); - $normalizedData = $serializer->normalize($data, 'xml'); - $normalizedData = $this->transformDataForEncoder($normalizedData); - - return $serializer->encode($normalizedData, 'xml', $encoderContext); + return $serializer->serialize($data, 'xml', $encoderContext); } public function getEncoderContext(array $data): array @@ -113,18 +112,4 @@ public function getEncoderContext(array $data): array XmlEncoder::ROOT_NODE_NAME => array_key_first($data), ]; } - - public function transformDataForEncoder(array $data): array - { - $firstKey = array_key_first($data); - - if ($firstKey === null) { - return $data; - } - - $data['#'] = $data[$firstKey]; - unset($data[$firstKey]); - - return $data; - } } diff --git a/src/lib/Output/Generator/Json.php b/src/lib/Output/Generator/Json.php index 2b520cc9..87a6c8be 100644 --- a/src/lib/Output/Generator/Json.php +++ b/src/lib/Output/Generator/Json.php @@ -339,9 +339,4 @@ public function getEncoderContext(array $data): array { return []; } - - public function transformDataForEncoder(array $data): array - { - return $data; - } } diff --git a/src/lib/Output/Generator/Xml.php b/src/lib/Output/Generator/Xml.php index 9c9a7a47..8851efa2 100644 --- a/src/lib/Output/Generator/Xml.php +++ b/src/lib/Output/Generator/Xml.php @@ -274,9 +274,4 @@ public function getEncoderContext(array $data): array { return []; } - - public function transformDataForEncoder(array $data): array - { - return $data; - } } diff --git a/src/lib/Output/Normalizer/JsonObjectNormalizer.php b/src/lib/Output/Normalizer/JsonObjectNormalizer.php index aee19b4c..06dbafb4 100644 --- a/src/lib/Output/Normalizer/JsonObjectNormalizer.php +++ b/src/lib/Output/Normalizer/JsonObjectNormalizer.php @@ -7,6 +7,7 @@ namespace Ibexa\Rest\Output\Normalizer; +use Ibexa\Contracts\Rest\Output\VisitorAdapterNormalizer; use Ibexa\Rest\Output\Generator\Data\ArrayList; use Ibexa\Rest\Output\Generator\Json\JsonObject; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; @@ -26,6 +27,9 @@ public function normalize($object, ?string $format = null, array $context = []): { $vars = get_object_vars($object); + $isOuterElement = $context[VisitorAdapterNormalizer::OUTER_ELEMENT] ?? false; + unset($context[VisitorAdapterNormalizer::OUTER_ELEMENT]); + $data = []; foreach ($vars as $key => $value) { if ($value instanceof ArrayList) { @@ -35,7 +39,8 @@ public function normalize($object, ?string $format = null, array $context = []): } $data[$name] = $this->normalizer->normalize($value, $format, $context); } else { - $data[$key] = $this->normalizer->normalize($value, $format, $context); + $modifiedKey = $isOuterElement && count($vars) === 1 ? '#' : $key; + $data[$modifiedKey] = $this->normalizer->normalize($value, $format, $context); } }