src/Infrastructure/EventListener/ExceptionEventSubscriber.php line 38

Open in your IDE?
  1. <?php
  2. namespace App\Infrastructure\EventListener;
  3. use App\Database\Domain\Entity\Log;
  4. use App\Database\Domain\Exception\ModelValidationException;
  5. use App\Infrastructure\Logs\DbLogger;
  6. use Doctrine\ORM\ORMException;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpFoundation\RedirectResponse;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  11. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  12. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  13. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  14. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  15. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  16. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  17. use Symfony\Component\Messenger\Exception\HandlerFailedException;
  18. use Symfony\Component\Routing\RouterInterface;
  19. class ExceptionEventSubscriber implements \Symfony\Component\EventDispatcher\EventSubscriberInterface
  20. {
  21.     private RouterInterface $router;
  22.     private SessionInterface $session;
  23.     private DbLogger $logger;
  24.     public function __construct(
  25.         RouterInterface $router,
  26.         SessionInterface $session,
  27.         DbLogger $logger
  28.     ) {
  29.         $this->router $router;
  30.         $this->session $session;
  31.         $this->logger $logger;
  32.     }
  33.     public function onKernelException(ExceptionEvent $event): void
  34.     {
  35.         // Disabling listener in dev env (but not in ajax requests) to get detailed error messages
  36.         if ($_ENV['APP_ENV'] === 'dev' && !$this->isApiException($event)) {
  37.             return;
  38.         }
  39.         $this->isApiException($event) ?
  40.             $this->handleApiException($event) : $this->handleException($event);
  41.     }
  42.     private function handleApiException(ExceptionEvent $event): void
  43.     {
  44.         $exception $event->getThrowable();
  45.         if ($exception instanceof HandlerFailedException) {
  46.             $exception $exception->getPrevious();
  47.         }
  48.         try {
  49.             $this->logger->error($exception->getMessage(), Log::SOURCE_GLOBAL, ['trace' => $exception->getTraceAsString()]);
  50.         } catch (\Throwable $e) {
  51.         }
  52.         $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
  53.         if ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) {
  54.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_NOT_FOUND);
  55.         }
  56.         if ($exception instanceof BadRequestHttpException) {
  57.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_BAD_REQUEST);
  58.         }
  59.         if ($exception instanceof AccessDeniedHttpException) {
  60.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_FORBIDDEN);
  61.         }
  62.         if ($exception instanceof ModelValidationException) {
  63.             $responseData = ['errors' => []];
  64.             foreach ($exception->getErrors() as $error) {
  65.                 $responseData['errors'][] = [
  66.                     'message' => $error->getMessage(),
  67.                     'pointer' => $error->getPropertyPath(),
  68.                 ];
  69.             }
  70.             $response = new JsonResponse($responseDataResponse::HTTP_UNPROCESSABLE_ENTITY);
  71.         }
  72.         $event->setResponse($response);
  73.     }
  74.     private function handleException(ExceptionEvent $event): void
  75.     {
  76.         $exception $event->getThrowable();
  77.         if ($exception instanceof HandlerFailedException) {
  78.             $exception $exception->getPrevious();
  79.         }
  80.         if ($exception instanceof HttpExceptionInterface) {
  81.             $code Response::HTTP_NOT_FOUND;
  82.             $message 'Resource was not found!';
  83.         } else {
  84.             $code Response::HTTP_INTERNAL_SERVER_ERROR;
  85.             $message 'Oops... Something went wrong...';
  86.             try {
  87.                 // $this->logger->error($exception->getMessage(), Log::SOURCE_GLOBAL);
  88.             } catch (ORMException|ModelValidationException $e) { // EntityManager is closed or log is incorrect
  89.                 //
  90.             }
  91.         }
  92.         $this->session->set('error.code'$code);
  93.         $this->session->set('error.message'$message);
  94.         $response = new RedirectResponse($this->router->generate('site_error'));
  95.         $event->setResponse($response);
  96.     }
  97.     private function isApiException(ExceptionEvent $event)
  98.     {
  99.         return strpos($event->getRequest()->getRequestUri(), 'api') !== false;
  100.     }
  101.     /**
  102.      * @return array<string, mixed>
  103.      */
  104.     public static function getSubscribedEvents(): array
  105.     {
  106.         return [\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION => 'onKernelException'];
  107.     }
  108. }