<?php
namespace App\EventListener;
use App\Exception\ApiExceptionInterface;
use Doctrine\ODM\MongoDB\DocumentManager;
use Exception;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Contracts\Translation\TranslatorInterface;
use Throwable;
use Twig\Environment;
class ApiExceptionListener
{
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var Environment
*/
private $twig;
/**
* ApiExceptionListener constructor.
* @param Environment $twig
* @param DocumentManager $documentManager
* @param TranslatorInterface $translator
*/
public function __construct(Environment $twig,
DocumentManager $documentManager,
TranslatorInterface $translator
)
{
$this->translator = $translator;
$this->twig = $twig;
}
/**
* @param ExceptionEvent $event
* @return bool
* @throws Exception
*/
public function onKernelException(ExceptionEvent $event)
{
$statusCode = 500;
if ($event->getThrowable() instanceof ApiExceptionInterface) {
$statusCode = $event->getThrowable()->getCode();
}
if (!$event->getRequest()->attributes->get("_controller")) {
return false;
}
$system = explode('\\', $event->getRequest()->attributes->get("_controller"))[2];
$contentType = $event->getRequest()->headers->get('Content-Type');
if ($system == 'Api') {
$response = $this->buildResponseData($event->getThrowable());
$jsonResponse = new JsonResponse($response);
$jsonResponse->setStatusCode($statusCode);
$event->setResponse($jsonResponse);
} else {
$viewResponse = $this->twig->render('error/' . $statusCode . '.html.twig', $this->buildResponseData($event->getThrowable()));
$event->setResponse(new Response($viewResponse));
}
return true;
}
/**
* @param Throwable $exception
* @return array
*/
private function buildResponseData(Throwable $exception)
{
$response = $this::normalizeException($exception);
if (get_class($exception) !== 'Booklogic\CoreBundle\Exception\ValidationException') {
$response['error']['message'] = $this->translator->trans($response['error']['message'], [], 'exceptions');
}
return $response;
}
public static function normalizeException(Throwable $exception)
{
$customMessage = json_decode($exception->getMessage(), 1);
if (is_array($customMessage)) {
$message = $customMessage['message'];
$code = $customMessage['code'];
if (isset($customMessage['audit'])) {
$audit = $customMessage['audit'];
}
} else {
$message = $exception->getMessage();
$code = $exception->getCode();
}
$response = [
'error' => [
'code' => (string)$code,
'message' => $message,
]
];
if ($_ENV['APP_ENV'] == 'dev') {
$response['error']['detail'] = [
'file' => $exception->getFile(),
'line' => $exception->getLine(),
];
}
if (isset($audit)) {
$response['audit'] = $audit;
}
return $response;
}
}