. */ declare(strict_types=1); namespace App\Serializer; use App\Entity\Attachments\Attachment; use App\Services\Attachments\AttachmentURLGenerator; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; class AttachmentNormalizer implements NormalizerInterface, NormalizerAwareInterface { use NormalizerAwareTrait; private const ALREADY_CALLED = 'ATTACHMENT_NORMALIZER_ALREADY_CALLED'; public function __construct( private readonly AttachmentURLGenerator $attachmentURLGenerator, ) { } public function normalize(mixed $object, string $format = null, array $context = []): array|null { if (!$object instanceof Attachment) { throw new \InvalidArgumentException('This normalizer only supports Attachment objects!'); } //Prevent loops, by adding a flag to the context $context[self::ALREADY_CALLED] = true; $data = $this->normalizer->normalize($object, $format, $context); $data['media_url'] = $this->attachmentURLGenerator->getViewURL($object); //Add thumbnail url if the attachment is a picture $data['thumbnail_url'] = $object->isPicture() ? $this->attachmentURLGenerator->getThumbnailURL($object) : null; return $data; } public function supportsNormalization(mixed $data, string $format = null, array $context = []): bool { // avoid recursion: only call once per object if (isset($context[self::ALREADY_CALLED])) { return false; } return $data instanceof Attachment; } public function getSupportedTypes(?string $format): array { return [ //We depend on the context to determine if we should normalize or not Attachment::class => false, ]; } }