vendor/drosalys/api-bundle/src/EventSubscriber/ActionResponseSubscriber.php line 62

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\Action\Action;
  12. use Drosalys\Bundle\ApiBundle\Action\Info\EventInfo;
  13. use Drosalys\Bundle\ApiBundle\Event\AbstractViewEvent;
  14. use Drosalys\Bundle\ApiBundle\Event\PostPersistEvent;
  15. use Drosalys\Bundle\ApiBundle\Event\PostBuildResponseEvent;
  16. use Drosalys\Bundle\ApiBundle\Event\PrePersistEvent;
  17. use Drosalys\Bundle\ApiBundle\Event\PreBuildResponseEvent;
  18. use Drosalys\Bundle\ApiBundle\Event\ReplaceBuildResponseEvent;
  19. use Drosalys\Bundle\ApiBundle\Event\ReplacePersistEvent;
  20. use Drosalys\Bundle\ApiBundle\Persister\PersisterHandler\PersisterHandlerInterface;
  21. use Drosalys\Bundle\ApiBundle\Request\ActionRequestTrait;
  22. use Drosalys\Bundle\ApiBundle\Response\ResponseHandler\ResponseHandlerInterface;
  23. use Drosalys\Bundle\ApiBundle\Routing\Attributes\AbstractRoute;
  24. use Psr\EventDispatcher\EventDispatcherInterface;
  25. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  26. use Symfony\Component\HttpFoundation\Request;
  27. use Symfony\Component\HttpFoundation\Response;
  28. use Symfony\Component\HttpKernel\Event\ViewEvent;
  29. use Symfony\Component\HttpKernel\KernelEvents;
  30. /**
  31. * Class ActionResponseSubscriber
  32. *
  33. * @author Benjamin Georgeault
  34. */
  35. class ActionResponseSubscriber implements EventSubscriberInterface
  36. {
  37. use ActionRequestTrait;
  38. /**
  39. * ActionResponseSubscriber constructor.
  40. * @param ResponseHandlerInterface[] $responseHandlers
  41. * @param PersisterHandlerInterface[] $persisterHandlers
  42. */
  43. public function __construct(
  44. private EventDispatcherInterface $dispatcher,
  45. private iterable $responseHandlers,
  46. private iterable $persisterHandlers,
  47. ) {
  48. }
  49. public static function getSubscribedEvents(): array
  50. {
  51. return [
  52. KernelEvents::VIEW => ['__invoke', 63],
  53. ];
  54. }
  55. public function __invoke(ViewEvent $event): void
  56. {
  57. if (null === $action = $this->retrieveActionFromRequest($request = $event->getRequest())) {
  58. return;
  59. }
  60. $this->applyPersister($action, $request, $data = $event->getControllerResult());
  61. if (null !== $response = $this->buildResponse($action, $request, $data)) {
  62. $event->setResponse($response);
  63. }
  64. }
  65. private function buildResponse(Action $action, Request $request, mixed $data): ?Response
  66. {
  67. if ((null !== $info = $action->getBuildResponseInfo()) && ($info->hasReplace())) {
  68. return ($info->getReplace())(new ReplaceBuildResponseEvent($action, $request, $data));
  69. }
  70. foreach ($this->responseHandlers as $handler) {
  71. if ($handler->support($action, $request, $data)) {
  72. if ((null !== $info = $action->getBuildResponseInfo()) && ($info->hasPre())) {
  73. ($info->getPre())(new PreBuildResponseEvent($action, $request, $data));
  74. }
  75. $this->dispatcher->dispatch(new PreBuildResponseEvent($action, $request, $data));
  76. $response = $handler->buildResponse($action, $request, $data);
  77. if ((null !== $info) && ($info->hasPost())) {
  78. ($info->getPost())(new PostBuildResponseEvent($action, $request, $data, $response));
  79. }
  80. $this->dispatcher->dispatch(new PostBuildResponseEvent($action, $request, $data, $response));
  81. return $response;
  82. }
  83. }
  84. return null;
  85. }
  86. private function applyPersister(Action $action, Request $request, mixed $data): void
  87. {
  88. if ($request->attributes->has(DeserializeActionControllerSubscriber::REQUEST_ERROR_KEY)) {
  89. return;
  90. }
  91. if ((null !== $info = $action->getPersistInfo()) && ($info->hasReplace())) {
  92. ($info->getReplace())(new ReplacePersistEvent($action, $request, $data));
  93. return;
  94. }
  95. if (null === $action->getDeserializeInfo() && $action->getMethod() !== AbstractRoute::DELETE) {
  96. return;
  97. }
  98. foreach ($this->persisterHandlers as $handler) {
  99. if ($handler->support($action, $request, $data)) {
  100. if ((null !== $info) && ($info->hasPre())) {
  101. ($info->getPre())(new PrePersistEvent($action, $request, $data));
  102. }
  103. $this->dispatcher->dispatch(new PrePersistEvent($action, $request, $data));
  104. $handler->persist($action, $request, $data);
  105. if ((null !== $info) && ($info->hasPost())) {
  106. ($info->getPost())(new PostPersistEvent($action, $request, $data));
  107. }
  108. $this->dispatcher->dispatch(new PostPersistEvent($action, $request, $data));
  109. break;
  110. }
  111. }
  112. }
  113. }