mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
Fix serializing collection with intersection types
This commit is contained in:
parent
711cdc3481
commit
bad3cdca09
@ -96,7 +96,10 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte
|
|||||||
return 'docgen' === $format && (is_object($data) || null === $data);
|
return 'docgen' === $format && (is_object($data) || null === $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getExpectedType(AttributeMetadata $attribute, ReflectionClass $reflection): string
|
/**
|
||||||
|
* @return string|array<string>
|
||||||
|
*/
|
||||||
|
private function getExpectedType(AttributeMetadata $attribute, ReflectionClass $reflection): string|array
|
||||||
{
|
{
|
||||||
$type = null;
|
$type = null;
|
||||||
|
|
||||||
@ -147,14 +150,31 @@ class DocGenObjectNormalizer implements NormalizerAwareInterface, NormalizerInte
|
|||||||
}
|
}
|
||||||
} while (null === $type && $reflection instanceof ReflectionClass);
|
} while (null === $type && $reflection instanceof ReflectionClass);
|
||||||
|
|
||||||
if (null === $type ?? null) {
|
if ($type instanceof \ReflectionNamedType) {
|
||||||
|
return $type->getName();
|
||||||
|
}
|
||||||
|
if ($type instanceof \ReflectionIntersectionType) {
|
||||||
|
foreach (array_map(fn (\ReflectionNamedType $t) => $t->getName(), $type->getTypes()) as $classString) {
|
||||||
|
if (ReadableCollection::class === $classString) {
|
||||||
|
return ReadableCollection::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = new ReflectionClass($classString);
|
||||||
|
|
||||||
|
if ($class->implementsInterface(ReadableCollection::class)) {
|
||||||
|
return ReadableCollection::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new \LogicException(sprintf("The automatic normalization of intersection types is not supported, unless a %s is contained in the intersected types", ReadableCollection::class));
|
||||||
|
} elseif (null === $type ?? null) {
|
||||||
throw new \LogicException(sprintf(
|
throw new \LogicException(sprintf(
|
||||||
'Could not determine the type for this attribute: %s. Add a return type to the method or property declaration',
|
'Could not determine the type for this attribute: %s. Add a return type to the method or property declaration',
|
||||||
$attribute->getName()
|
$attribute->getName()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $type->getName();
|
throw new \LogicException(sprintf("The automatic normalization of %s is not supported", $type::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,10 @@ namespace Chill\DocGeneratorBundle\tests\Serializer\Normalizer;
|
|||||||
|
|
||||||
use Chill\MainBundle\Entity\Scope;
|
use Chill\MainBundle\Entity\Scope;
|
||||||
use Chill\MainBundle\Entity\User;
|
use Chill\MainBundle\Entity\User;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Doctrine\Common\Collections\ReadableCollection;
|
||||||
|
use Doctrine\Common\Collections\Selectable;
|
||||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||||
use Symfony\Component\Serializer\Annotation as Serializer;
|
use Symfony\Component\Serializer\Annotation as Serializer;
|
||||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
@ -28,7 +32,6 @@ final class DocGenObjectNormalizerTest extends KernelTestCase
|
|||||||
|
|
||||||
protected function setUp(): void
|
protected function setUp(): void
|
||||||
{
|
{
|
||||||
parent::setUp();
|
|
||||||
self::bootKernel();
|
self::bootKernel();
|
||||||
|
|
||||||
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
$this->normalizer = self::$container->get(NormalizerInterface::class);
|
||||||
@ -171,6 +174,64 @@ final class DocGenObjectNormalizerTest extends KernelTestCase
|
|||||||
|
|
||||||
$this->assertEquals($expected, $normalized, 'test normalization fo an user with null center');
|
$this->assertEquals($expected, $normalized, 'test normalization fo an user with null center');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testIntersectionTypeForReadableCollection(): void
|
||||||
|
{
|
||||||
|
$value = new TestableWithIntersectionReadableCollection();
|
||||||
|
|
||||||
|
$normalized = $this->normalizer->normalize($value, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => TestableWithIntersectionReadableCollection::class]);
|
||||||
|
|
||||||
|
self::assertIsArray($normalized);
|
||||||
|
self::assertIsArray($normalized['collection']);
|
||||||
|
self::assertCount(2, $normalized['collection']);
|
||||||
|
|
||||||
|
self::assertEquals(
|
||||||
|
['baz' => 'bloup', 'isNull' => false],
|
||||||
|
$normalized['collection'][0]
|
||||||
|
);
|
||||||
|
self::assertEquals(
|
||||||
|
['baz' => 'bloup', 'isNull' => false],
|
||||||
|
$normalized['collection'][1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntersectionTypeForReadableCollectionWithNullValue(): void
|
||||||
|
{
|
||||||
|
$normalized = $this->normalizer->normalize(null, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => TestableWithIntersectionReadableCollection::class]);
|
||||||
|
|
||||||
|
self::assertIsArray($normalized);
|
||||||
|
self::assertIsArray($normalized['collection']);
|
||||||
|
self::assertCount(0, $normalized['collection']);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntersectionTypeForCollection(): void
|
||||||
|
{
|
||||||
|
$value = new TestableWithCollection();
|
||||||
|
|
||||||
|
$normalized = $this->normalizer->normalize($value, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => TestableWithCollection::class]);
|
||||||
|
|
||||||
|
self::assertIsArray($normalized);
|
||||||
|
self::assertIsArray($normalized['collection']);
|
||||||
|
self::assertCount(2, $normalized['collection']);
|
||||||
|
|
||||||
|
self::assertEquals(
|
||||||
|
['baz' => 'bloup', 'isNull' => false],
|
||||||
|
$normalized['collection'][0]
|
||||||
|
);
|
||||||
|
self::assertEquals(
|
||||||
|
['baz' => 'bloup', 'isNull' => false],
|
||||||
|
$normalized['collection'][1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testIntersectionTypeForCollectionWithNullValue(): void
|
||||||
|
{
|
||||||
|
$normalized = $this->normalizer->normalize(null, 'docgen', [AbstractNormalizer::GROUPS => ['docgen:read'], 'docgen:expects' => TestableWithCollection::class]);
|
||||||
|
|
||||||
|
self::assertIsArray($normalized);
|
||||||
|
self::assertIsArray($normalized['collection']);
|
||||||
|
self::assertCount(0, $normalized['collection']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestableParentClass
|
class TestableParentClass
|
||||||
@ -215,3 +276,29 @@ class TestableClassWithBool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestableWithIntersectionReadableCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Serializer\Groups("docgen:read")
|
||||||
|
*/
|
||||||
|
public ReadableCollection&Selectable $collection;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->collection = new ArrayCollection([new TestableChildClass(), new TestableChildClass()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestableWithCollection
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Serializer\Groups("docgen:read")
|
||||||
|
*/
|
||||||
|
public Collection&Selectable $collection;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->collection = new ArrayCollection([new TestableChildClass(), new TestableChildClass()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user