<?php
declare(strict_types=1);
namespace App\Subscriber;
use App\Service\Exception\ExceptionJsonLogger;
use App\Service\Exception\Handler\ExceptionHandler;
use ReflectionClass;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ExceptionEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Messenger\Exception\HandlerFailedException;
class ExceptionSubscriber implements EventSubscriberInterface
{
private ExceptionHandler $exceptionHandler;
private ExceptionJsonLogger $jsonLogger;
public function __construct(ExceptionHandler $exceptionHandler, ExceptionJsonLogger $jsonLogger)
{
$this->exceptionHandler = $exceptionHandler;
$this->jsonLogger = $jsonLogger;
}
public static function getSubscribedEvents(): array
{
return [KernelEvents::EXCEPTION => ['onKernelException', -127]];
}
public function onKernelException(ExceptionEvent $event): void
{
$exception = $event->getThrowable();
if ($exception instanceof HandlerFailedException) {
$exception = $exception->getNestedExceptions()[0];
}
$reflection = new ReflectionClass($exception);
$exceptionName = $reflection->getName();
$match = str_contains($exceptionName, "App\Exception");
$additionalInfo = $this->checkEventParameters($event,$exception) ?: [];
if ($match === true){
$this->jsonLogger->multiLogger($exception, $additionalInfo);
}
$httpStatusCode = (new \ReflectionClass($exception))->hasMethod('getStatusCode') ? $exception->getStatusCode() : Response::HTTP_INTERNAL_SERVER_ERROR;
$exceptionDTO = $this->exceptionHandler->handle($exception);
$response = new JsonResponse($exceptionDTO->toArray(), $httpStatusCode);
$event->setResponse($response);
}
public function checkEventParameters($event, $exception): array
{
$additionalInfo = [];
$parameters = $event->getRequest()->attributes;
if (!is_null($parameters->get('orderId'))){
$additionalInfo[] = ['orderId' => $parameters->get('orderId')];
}
if (!is_null($parameters->get('cinemaId'))){
$additionalInfo[] = ['cinemaId' => $parameters->get('cinemaId')];
}
if (!is_null($parameters->get('paymentProvider'))){
$additionalInfo[] = ['paymentProvider' => $parameters->get('paymentProvider')];
}
if (!is_null($parameters->get('providerId'))){
$additionalInfo[] = ['providerId' => $parameters->get('providerId')];
}
if (!is_null($parameters->get('screeningsId'))){
$additionalInfo[] = ['screeningsId' => $parameters->get('screeningsId')];
}
if (!is_null($parameters->get('screeningItemId'))){
$additionalInfo[] = ['screeningItemId' => $parameters->get('screeningItemId')];
}
if (!is_null($parameters->get('paymentMethodId'))){
$additionalInfo[] = ['paymentMethodId' => $parameters->get('paymentMethodId')];
}
if (!is_null($parameters->get('bookingId'))){
$additionalInfo[] = ['bookingId' => $parameters->get('bookingId')];
}
if (!is_null($parameters->get('itemId'))){
$additionalInfo[] = ['itemId' => $parameters->get('itemId')];
}
if (!is_null($parameters->get('groupId'))){
$additionalInfo[] = ['groupId' => $parameters->get('groupId')];
}
if (!is_null($parameters->get('promotion'))){
$additionalInfo[] = ['promotion' => $parameters->get('promotion')];
}
if (!is_null($parameters->get('pickupTimeId'))){
$additionalInfo[] = ['pickupTimeId' => $parameters->get('pickupTimeId')];
}
if (!empty($event->getRequest()->request->all())){
$additionalInfo[] = ['request' => $event->getRequest()->request->all()];
}
$reflection = new ReflectionClass($exception);
if ($reflection->hasMethod('getProperties') && !empty($exception->getProperties())){
$additionalInfo[] = $exception->getProperties();
}
return $additionalInfo;
}
}