diff --git a/src/Serializer/PartNormalizer.php b/src/Serializer/PartNormalizer.php index 9767759d..a4890104 100644 --- a/src/Serializer/PartNormalizer.php +++ b/src/Serializer/PartNormalizer.php @@ -29,21 +29,24 @@ use App\Entity\Parts\Supplier; use App\Entity\PriceInformations\Orderdetail; use App\Entity\PriceInformations\Pricedetail; use Brick\Math\BigDecimal; -use Symfony\Component\DependencyInjection\Attribute\Autowire; -use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; +use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; -use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; /** * @see \App\Tests\Serializer\PartNormalizerTest - * TODO: Properly rewrite this class to use the SerializerAware interface and dont use the ObjectNormalizer directly */ -class PartNormalizer implements NormalizerInterface, DenormalizerInterface +class PartNormalizer implements NormalizerInterface, DenormalizerInterface, NormalizerAwareInterface, DenormalizerAwareInterface { + use NormalizerAwareTrait; + use DenormalizerAwareTrait; + + private const ALREADY_CALLED = 'PART_NORMALIZER_ALREADY_CALLED'; + private const DENORMALIZE_KEY_MAPPING = [ 'notes' => 'comment', 'quantity' => 'instock', @@ -56,10 +59,6 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface public function __construct( private readonly StructuralElementFromNameDenormalizer $locationDenormalizer, - #[Autowire(service: ObjectNormalizer::class)] - private readonly NormalizerInterface $normalizer, - #[Autowire(service: ObjectNormalizer::class)] - private readonly DenormalizerInterface $denormalizer, ) { } @@ -67,20 +66,22 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface public function supportsNormalization($data, string $format = null, array $context = []): bool { //We only remove the type field for CSV export - return $format === 'csv' && $data instanceof Part ; + return !isset($context[self::ALREADY_CALLED]) && $format === 'csv' && $data instanceof Part ; } - /** - * @return (float|mixed)[]|\ArrayObject|null|scalar - * - * @psalm-return \ArrayObject|array{total_instock: float|mixed,...}|null|scalar - */ - public function normalize($object, string $format = null, array $context = []) + public function normalize($object, string $format = null, array $context = []): array { if (!$object instanceof Part) { throw new \InvalidArgumentException('This normalizer only supports Part objects!'); } + $context[self::ALREADY_CALLED] = true; + + //Prevent exception in API Platform + if ($object->getID() === null) { + $context['iri'] = 'not-persisted'; + } + $data = $this->normalizer->normalize($object, $format, $context); //Remove type field for CSV export @@ -93,7 +94,7 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface public function supportsDenormalization($data, string $type, string $format = null, array $context = []): bool { - return is_array($data) && is_a($type, Part::class, true); + return !isset($context[self::ALREADY_CALLED]) && is_array($data) && is_a($type, Part::class, true); } private function normalizeKeys(array &$data): array @@ -129,6 +130,8 @@ class PartNormalizer implements NormalizerInterface, DenormalizerInterface $data['minamount'] = 0.0; } + $context[self::ALREADY_CALLED] = true; + $object = $this->denormalizer->denormalize($data, $type, $format, $context); if (!$object instanceof Part) { diff --git a/tests/Serializer/PartNormalizerTest.php b/tests/Serializer/PartNormalizerTest.php index 39295a86..de5ac2db 100644 --- a/tests/Serializer/PartNormalizerTest.php +++ b/tests/Serializer/PartNormalizerTest.php @@ -28,17 +28,24 @@ use App\Entity\PriceInformations\Orderdetail; use App\Entity\PriceInformations\Pricedetail; use App\Serializer\PartNormalizer; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; +use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; +use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class PartNormalizerTest extends WebTestCase { /** @var PartNormalizer */ - protected $service; + protected DenormalizerInterface&NormalizerInterface $service; protected function setUp(): void { //Get a service instance. self::bootKernel(); $this->service = self::getContainer()->get(PartNormalizer::class); + + //We need to inject the serializer into the normalizer, as we use it directly + $serializer = self::getContainer()->get('serializer'); + $this->service->setNormalizer($serializer); + $this->service->setDenormalizer($serializer); } public function testSupportsNormalization(): void