<?php
namespace App\System\Listener\Response;
use App\System\Validation\ConstraintsViolationException;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\Validator\ConstraintViolationInterface;
use Throwable;
class ResponseExceptionListener
{
public function onKernelException(ExceptionEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$exception = $event->getThrowable();
if ($exception instanceof ConstraintsViolationException) {
$content = $this->normalizeConstraintsViolation($exception);
$code = Response::HTTP_UNPROCESSABLE_ENTITY;
} else {
$content = $this->normalizeUseCaseException($exception);
$code = Response::HTTP_BAD_REQUEST;
}
$response = new JsonResponse();
$response
->setStatusCode($code)
->setContent(json_encode($content));
$event->setResponse($response);
}
private function normalizeConstraintsViolation(ConstraintsViolationException $exception): array
{
$violations = [];
foreach ($exception->getConstraints() as $constraint) {
/* @var ConstraintViolationInterface $constraint */
$violations[] = [
'propertyPath' => $constraint->getPropertyPath(),
'title' => $constraint->getMessage(),
'parameters' => [],
];
}
return [
'title' => 'constraints violation',
'status' => 422,
'detail' => $exception->getMessage(),
'codes' => [],
'violations' => $violations,
];
}
private function normalizeUseCaseException(Throwable $exception): array
{
return [
'title' => 'Bad Request',
'status' => 400,
'detail' => $exception->getMessage(),
'codes' => $exception->getCode(),
'violations' => [],
];
}
}