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.         $response->headers->set('Access-Control-Allow-Origin''*');
  58.         $response->headers->set('Access-Control-Allow-Methods''GET, POST, PUT, DELETE, OPTIONS');
  59.         $response->headers->set('Access-Control-Allow-Headers''Authorization, Content-Type');
  60.         $event->allowCustomResponseCode();
  61.         $event->setResponse($response);
  62.     }
  63.     /**
  64.      * Get api exception message - different for def and prod environments
  65.      *
  66.      * @param Throwable $exception
  67.      * @return string
  68.      * @throws \Exception
  69.      */
  70.     private function getApiExceptionMessage(Throwable $exception): string
  71.     {
  72.         return $exception instanceof AppClientException || $this->inDebugMode()
  73.             ? $exception->getMessage()
  74.             : 'An error ocurred, please try again later';
  75.     }
  76.     /**
  77.      * Check if exception occurred during API call
  78.      *
  79.      * @param ExceptionEvent $event
  80.      * @return bool
  81.      */
  82.     private function isApiCall(ExceptionEvent $event): bool
  83.     {
  84.         $request $event->getRequest();
  85.         if (strpos($request->get('_controller'), '\\Api\\') !== false) {
  86.             return true;
  87.         }
  88.         return strpos($request->headers->get('Content-Type'), '/json') !== false;
  89.     }
  90.     /**
  91.      * Check if in debug mode
  92.      *
  93.      * @return bool
  94.      * @throws \Exception
  95.      */
  96.     private function inDebugMode(): bool
  97.     {
  98.         if ($this->container->hasParameter('debug')
  99.             && $this->container->getParameter('debug') === true
  100.         ) {
  101.             return true;
  102.         }
  103.         /** @var KernelInterface $kernel */
  104.         $kernel $this->container->get('kernel');
  105.         return $kernel->getEnvironment() === 'dev';
  106.     }
  107.     /**
  108.      * Get HTTP code for exception
  109.      *
  110.      * @param Throwable $exception
  111.      * @return int
  112.      */
  113.     private function getHttpCodeForException(Throwable $exception): int
  114.     {
  115.         if ($exception instanceof AppClientException) {
  116.             return 200;
  117.         }
  118.         if ($exception instanceof AccessDeniedHttpException) {
  119.             return 403;
  120.         }
  121.         return 500;
  122.     }
  123. }