<?php
/**
*
* (c) BonBonSlick
*
*/
declare(strict_types=1);
namespace App\Subscribers;
use App\Exceptions\UserNotFoundException;
use function get_class;
use function in_array;
use Psr\Log\LoggerInterface;
use function sprintf;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Class self
*/
final class ExceptionEventSubscriber implements EventSubscriberInterface
{
/**
* @var LoggerInterface
*/
private $logger;
/**
* @var RouterInterface
*/
private $router;
/**
* ExceptionListener constructor.
*
* @param LoggerInterface $logger
* @param RouterInterface $router
*/
public function __construct(LoggerInterface $logger, RouterInterface $router)
{
$this->logger = $logger;
$this->router = $router;
}
/**
* {@inheritdoc]
*/
public static function getSubscribedEvents(): array
{
// return the subscribed events, their methods and priorities
return [
KernelEvents::EXCEPTION => [
['processException', 10],
],
];
}
/**
* @param GetResponseForExceptionEvent $event
*
* @return void
*/
public function processException(GetResponseForExceptionEvent $event): void
{
// don't do anything if it's not the master request
if (false === $event->isMasterRequest()) {
return;
}
// return json if json request
$exception = $event->getException();
// dump($exception);
// die;
if (UserNotFoundException::class === get_class($exception)) {
$response = new JsonResponse(
['error' => true, 'message' => $exception->getMessage()],
Response::HTTP_NOT_FOUND
);
$response->headers->set('Content-Type', 'application/problem+json');
$event->setResponse($response);
return;
}
if (AccessDeniedException::class === get_class($exception)) {
$url = $this->router->generate('admin.login');
$response = new RedirectResponse($url);
$event->setResponse($response);
return;
}
$isExceptionClassInExcludedExceptions = in_array(get_class($exception), $this->skipExceptions(), true);
if (true === $isExceptionClassInExcludedExceptions) {
$response = new JsonResponse(
['error' => true, 'message' => $exception->getMessage()],
true === array_key_exists($exception->getCode(), Response::$statusTexts) ?
$exception->getCode() : Response::HTTP_INTERNAL_SERVER_ERROR
);
$response->headers->set('Content-Type', 'application/problem+json');
$event->setResponse($response);
}
// do nothing if in excluded
if (true === $isExceptionClassInExcludedExceptions) {
return;
}
// Send the modified response object to the event and log exception
$logMessage = sprintf(
'EXCEPTION %s. Message: %s. Code: %s',
$exception->getFile(),
$exception->getMessage(),
$exception->getCode()
);
$this->logger->error($logMessage);
$message = 'Something went wrong.';
$url = $this->router->generate('homep404');
$response = new RedirectResponse($url);
// $response = new JsonResponse(
// ['error' => true, 'message' => $message],
// Response::HTTP_INTERNAL_SERVER_ERROR
// );
// $response->headers->set('Content-Type', 'application/problem+json');
// $event->setResponse($response);
}
/**
* Avoid logging these exceptions
*
* @return string[]
*/
private function skipExceptions(): array
{
return [
AccessDeniedException::class,
UnsupportedUserException::class,
UserNotFoundException::class,
CustomUserMessageAuthenticationException::class,
AuthenticationException::class,
];
}
}