<?php
declare(strict_types=1);
namespace App\EventSubscriber;
use App\Controller\Response\MicroServiceApiResponse;
use App\Utils\RequestHelper;
use App\Domain\Payload\Error;
use App\Exception\ApiException;
use App\Domain\Payload\Payload;
use App\Domain\Payload\ErrorCollection;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Response;
use App\Controller\Response\GetPayloadInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use App\Controller\Response\ValidationErrorApiResponse;
use App\Services\ErrorHandling\ApiErrorResponseHandler;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use InvalidArgumentException;
class ApiErrorHandlingSubscriber implements EventSubscriberInterface
{
/**
* @var RequestHelper
*/
private $requestHelper;
/**
* @var ApiErrorResponseHandler
*/
private $errorResponseHandler;
public function __construct(RequestHelper $requestHelper, ApiErrorResponseHandler $errorResponseHandler)
{
$this->requestHelper = $requestHelper;
$this->errorResponseHandler = $errorResponseHandler;
}
/**
* @throws InvalidArgumentException
*/
public function onKernelResponse(ResponseEvent $event): void
{
$response = $event->getResponse();
if ($this->requestHelper->isV1Route()) {
return;
}
if ($response instanceof MicroServiceApiResponse) {
return;
}
if ($response instanceof GetPayloadInterface && $response->getPayload()->hasError()) {
$payload = $response->getPayload();
$error = $payload->getError();
if ($error instanceof Error && $error->getData() instanceof ErrorCollection) {
$payload->setErrors($error->getData()->getErrors());
}
$event->setResponse(
$this->errorResponseHandler->handle(
ApiException::createBusinessLogicException($payload)
)
);
return;
}
if ($response instanceof ValidationErrorApiResponse) {
$response->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY);
$event->setResponse($response);
return;
}
if ($response instanceof Response && $response->getStatusCode() === Response::HTTP_UNAUTHORIZED) {
$content = json_decode($response->getContent() ?? '{}', true);
$payload = new Payload();
$payload->setError(new Error(0, $content['error_description'] ?? 'OAuth2 authentication required'));
$event->setResponse(
$this->errorResponseHandler->handle(
ApiException::createUnauthorizedException($payload)
)
);
}
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => ['onKernelResponse', 2],
];
}
}