src/Framework/EventListener/APIExceptionEventListener.php line 22

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace App\Framework\EventListener;
  3. use App\Framework\Exception\APIException;
  4. use App\Framework\Exception\AssertionException;
  5. use App\Framework\Exception\TalloException;
  6. use Doctrine\ORM\EntityNotFoundException;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  9. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  10. class APIExceptionEventListener
  11. {
  12.     private string $env;
  13.     public function __construct(string $env)
  14.     {
  15.         $this->env $env;
  16.     }
  17.     public function onException(ExceptionEvent $event): void
  18.     {
  19.         $debug true;
  20.         // TODO: Any exception that is not a user-facing error should be logged and not sent in production environment!!!!
  21.         // Only intercept requests that are accepting json as response
  22.         $request $event->getRequest();
  23.         if (!in_array('application/json'$request->getAcceptableContentTypes(), true)) {
  24.             return;
  25.         }
  26.         $statusCode 500;
  27.         $result = [];
  28.         $exception $event->getThrowable();
  29.         // Handle API Exceptions more gracefully, as 400 (Client errors)
  30.         if ($exception instanceof APIException) {
  31.             $statusCode 400;
  32.             $result = [
  33.                 'type' => $exception->getMessage(),
  34.                 'errors' => $exception->getErrors(),
  35.             ];
  36.             if ($debug) {
  37.                 $result['debug'] = $exception->getDebugData();
  38.             }
  39.         } elseif ($exception instanceof EntityNotFoundException) {
  40.             $statusCode 400;
  41.             $result = [
  42.                 'code' => 'error.entity.notfound',
  43.                 'message' => $exception->getMessage(),
  44.             ];
  45.         } elseif ($exception instanceof AssertionException) {
  46.             $statusCode 500;
  47.             $result = [
  48.                 'type' => 'assert.failed',
  49.                 'errors' => $exception->getErrors(),
  50.             ];
  51.         } elseif ($exception instanceof AccessDeniedHttpException) {
  52.             $statusCode 403;
  53.             $result = [
  54.                 'type' => 'error',
  55.                 'code' => 'error.authorization.rejected',
  56.                 'message' => $exception->getCode(),
  57.                 'errors' => $exception->getMessage(),
  58.             ];
  59.         } elseif ($exception instanceof TalloException) {
  60.             $statusCode 400;
  61.             $result = [
  62.                 'type' => 'error',
  63.                 'code' => $exception->getCode(),
  64.                 'message' => $exception->getCode(),
  65.                 'errors' => $exception->getErrors(),
  66.             ];
  67.         } else {
  68.             // DEBUG mode?
  69.             $statusCode 500;
  70.             $result = [
  71.                 'type' => 'Error',
  72.                 'code' => $exception->getCode(),
  73.                 'message' => $exception->getMessage(),
  74.             ];
  75.         }
  76.         // Add the stack trace in debug
  77.         if ($this->env === 'dev') {
  78.             $result['trace'] = $exception->getTraceAsString();
  79.         }
  80.         $response = new JsonResponse($result$statusCode);
  81.         $response->setEncodingOptions(JSON_UNESCAPED_UNICODE);
  82.         $event->setResponse($response);
  83.     }
  84. }