src/Front/EventSubscriber/CustomerExceptionSubscriber.php line 39

  1. <?php
  2. namespace App\Front\EventSubscriber;
  3. use Symfony\Component\EventDispatcher\EventSubscriberInterface,
  4.     Symfony\Component\HttpFoundation\Request,
  5.     Symfony\Component\HttpFoundation\JsonResponse,
  6.     Symfony\Component\HttpKernel\Event\ExceptionEvent,
  7.     Symfony\Component\HttpKernel\KernelEvents,
  8.     Symfony\Component\HttpKernel\Exception\HttpException,
  9.     Symfony\Component\HttpKernel\Exception\NotFoundHttpException,
  10.     Symfony\Contracts\Translation\TranslatorInterface,
  11.     Symfony\Component\Security\Http\FirewallMapInterface,
  12.     Symfony\Component\DependencyInjection\Attribute\Autowire;
  13. use App\Front\Exception\FrontApiException,
  14.     App\Front\Exception\FrontApiValidationException;
  15. class CustomerExceptionSubscriber implements EventSubscriberInterface
  16. {
  17.     private const REQUEST_FIREWALL_CONTEXT_ATTRIBUTE '_firewall_context';
  18.     private const CUSTOMER_FIREWALL_NAME 'customer';
  19.     public function __construct(
  20.         private readonly TranslatorInterface $translator,
  21.         private readonly FirewallMapInterface $firewallMap,
  22.         #[Autowire('%kernel.environment%')]
  23.         private readonly string $env
  24.     ) {}
  25.     public static function getSubscribedEvents()
  26.     {
  27.         return [
  28.             KernelEvents::EXCEPTION => [
  29.                 ['process'0]
  30.             ],
  31.         ];
  32.     }
  33.     public function process(ExceptionEvent $event): void
  34.     {
  35.         $request $event->getRequest();
  36.         $exception $event->getThrowable();
  37.         if (! $this->supports($request$exception)) {
  38.             return;
  39.         }
  40.         /** @var HttpException */
  41.         $exception $event->getThrowable();
  42.         $message 'Error';
  43.         switch(true) {
  44.             case $exception instanceof NotFoundHttpException:
  45.                 $message $this->translator->trans('Not found.');
  46.                 break;
  47.             case $exception instanceof FrontApiException:
  48.             case in_array($this->env, ['dev''test']):
  49.                 $message $exception->getMessage();
  50.                 break;
  51.             default:
  52.                 break;
  53.         }
  54.         $data['message'] = $message;
  55.         if ($exception instanceof FrontApiValidationException) {
  56.             $data['violations'] = $exception->getViolationsMessages();
  57.         }
  58.         $event->setResponse(
  59.             new JsonResponse(
  60.                 data$data,
  61.                 status$exception->getStatusCode()
  62.             )
  63.         );
  64.     }
  65.     private function getFirewallName(Request $request): ?string
  66.     {
  67.         if (! $context $request->attributes->get(self::REQUEST_FIREWALL_CONTEXT_ATTRIBUTE)) {
  68.             return null;
  69.         }
  70.         $contextPath explode('.'$context);
  71.         return end($contextPath);
  72.     }
  73.     private function isCustomerFirewall(Request $request): bool
  74.     {
  75.         return $this->getFirewallName($request) === self::CUSTOMER_FIREWALL_NAME;
  76.     }
  77.     private function isContentTypeJson(Request $request): bool
  78.     {
  79.         return $request->getContentTypeFormat() === 'json';
  80.     }
  81.     private function isOnlyJsonAcceptable(Request $request): bool
  82.     {
  83.         $acceptableTypes $request->getAcceptableContentTypes();
  84.         return count($acceptableTypes) === && $acceptableTypes[0] === 'application/json';
  85.     }
  86.     private function supports(Request $requestmixed $exception): bool
  87.     {
  88.         return $this->isCustomerFirewall($request) && $exception instanceof HttpException && (
  89.             $this->isContentTypeJson($request) || $this->isOnlyJsonAcceptable($request)
  90.         );
  91.     }
  92. }