<?php
namespace App\EventListener;
use App\Entity\Loggable;
use App\Helper\LoggingHelper;
use App\Message\LoggingMessage;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Security\Core\Security;
final class LoggingListener
{
private EntityManagerInterface $entityManager;
private MessageBusInterface $bus;
private Security $security;
/**
* @param EntityManagerInterface $entityManager
* @param MessageBusInterface $bus
* @param Security $security
*/
public function __construct(
EntityManagerInterface $entityManager,
MessageBusInterface $bus,
Security $security
) {
$this->entityManager = $entityManager;
$this->bus = $bus;
$this->security = $security;
}
/**
* @return void
*/
public function postUpdate(LifecycleEventArgs $event): void
{
$entity = $event->getObject();
if ($this->supports($entity)) {
$uow = $this->entityManager->getUnitOfWork();
$uow->computeChangeSets();
$payloadAfter = $uow->getOriginalEntityData($entity);
$payloadAfter = LoggingHelper::getCustomizedArray($payloadAfter, $entity->getFields());
$changesSet = $uow->getEntityChangeSet($entity);
$className = get_class($entity);
$payloadBefore = [];
foreach ($changesSet as $key => $changeset) {
$payloadBefore[$key] = $changeset[0];
}
$payloadBefore = array_merge($payloadAfter, $payloadBefore);
if (array_intersect_key($entity->getFields(), $changesSet)) {
$this->bus->dispatch(new LoggingMessage(
$className,
$this->security->getUser() ? $this->security->getUser()->getId() : -1,
$changesSet,
LoggingHelper::fillCollectionById($payloadBefore),
LoggingHelper::fillCollectionById($payloadAfter),
$entity->getId(),
new \DateTimeImmutable('now')
));
}
}
}
/**
* @param $entity
*
* @return bool
*/
private function supports($entity): bool
{
return $entity instanceof Loggable;
}
}