<?php
/*
* This file is part of the drosalys/api-bundle package.
*
* (c) Benjamin Georgeault
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Drosalys\Bundle\ApiBundle\EventSubscriber;
use Drosalys\Bundle\ApiBundle\Event\PostDeserializeEvent;
use Drosalys\Bundle\ApiBundle\Event\PreDeserializeEvent;
use Drosalys\Bundle\ApiBundle\Request\ActionRequestTrait;
use Drosalys\Bundle\ApiBundle\Serializer\SerializerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Validator\Validator\ValidatorInterface;
/**
* Class DeserializeActionControllerSubscriber
*
* @author Benjamin Georgeault
*/
class DeserializeActionControllerSubscriber implements EventSubscriberInterface
{
const REQUEST_KEY = '_drosalys_api_object';
const REQUEST_ERROR_KEY = '_drosalys_api_object_error';
use ActionRequestTrait;
public function __construct(
private SerializerInterface $serializer,
private ValidatorInterface $validator,
private ArgumentResolverInterface $argumentResolver,
) {
}
public static function getSubscribedEvents(): array
{
return [
// Trigger after Sensio IsGranted listener.
KernelEvents::CONTROLLER_ARGUMENTS => ['__invoke', -63],
];
}
public function __invoke(ControllerArgumentsEvent $event): void
{
if (
(null === $action = $this->retrieveActionFromRequest($request = $event->getRequest()))
|| (null === $deserializeInfo = $action->getDeserializeInfo())
) {
return;
}
$type = $deserializeInfo->getType();
if ($type->hasWrap()) { // TODO
throw new \RuntimeException('Not yet implemented.');
}
if (!$type->isClass()) {
return;
}
if (null === $object = $request->attributes->get($deserializeInfo->getName())) {
return;
}
if (
(null !== $eventInfo = $deserializeInfo->getEventInfo())
&& $eventInfo->hasPre()
) {
($eventInfo->getPre())(new PreDeserializeEvent($action, $request, $object));
}
$object = $this->serializer->deserialize(
$request->getContent(),
$type->getClassName(),
'json',
$deserializeInfo->getGroups(),
$object,
);
if ((null !== $eventInfo) && $eventInfo->hasPost()) {
($eventInfo->getPost())(new PostDeserializeEvent($action, $request, $object));
}
$request->attributes->set(self::REQUEST_KEY, $object);
if (false !== $validationGroups = $deserializeInfo->getValidationGroups()) {
$errors = $this->validator->validate($object, null, $validationGroups);
if (0 < $errors->count()) {
$request->attributes->set(self::REQUEST_ERROR_KEY, $errors);
// If one argument is null, maybe its the ConstraintList, so refresh controller's arguments.
foreach ($event->getArguments() as $argument) {
if (null === $argument) {
$event->setArguments($this->argumentResolver->getArguments($request, $event->getController()));
break;
}
}
}
}
}
}