vendor/api-platform/core/src/Symfony/EventListener/DeserializeListener.php line 48
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace ApiPlatform\Symfony\EventListener;
use ApiPlatform\Api\FormatMatcher;
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
use ApiPlatform\Serializer\SerializerContextBuilderInterface;
use ApiPlatform\Util\OperationRequestInitiatorTrait;
use ApiPlatform\Util\RequestAttributesExtractor;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
/**
* Updates the entity retrieved by the data provider with data contained in the request body.
*
* @author Kévin Dunglas <dunglas@gmail.com>
*/
final class DeserializeListener
{
use OperationRequestInitiatorTrait;
public const OPERATION_ATTRIBUTE_KEY = 'deserialize';
public function __construct(private readonly SerializerInterface $serializer, private readonly SerializerContextBuilderInterface $serializerContextBuilder, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataFactory = null)
{
$this->resourceMetadataCollectionFactory = $resourceMetadataFactory;
}
/**
* Deserializes the data sent in the requested format.
*
* @throws UnsupportedMediaTypeHttpException
*/
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
$method = $request->getMethod();
if (
'DELETE' === $method
|| $request->isMethodSafe()
|| !($attributes = RequestAttributesExtractor::extractAttributes($request))
|| !$attributes['receive']
) {
return;
}
$operation = $this->initializeOperation($request);
if (!($operation?->canDeserialize() ?? true)) {
return;
}
$context = $this->serializerContextBuilder->createFromRequest($request, false, $attributes);
$format = $this->getFormat($request, $operation?->getInputFormats() ?? []);
$data = $request->attributes->get('data');
if (null !== $data) {
$context[AbstractNormalizer::OBJECT_TO_POPULATE] = $data;
}
$request->attributes->set(
'data',
$this->serializer->deserialize($request->getContent(), $context['resource_class'], $format, $context)
);
}
/**
* Extracts the format from the Content-Type header and check that it is supported.
*
* @throws UnsupportedMediaTypeHttpException
*/
private function getFormat(Request $request, array $formats): string
{
/** @var ?string $contentType */
$contentType = $request->headers->get('CONTENT_TYPE');
if (null === $contentType) {
throw new UnsupportedMediaTypeHttpException('The "Content-Type" header must exist.');
}
$formatMatcher = new FormatMatcher($formats);
$format = $formatMatcher->getFormat($contentType);
if (null === $format) {
$supportedMimeTypes = [];
foreach ($formats as $mimeTypes) {
foreach ($mimeTypes as $mimeType) {
$supportedMimeTypes[] = $mimeType;
}
}
throw new UnsupportedMediaTypeHttpException(sprintf('The content-type "%s" is not supported. Supported MIME types are "%s".', $contentType, implode('", "', $supportedMimeTypes)));
}
return $format;
}
}