<?php
namespace Familia2\Infrastructure\Listeners;
use Exception;
use Familia2\Application\Services\Error\ErrorResponse;
use Familia2\Application\Services\Error\ExceptionError;
use Familia2\Application\Services\Exceptions\RequestException;
use Familia2\Infrastructure\EventLogger\EventLogger;
use JMS\Serializer\Serializer;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\Translation\TranslatorInterface;
class ApiExceptionListener
{
/**
* @var Serializer $serializer
*/
private $serializer;
/**
* @var EventLogger $eventLogger
*/
private $eventLogger;
/**
* @var ContainerInterface $container
*/
private $container;
/**
* @var TranslatorInterface $translator
*/
private $translator;
/**
* @param Serializer $serializer
* @param EventLogger $eventLogger
* @param ContainerInterface $container
* @param TranslatorInterface $translator
*/
public function __construct(
Serializer $serializer,
EventLogger $eventLogger,
ContainerInterface $container,
TranslatorInterface $translator
) {
$this->serializer = $serializer;
$this->eventLogger = $eventLogger;
$this->container = $container;
$this->translator = $translator;
}
/**
* @param $event
*
* @throws Exception
*/
public function onKernelException(GetResponseForExceptionEvent $event)
{
if (strpos($event->getRequest()->getUri(), '/api') !== false) {
$exception = $event->getException();
if ($exception instanceof RequestException) {
$errors = $exception->getErrors();
$exceptionCode = $exception->getCode();
} elseif ($exception instanceof InsufficientAuthenticationException) {
$unauthorizedError = new ExceptionError(
$this->translator->trans('error.session.unauthorized', [], 'validators')
);
$errors = ErrorResponse::forError($unauthorizedError);
$exceptionCode = Response::HTTP_UNAUTHORIZED;
} else {
$this->eventLogger->log($exception);
$errors = ErrorResponse::forError(new ExceptionError($exception->getMessage()));
$exceptionCode = $exception->getCode();
if (!isset(Response::$statusTexts[$exceptionCode])) {
$exceptionCode = Response::HTTP_INTERNAL_SERVER_ERROR;
}
}
$errors = $this->serializer->serialize($errors, 'json');
$event->setResponse(new Response($errors, $exceptionCode));
} elseif ($event->getException() instanceof NotFoundHttpException) {
$event->setResponse(new RedirectResponse($this->container->getParameter('path.front.404_error')));
}
}
}