<?php
declare(strict_types=1);
namespace App\Infrastructure\EventListener;
use ApiPlatform\Api\IriConverterInterface;
use ApiPlatform\Exception\ItemNotFoundException;
use App\Application\Service\Log\LogService;
use App\Domain\Entity\Activity;
use App\Domain\Entity\Award;
use App\Domain\Entity\Comment;
use App\Domain\Entity\Destination;
use App\Domain\Entity\DirectoryDepartment;
use App\Domain\Entity\Log;
use App\Domain\Entity\Offmap;
use App\Domain\Entity\Partner;
use App\Domain\Entity\Payment;
use App\Domain\Entity\PaymentLog;
use App\Domain\Entity\Person;
use App\Domain\Entity\PersonPointOfInterest;
use App\Domain\Entity\PointOfInterest;
use App\Domain\Entity\PointOfInterest\Picture;
use App\Domain\Entity\PointOfInterest\Revision;
use App\Domain\Entity\PressKit;
use App\Domain\Entity\PressStatement;
use App\Domain\Entity\PressVisualkit;
use App\Domain\Entity\PromoCode;
use App\Domain\Entity\RevisionLog;
use App\Domain\Entity\StatisticLog;
use App\Domain\Entity\Step;
use App\Domain\Entity\TeamMember;
use App\Domain\Entity\Trip;
use App\Domain\Entity\TripCategory;
use App\Domain\Entity\TripCountry;
use Doctrine\DBAL\Types\ConversionException;
use Doctrine\ORM\Event\PostPersistEventArgs;
use Exception;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Security;
class LogEventListener
{
private array $logEntities = [
Activity::class,
Award::class,
Comment::class,
Destination::class,
DirectoryDepartment::class,
Offmap::class,
Partner::class,
Payment::class,
Person::class,
PersonPointOfInterest::class,
Picture::class,
PointOfInterest::class,
PressKit::class,
PressStatement::class,
PressVisualkit::class,
PromoCode::class,
Step::class,
TeamMember::class,
Trip::class,
TripCategory::class,
TripCountry::class,
];
private array $logRoutes = [
'payment_export' => PaymentLog::EXPORT,
'get_revision' => StatisticLog::READ,
'get_activity' => StatisticLog::READ,
];
private array $excludeRoutes = [
'search_main_revisions',
'search_activities'
];
public function __construct(
public IriConverterInterface $converter,
public RouterInterface $router,
private readonly LogService $logService,
private readonly Security $security,
private readonly RequestStack $request,
) {}
/**
* @throws Exception
*/
public function onKernelView(RequestEvent $event): void
{
$request = $event->getRequest();
$requestRoute = $request->attributes->get('_route');
if (!$requestRoute || in_array($requestRoute, $this->excludeRoutes, true)) {
return;
}
$entityClass = $request->attributes->get('_api_resource_class');
if (
!$entityClass ||
(!array_key_exists($requestRoute, $this->logRoutes) && !in_array($entityClass, $this->logEntities, true))
) {
return;
}
$logEvent = null;
$data = null;
$method = $request->getMethod();
if ($method === "POST") {
return;
}
if ($method === "DELETE") {
$logEvent = Log::DELETE;
}
if ($method === "PUT") {
$logEvent = Log::UPDATE;
$data = $request->getContent();
}
if (array_key_exists($requestRoute, $this->logRoutes)) {
$logEvent = $this->logRoutes[$requestRoute];
}
if (!$logEvent) {
return;
}
try {
$iri = $request->getRequestUri();
$iri = explode('/', $iri);
array_splice($iri, 4);
$iri = implode('/', $iri);
$entity = $this->converter->getResourceFromIri($iri);
} catch (ItemNotFoundException | InvalidArgumentException | ConversionException) {
$entity = null;
}
$user = $this->security->getUser();
$this->logService->createLog(
logClass : Log::class,
action : $logEvent,
entity : $entityClass,
author : $user,
entityId : $entity?->id,
data : (string)$data,
flush : true,
httpAgent: $request->headers->get('user-agent'),
);
}
/**
* @throws Exception
*/
public function postPersist(PostPersistEventArgs $args): void
{
$object = $args->getObject();
if (!in_array($object::class, $this->logEntities, true)) {
return;
}
$user = $this->security->getUser();
$request = $this->request->getMainRequest();
if (!$request) {
return;
}
$data = $request->getContent();
if ($request->getContentType() === 'form') {
$data = $request->request->all();
}
if ($object?->id === null) {
return;
}
$this->logService->createLog(
logClass : Log::class,
action : Log::CREATE,
entity : $object::class,
author : $user,
entityId : $object->id,
data : json_encode($data, JSON_THROW_ON_ERROR),
flush : true,
httpAgent: $request->headers->get('user-agent'),
);
}
}