vendor/launchpad/backend/src/Base/EventListener/AppExceptionListener.php line 37

Open in your IDE?
  1. <?php
  2. namespace LaunchPad\Bundle\LaunchPadBundle\Base\EventListener;
  3. use LaunchPad\Bundle\LaunchPadBundle\Base\Exception\AppClientException;
  4. use LaunchPad\Bundle\LaunchPadBundle\Base\Exception\MissingApiParamsException;
  5. use Symfony\Component\DependencyInjection\Container;
  6. use Symfony\Component\DependencyInjection\ContainerInterface;
  7. use Symfony\Component\HttpFoundation\JsonResponse;
  8. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  9. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  10. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  11. use Symfony\Component\HttpKernel\KernelInterface;
  12. use Throwable;
  13. class AppExceptionListener
  14. {
  15.     /**
  16.      * @var Container
  17.      */
  18.     private $container;
  19.     /**
  20.      * @param ContainerInterface $container
  21.      */
  22.     public function __construct(ContainerInterface $container)
  23.     {
  24.         $this->container $container;
  25.     }
  26.     /**
  27.      * Intercept exceptions
  28.      *
  29.      * @param ExceptionEvent $event
  30.      * @return void
  31.      * @throws \Exception
  32.      */
  33.     public function onKernelException(ExceptionEvent $event): void
  34.     {
  35.         $exception $event->getThrowable();
  36.         if (!$this->isApiCall($event)) {
  37.             return;
  38.         }
  39.         $responseData = [
  40.             'success' => false,
  41.             'data' => null,
  42.             'errors' => $exception instanceof MissingApiParamsException
  43.                 $exception->getErrors()
  44.                 : [],
  45.             'message' => $this->getApiExceptionMessage($exception),
  46.             'code' => $exception->getCode() ?: 500,
  47.         ];
  48.         if ($this->inDebugMode()) {
  49.             $responseData['debug'] = [
  50.                 'trace' => $exception->getTraceAsString(),
  51.                 'message' => $exception->getMessage(),
  52.             ];
  53.         }
  54.         $response = new JsonResponse($responseData);
  55.         $response->headers->set('Content-Type''application/json');
  56.         $response->setStatusCode($this->getHttpCodeForException($exception));
  57.         $event->allowCustomResponseCode();
  58.         $event->setResponse($response);
  59.     }
  60.     /**
  61.      * Get api exception message - different for def and prod environments
  62.      *
  63.      * @param Throwable $exception
  64.      * @return string
  65.      * @throws \Exception
  66.      */
  67.     private function getApiExceptionMessage(Throwable $exception): string
  68.     {
  69.         return $exception instanceof AppClientException || $this->inDebugMode()
  70.             ? $exception->getMessage()
  71.             : 'An error ocurred, please try again later';
  72.     }
  73.     /**
  74.      * Check if exception occurred during API call
  75.      *
  76.      * @param ExceptionEvent $event
  77.      * @return bool
  78.      */
  79.     private function isApiCall(ExceptionEvent $event): bool
  80.     {
  81.         $request $event->getRequest();
  82.         if (strpos($request->get('_controller'), '\\Api\\') !== false) {
  83.             return true;
  84.         }
  85.         return strpos($request->headers->get('Content-Type'), '/json') !== false;
  86.     }
  87.     /**
  88.      * Check if in debug mode
  89.      *
  90.      * @return bool
  91.      * @throws \Exception
  92.      */
  93.     private function inDebugMode(): bool
  94.     {
  95.         if ($this->container->hasParameter('debug')
  96.             && $this->container->getParameter('debug') === true
  97.         ) {
  98.             return true;
  99.         }
  100.         /** @var KernelInterface $kernel */
  101.         $kernel $this->container->get('kernel');
  102.         return $kernel->getEnvironment() === 'dev';
  103.     }
  104.     /**
  105.      * Get HTTP code for exception
  106.      *
  107.      * @param Throwable $exception
  108.      * @return int
  109.      */
  110.     private function getHttpCodeForException(Throwable $exception): int
  111.     {
  112.         if ($exception instanceof AppClientException) {
  113.             return 200;
  114.         }
  115.         if ($exception instanceof AccessDeniedHttpException) {
  116.             return 403;
  117.         }
  118.         return 500;
  119.     }
  120. }