src/EventListener/ExceptionListener.php line 40

Open in your IDE?
  1. <?php
  2. namespace App\EventListener;
  3. use App\Exception\ApiAccessDeniedException;
  4. use App\Exception\VerboseExceptionInterface;
  5. use Symfony\Component\ErrorHandler\Exception\FlattenException;
  6. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  11. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  12. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  13. use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
  14. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  15. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  16. use Symfony\Component\HttpKernel\KernelEvents;
  17. use Symfony\Component\HttpKernel\KernelInterface;
  18. class ExceptionListener implements EventSubscriberInterface
  19. {
  20.     /**
  21.      * @var KernelInterface
  22.      */
  23.     private $kernel;
  24.     public function __construct(KernelInterface $kernel)
  25.     {
  26.         $this->kernel $kernel;
  27.     }
  28.     public static function getSubscribedEvents(): array
  29.     {
  30.         return [
  31.             KernelEvents::EXCEPTION => 'onKernelException',
  32.         ];
  33.     }
  34.     public function onKernelException(ExceptionEvent $event): void
  35.     {
  36.         if (!$event->isMasterRequest()) {
  37.             return;
  38.         }
  39.         if (!$event->getRequest() instanceof Request || $event->getRequest()->getRequestFormat() !== 'json') {
  40.             return;
  41.         }
  42.         $exception $event->getThrowable();
  43.         $response = [
  44.             'error' => '',
  45.             'code' => Response::HTTP_BAD_REQUEST,
  46.             'message' => null,
  47.         ];
  48.         $exceptionInterfaces class_implements(\get_class($exception));
  49.         if (
  50.             isset($exceptionInterfaces[HttpExceptionInterface::class]) &&
  51.             method_exists($exception'getStatusCode')
  52.         ) {
  53.             // our exception is a HttpException, get status code from it
  54.             /* @var HttpExceptionInterface $exception */
  55.             $response['code'] = $exception->getStatusCode();
  56.             if (
  57.                 $exception instanceof NotFoundHttpException &&
  58.                 strpos($exception->getMessage(), 'No route found') !== false
  59.             ) {
  60.                 // Invalid route.
  61.                 $response['error'] = 'Invalid request.';
  62.             } elseif ($exception instanceof AccessDeniedHttpException || $exception instanceof ApiAccessDeniedException) {
  63.                 $response['error'] = $exception->getMessage() === 'Token issue' $exception->getMessage() : 'Not allowed, insufficient permissions.';
  64.                 $response['message'] = $exception->getMessage();
  65.             }
  66.         } else {
  67.             $response['code'] = $exception->getCode() === Response::HTTP_INTERNAL_SERVER_ERROR $exception->getCode();
  68.             if (!$this->kernel->isDebug()) {
  69.                 $response['error'] = '';
  70.             }
  71.         }
  72.         if ($response['error'] === '' && isset(Response::$statusTexts[$response['code']])) {
  73.             $response['error'] = Response::$statusTexts[$response['code']];
  74.         }
  75.         if (
  76.             isset($exceptionInterfaces[VerboseExceptionInterface::class]) &&
  77.             method_exists($exception'getExtraData')
  78.         ) {
  79.             /* @var VerboseExceptionInterface $exception */
  80.             $response['errors'] = $exception->getExtraData();
  81.         }
  82.         if ($exception instanceof ConflictHttpException) {
  83.             $response['message'] = $exception->getMessage();
  84.             $response['error'] = $exception->getMessage();
  85.         }
  86.         if ($exception instanceof BadRequestHttpException) {
  87.             $response['message'] = $exception->getMessage();
  88.             $response['error'] = $exception->getMessage();
  89.         }
  90.         // give some more feedback in debug mode :-)
  91.         if ($this->kernel->isDebug()) {
  92.             $response['debug'] = [
  93.                 'line' => $exception->getLine(),
  94.                 'file' => $exception->getFile(),
  95.                 'exception' => FlattenException::createFromThrowable($exception)->toArray(),
  96.             ];
  97.         }
  98.         if ($this->kernel->isDebug()) {
  99.             unset($response['message']);
  100.         }
  101.         $event->setResponse(new JsonResponse($response$response['code']));
  102.     }
  103. }