vendor/drosalys/api-bundle/src/EventSubscriber/DeserializeActionControllerSubscriber.php line 51

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the drosalys/api-bundle package.
  4. *
  5. * (c) Benjamin Georgeault
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace Drosalys\Bundle\ApiBundle\EventSubscriber;
  11. use Drosalys\Bundle\ApiBundle\Event\PostDeserializeEvent;
  12. use Drosalys\Bundle\ApiBundle\Event\PreDeserializeEvent;
  13. use Drosalys\Bundle\ApiBundle\Request\ActionRequestTrait;
  14. use Drosalys\Bundle\ApiBundle\Serializer\SerializerInterface;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
  17. use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent;
  18. use Symfony\Component\HttpKernel\KernelEvents;
  19. use Symfony\Component\Validator\Validator\ValidatorInterface;
  20. /**
  21. * Class DeserializeActionControllerSubscriber
  22. *
  23. * @author Benjamin Georgeault
  24. */
  25. class DeserializeActionControllerSubscriber implements EventSubscriberInterface
  26. {
  27. const REQUEST_KEY = '_drosalys_api_object';
  28. const REQUEST_ERROR_KEY = '_drosalys_api_object_error';
  29. use ActionRequestTrait;
  30. public function __construct(
  31. private SerializerInterface $serializer,
  32. private ValidatorInterface $validator,
  33. private ArgumentResolverInterface $argumentResolver,
  34. ) {
  35. }
  36. public static function getSubscribedEvents(): array
  37. {
  38. return [
  39. // Trigger after Sensio IsGranted listener.
  40. KernelEvents::CONTROLLER_ARGUMENTS => ['__invoke', -63],
  41. ];
  42. }
  43. public function __invoke(ControllerArgumentsEvent $event): void
  44. {
  45. if (
  46. (null === $action = $this->retrieveActionFromRequest($request = $event->getRequest()))
  47. || (null === $deserializeInfo = $action->getDeserializeInfo())
  48. ) {
  49. return;
  50. }
  51. $type = $deserializeInfo->getType();
  52. if ($type->hasWrap()) { // TODO
  53. throw new \RuntimeException('Not yet implemented.');
  54. }
  55. if (!$type->isClass()) {
  56. return;
  57. }
  58. if (null === $object = $request->attributes->get($deserializeInfo->getName())) {
  59. return;
  60. }
  61. if (
  62. (null !== $eventInfo = $deserializeInfo->getEventInfo())
  63. && $eventInfo->hasPre()
  64. ) {
  65. ($eventInfo->getPre())(new PreDeserializeEvent($action, $request, $object));
  66. }
  67. $object = $this->serializer->deserialize(
  68. $request->getContent(),
  69. $type->getClassName(),
  70. 'json',
  71. $deserializeInfo->getGroups(),
  72. $object,
  73. );
  74. if ((null !== $eventInfo) && $eventInfo->hasPost()) {
  75. ($eventInfo->getPost())(new PostDeserializeEvent($action, $request, $object));
  76. }
  77. $request->attributes->set(self::REQUEST_KEY, $object);
  78. if (false !== $validationGroups = $deserializeInfo->getValidationGroups()) {
  79. $errors = $this->validator->validate($object, null, $validationGroups);
  80. if (0 < $errors->count()) {
  81. $request->attributes->set(self::REQUEST_ERROR_KEY, $errors);
  82. // If one argument is null, maybe its the ConstraintList, so refresh controller's arguments.
  83. foreach ($event->getArguments() as $argument) {
  84. if (null === $argument) {
  85. $event->setArguments($this->argumentResolver->getArguments($request, $event->getController()));
  86. break;
  87. }
  88. }
  89. }
  90. }
  91. }
  92. }