src/Front/EventSubscriber/CustomerExceptionSubscriber.php line 39
<?php
namespace App\Front\EventSubscriber;
use Symfony\Component\EventDispatcher\EventSubscriberInterface,
Symfony\Component\HttpFoundation\Request,
Symfony\Component\HttpFoundation\JsonResponse,
Symfony\Component\HttpKernel\Event\ExceptionEvent,
Symfony\Component\HttpKernel\KernelEvents,
Symfony\Component\HttpKernel\Exception\HttpException,
Symfony\Component\HttpKernel\Exception\NotFoundHttpException,
Symfony\Contracts\Translation\TranslatorInterface,
Symfony\Component\Security\Http\FirewallMapInterface,
Symfony\Component\DependencyInjection\Attribute\Autowire;
use App\Front\Exception\FrontApiException,
App\Front\Exception\FrontApiValidationException;
class CustomerExceptionSubscriber implements EventSubscriberInterface
{
private const REQUEST_FIREWALL_CONTEXT_ATTRIBUTE = '_firewall_context';
private const CUSTOMER_FIREWALL_NAME = 'customer';
public function __construct(
private readonly TranslatorInterface $translator,
private readonly FirewallMapInterface $firewallMap,
#[Autowire('%kernel.environment%')]
private readonly string $env
) {}
public static function getSubscribedEvents()
{
return [
KernelEvents::EXCEPTION => [
['process', 0]
],
];
}
public function process(ExceptionEvent $event): void
{
$request = $event->getRequest();
$exception = $event->getThrowable();
if (! $this->supports($request, $exception)) {
return;
}
/** @var HttpException */
$exception = $event->getThrowable();
$message = 'Error';
switch(true) {
case $exception instanceof NotFoundHttpException:
$message = $this->translator->trans('Not found.');
break;
case $exception instanceof FrontApiException:
case in_array($this->env, ['dev', 'test']):
$message = $exception->getMessage();
break;
default:
break;
}
$data['message'] = $message;
if ($exception instanceof FrontApiValidationException) {
$data['violations'] = $exception->getViolationsMessages();
}
$event->setResponse(
new JsonResponse(
data: $data,
status: $exception->getStatusCode()
)
);
}
private function getFirewallName(Request $request): ?string
{
if (! $context = $request->attributes->get(self::REQUEST_FIREWALL_CONTEXT_ATTRIBUTE)) {
return null;
}
$contextPath = explode('.', $context);
return end($contextPath);
}
private function isCustomerFirewall(Request $request): bool
{
return $this->getFirewallName($request) === self::CUSTOMER_FIREWALL_NAME;
}
private function isContentTypeJson(Request $request): bool
{
return $request->getContentTypeFormat() === 'json';
}
private function isOnlyJsonAcceptable(Request $request): bool
{
$acceptableTypes = $request->getAcceptableContentTypes();
return count($acceptableTypes) === 1 && $acceptableTypes[0] === 'application/json';
}
private function supports(Request $request, mixed $exception): bool
{
return $this->isCustomerFirewall($request) && $exception instanceof HttpException && (
$this->isContentTypeJson($request) || $this->isOnlyJsonAcceptable($request)
);
}
}