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

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