<?php
declare(strict_types=1);
namespace App\EventListener;
use ApiPlatform\Core\EventListener\DeserializeListener as DecoratedListener;
use ApiPlatform\Core\Util\RequestAttributesExtractor;
use ApiPlatform\Serializer\SerializerContextBuilderInterface;
use App\Traits\FormDataForPutTrait;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
final class DeserializeListener
{
use FormDataForPutTrait;
private DecoratedListener $decorated;
private DenormalizerInterface $denormalizer;
private SerializerContextBuilderInterface $serializerContextBuilder;
public function __construct(
DenormalizerInterface $denormalizer,
SerializerContextBuilderInterface $serializerContextBuilder,
DecoratedListener $decorated
) {
$this->denormalizer = $denormalizer;
$this->serializerContextBuilder = $serializerContextBuilder;
$this->decorated = $decorated;
}
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
if ($request->isMethodCacheable() || $request->isMethod(Request::METHOD_DELETE)) {
return;
}
if ('form' === $request->getContentType()) {
$this->denormalizeFromRequest($request);
} else {
$this->decorated->onKernelRequest($event);
}
}
private function denormalizeFromRequest(Request $request): void
{
$this->activeHttpPut($request);
if (!$attributes = RequestAttributesExtractor::extractAttributes($request)) {
return;
}
$context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes);
$populated = $request->attributes->get('data');
if (null !== $populated) {
$context['object_to_populate'] = $populated;
}
$data = $request->request->all();
$files = $request->files->all();
$route = $request->attributes->get('_route');
$booleanFields = [
'api_letters_post_collection' => ['isRead', 'isArchived'],
'api_letters_put_item' => ['isRead', 'isArchived'],
'api_letter_signatures_post_collection' => ['isCoursier'],
'api_letter_signatures_put_item' => ['isCoursier'],
];
if (array_key_exists($route, $booleanFields)) {
foreach ($booleanFields[$route] as $field) {
if (isset($data[$field])) {
$data[$field] = filter_var($data[$field], FILTER_VALIDATE_BOOLEAN);
}
}
$request->request->replace($data);
}
$object = $this->denormalizer->denormalize(array_merge($data, $files), $attributes['resource_class'], null, $context);
$request->attributes->set('data', $object);
}
}