From 5098b6fda6323caeaa52ff1c48119de55f58a37b Mon Sep 17 00:00:00 2001 From: Jan Goralski Date: Wed, 26 Jun 2024 10:10:54 +0200 Subject: [PATCH] [Maintenance] Fix `ProductNormalizer` not resolving custom ProductAssociation classes --- config/services/serializer.xml | 1 + src/Api/Normalizer/ProductNormalizer.php | 11 ++++++++-- .../Api/Normalizer/ProductNormalizerTest.php | 22 ++++++++++++++++--- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/config/services/serializer.xml b/config/services/serializer.xml index fb26cff..6cc01ca 100644 --- a/config/services/serializer.xml +++ b/config/services/serializer.xml @@ -10,6 +10,7 @@ + %sylius.model.product_association.class% diff --git a/src/Api/Normalizer/ProductNormalizer.php b/src/Api/Normalizer/ProductNormalizer.php index 6fce0c5..5b08083 100644 --- a/src/Api/Normalizer/ProductNormalizer.php +++ b/src/Api/Normalizer/ProductNormalizer.php @@ -6,7 +6,6 @@ use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use Sylius\Bundle\ApiBundle\Converter\IriToIdentifierConverterInterface; -use Sylius\Component\Product\Model\ProductAssociation; use Sylius\Component\Product\Model\ProductAssociationInterface; use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; @@ -19,7 +18,15 @@ public function __construct( private NormalizerInterface $decoratedNormalizer, private ItemDataProviderInterface $itemDataProvider, private IriToIdentifierConverterInterface $iriToIdentifierConverter, + private string $productAssociationClass, ) { + if (!is_a($productAssociationClass, ProductAssociationInterface::class, true)) { + throw new \InvalidArgumentException(sprintf( + 'The class "%s" must implement "%s".', + $productAssociationClass, + ProductAssociationInterface::class, + )); + } } public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool @@ -39,7 +46,7 @@ public function normalize($object, string $format = null, array $context = []): foreach ($associations as $association) { $id = $this->iriToIdentifierConverter->getIdentifier($association); /** @var ProductAssociationInterface $associationObject */ - $associationObject = $this->itemDataProvider->getItem(ProductAssociation::class, (string) $id); + $associationObject = $this->itemDataProvider->getItem($this->productAssociationClass, (string) $id); $associationTypeCode = $associationObject->getType()?->getCode(); if (null === $associationTypeCode) { diff --git a/tests/Unit/Api/Normalizer/ProductNormalizerTest.php b/tests/Unit/Api/Normalizer/ProductNormalizerTest.php index bbaf278..635ffe3 100644 --- a/tests/Unit/Api/Normalizer/ProductNormalizerTest.php +++ b/tests/Unit/Api/Normalizer/ProductNormalizerTest.php @@ -20,6 +20,21 @@ final class ProductNormalizerTest extends TestCase { use ProphecyTrait; + private string $productAssociationClass = ProductAssociation::class; + + public function testItThrowsInvalidArgumentExceptionWhenProductAssociationClassDoesNotImplementProductAssociationInterface(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The class "stdClass" must implement "Sylius\Component\Product\Model\ProductAssociationInterface".'); + + new ProductNormalizer( + $this->prophesize(ContextAwareNormalizerInterface::class)->reveal(), + $this->prophesize(ItemDataProviderInterface::class)->reveal(), + $this->prophesize(IriToIdentifierConverterInterface::class)->reveal(), + \stdClass::class, + ); + } + public function testItAddsAssociationsTypesToProductResponse(): void { $baseNormalizer = $this->prophesize(ProductNormalizerInterface::class); @@ -29,7 +44,8 @@ public function testItAddsAssociationsTypesToProductResponse(): void $normalizer = new ProductNormalizer( $baseNormalizer->reveal(), $itemDataProvider->reveal(), - $iriToIdentifierConverter->reveal() + $iriToIdentifierConverter->reveal(), + $this->productAssociationClass, ); $product = $this->prophesize(Product::class); @@ -52,9 +68,9 @@ public function testItAddsAssociationsTypesToProductResponse(): void $secondAssociationType->getCode()->willReturn('second_association_type'); $iriToIdentifierConverter->getIdentifier('/api/v2/product-associations/1')->willReturn('1'); - $itemDataProvider->getItem(ProductAssociation::class, '1')->willReturn($firstAssociation); + $itemDataProvider->getItem($this->productAssociationClass, '1')->willReturn($firstAssociation); $iriToIdentifierConverter->getIdentifier('/api/v2/product-associations/2')->willReturn('2'); - $itemDataProvider->getItem(ProductAssociation::class, '2')->willReturn($secondAssociation); + $itemDataProvider->getItem($this->productAssociationClass, '2')->willReturn($secondAssociation); self::assertSame( [