src/Mm/Escmid/EaaBundle/EventListener/ExceptionListener.php line 71

Open in your IDE?
  1. <?php
  2. namespace Mm\Escmid\EaaBundle\EventListener;
  3. use Mm\Escmid\EaaBundle\EventListener\ExceptionHandler\ExceptionHandlerDefinition;
  4. use Mm\Escmid\EaaBundle\EventListener\ExceptionHandler\ExceptionHandlerInterface;
  5. use Mm\Escmid\EaaBundle\Platform\Security\AuthenticationException;
  6. use Mm\Escmid\EaaBundle\Platform\Service\ExceptionResponseGeneratorServiceInterface;
  7. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  8. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  9. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  10. use Symfony\Component\HttpKernel\KernelEvents;
  11. use Symfony\Component\HttpKernel\KernelInterface;
  12. class ExceptionListener implements EventSubscriberInterface
  13. {
  14. public function __construct(
  15. private readonly KernelInterface $kernel,
  16. private readonly ExceptionResponseGeneratorServiceInterface $responseGeneratorService,
  17. private readonly array $handlerDefinitions,
  18. private ExceptionHandlerInterface $fallbackHandler
  19. ) {
  20. }
  21. public function checkIfDefinitionContainsKey(ExceptionHandlerDefinition $handlerDefinition, string $key): bool
  22. {
  23. return in_array($key, $handlerDefinition->getKeys(), true);
  24. }
  25. public function getFallthruHandlerDefinition(): ?ExceptionHandlerDefinition
  26. {
  27. return $this->getHandlerDefinitionForKey('fallthru_'.$this->kernel->getEnvironment());
  28. }
  29. public function getHandlerDefinitionForKey(string $key): ?ExceptionHandlerDefinition
  30. {
  31. foreach ($this->handlerDefinitions as $definition) {
  32. if ($this->checkIfDefinitionContainsKey($definition, $key)) {
  33. return $definition;
  34. }
  35. }
  36. return null;
  37. }
  38. /**
  39. * Get exception handler for event.
  40. */
  41. public function getHandlerForException(\Throwable $exception): ExceptionHandlerInterface
  42. {
  43. $exceptionClassName = $exception::class;
  44. $handlerDefinition = $this->getHandlerDefinitionForKey($exceptionClassName);
  45. if (!$handlerDefinition) {
  46. $handlerDefinition = $this->getFallthruHandlerDefinition();
  47. }
  48. if (!$handlerDefinition) {
  49. $exceptionHandler = $this->fallbackHandler;
  50. } else {
  51. $exceptionHandler = $handlerDefinition->getExceptionHandler();
  52. }
  53. return $exceptionHandler;
  54. }
  55. /**
  56. * Handle kernel exceptions.
  57. */
  58. public function onKernelException(ExceptionEvent $event): void
  59. {
  60. $exception = $event->getThrowable();
  61. $previousException = $exception->getPrevious();
  62. if (
  63. !($exception instanceof AuthenticationException)
  64. && !($exception instanceof AccessDeniedHttpException)
  65. && ($previousException instanceof \Exception)
  66. ) {
  67. $exception = $previousException;
  68. }
  69. $exceptionHandler = $this->getHandlerForException($exception);
  70. $responseData = $exceptionHandler->handle($event);
  71. $event->setResponse($this->responseGeneratorService->generateResponse($responseData));
  72. }
  73. /**
  74. * @return array<string, mixed>
  75. */
  76. public static function getSubscribedEvents(): array
  77. {
  78. return [
  79. KernelEvents::EXCEPTION => ['onKernelException', -1],
  80. ];
  81. }
  82. }