<?php
declare(strict_types=1);
namespace App\EventListener;
use Neomerx\JsonApi\Document\Document;
use Neomerx\JsonApi\Document\Error;
use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
final class ExceptionSubscriber implements EventSubscriberInterface
{
private const EXCEPTION_STATUS_MAP = [
AuthenticationCredentialsNotFoundException::class => 401,
];
public static function getSubscribedEvents(): array
{
return [
KernelEvents::EXCEPTION => [
['onKernelException', -100],
],
];
}
public function onKernelException(GetResponseForExceptionEvent $event): void
{
$document = new Document();
$error = new Error();
$exception = $event->getException();
$exceptionClass = \get_class($exception);
$exception = FlattenException::create($exception);
$statusCode = self::EXCEPTION_STATUS_MAP[$exceptionClass] ?? $exception->getStatusCode();
$error->setStatus((string) $statusCode);
$error->setTitle(JsonResponse::$statusTexts[$statusCode] ?? null);
$document->addError($error);
$document->addJsonApiVersion('1.0');
$event->setResponse(new JsonResponse($document->getDocument(), $statusCode, [
'Content-Type' => 'application/vnd.api+json',
]));
}
}