Rewrote PartNormalizer so that it does not use ObjectNormalizer directly

This commit is contained in:
Jan Böhmer 2024-03-03 19:28:44 +01:00
parent e53da5ad06
commit 7a90d3f281
2 changed files with 28 additions and 18 deletions

View file

@ -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) {

View file

@ -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