src/Infrastructure/EventListener/ExceptionListener.php line 40

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. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  20. use Throwable;
  21. class ExceptionListener
  22. {
  23.     private RouterInterface $router;
  24.     private SessionInterface $session;
  25.     private DbLogger $logger;
  26.     public function __construct(
  27.         RouterInterface $router,
  28.         SessionInterface $session,
  29.         DbLogger $logger
  30.     ) {
  31.         $this->router  $router;
  32.         $this->session $session;
  33.         $this->logger  $logger;
  34.     }
  35.     public function onKernelException(ExceptionEvent $event): void
  36.     {
  37.         // Disabling listener in dev env (but not in ajax requests) to get detailed error messages
  38.         if ($_ENV['APP_ENV'] === 'dev' && !$this->isApiException($event)) return;
  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.         }
  53.         $response  = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_INTERNAL_SERVER_ERROR);
  54.         if ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) {
  55.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_NOT_FOUND);
  56.         }
  57.         if ($exception instanceof BadRequestHttpException) {
  58.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_BAD_REQUEST);
  59.         }
  60.         if ($exception instanceof AccessDeniedHttpException) {
  61.             $response = new JsonResponse(['message' => $exception->getMessage()], Response::HTTP_FORBIDDEN);
  62.         }
  63.         if ($exception instanceof ModelValidationException) {
  64.             $responseData = ['errors' => []];
  65.             foreach ($exception->getErrors() as $error) {
  66.                 $responseData['errors'][] = [
  67.                     'message' => $error->getMessage(),
  68.                     'pointer' => $error->getPropertyPath()
  69.                 ];
  70.             }
  71.             $response = new JsonResponse($responseDataResponse::HTTP_UNPROCESSABLE_ENTITY);
  72.         }
  73.         $event->setResponse($response);
  74.     }
  75.     /**
  76.      * @param ExceptionEvent $event
  77.      */
  78.     private function handleException(ExceptionEvent $event): void
  79.     {
  80.         $exception $event->getThrowable();
  81.         if ($exception instanceof HandlerFailedException) {
  82.             $exception $exception->getPrevious();
  83.         }
  84.         if ($exception instanceof HttpExceptionInterface) {
  85.             $code    Response::HTTP_NOT_FOUND;
  86.             $message "Resource was not found!";
  87.         } else {
  88.             $code    Response::HTTP_INTERNAL_SERVER_ERROR;
  89.             $message "Oops... Something went wrong...";
  90.             try {
  91.                 //$this->logger->error($exception->getMessage(), Log::SOURCE_GLOBAL);
  92.             } catch (ORMException ModelValidationException $e) { // EntityManager is closed or log is incorrect
  93.                 //
  94.             }
  95.         }
  96.         $this->session->set('error.code'$code);
  97.         $this->session->set('error.message'$message);
  98.         $response = new RedirectResponse($this->router->generate('site_error'));
  99.         $event->setResponse($response);
  100.     }
  101.     private function isApiException(ExceptionEvent $event)
  102.     {
  103.         return strpos($event->getRequest()->getRequestUri(), 'api') !== false;
  104.     }
  105. }