diff --git a/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php b/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php index 04462b14..f43cc7a2 100644 --- a/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php +++ b/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php @@ -17,6 +17,9 @@ class DoctrineSubscriber implements EventSubscriber { + /** @var Transaction[] */ + private array $transactions = []; + private TransactionManager $transactionManager; private ?SQLLogger $loggerBackup = null; @@ -35,7 +38,11 @@ public function __construct(TransactionManager $transactionManager) public function onFlush(OnFlushEventArgs $args): void { $entityManager = DoctrineHelper::getEntityManagerFromOnFlushEventArgs($args); - $transaction = new Transaction($entityManager); + $entityManagerId = spl_object_id($entityManager); + + // cached transaction model, if it holds same EM no need to create a new one + $transaction = ($this->transactions[$entityManagerId] ??= new Transaction($entityManager)); + // Populate transaction $this->transactionManager->populate($transaction); @@ -48,27 +55,32 @@ public function onFlush(OnFlushEventArgs $args): void return; } + trigger_deprecation('damienharper/auditor', '2.2', 'SQLLogger is deprecated. Use DHMiddleware instead'); + // extend the SQL logger - $this->loggerBackup = $entityManager->getConnection()->getConfiguration()->getSQLLogger(); - $auditLogger = new Logger(function () use ($entityManager, $transaction): void { - // flushes pending data - $entityManager->getConnection()->getConfiguration()->setSQLLogger($this->loggerBackup); - $this->transactionManager->process($transaction); - $transaction->reset(); - }); - - // Initialize a new LoggerChain with the new AuditLogger + the existing SQLLoggers. - $loggerChain = new LoggerChain(); - if ($this->loggerBackup instanceof LoggerChain) { - foreach ($this->loggerBackup->getLoggers() as $logger) { - $loggerChain->addLogger($logger); + $currentLogger = $entityManager->getConnection()->getConfiguration()->getSQLLogger(); + if (!$currentLogger instanceof LoggerChain) { + $this->loggerBackup = $currentLogger; + + $auditLogger = new Logger(function () use ($entityManager, $transaction): void { + // reset logger + $entityManager->getConnection()->getConfiguration()->setSQLLogger($this->loggerBackup); + + // flushes pending data + $this->transactionManager->process($transaction); + $transaction->reset(); + }); + + // Initialize a new LoggerChain with the new AuditLogger + the existing SQLLoggers. + $loggerChain = new LoggerChain(); + if (null !== $currentLogger) { + $loggerChain->addLogger($currentLogger); } - } elseif ($this->loggerBackup instanceof SQLLogger) { - $loggerChain->addLogger($this->loggerBackup); + $loggerChain->addLogger($auditLogger); + + $entityManager->getConnection()->getConfiguration()->setSQLLogger($loggerChain); } - $loggerChain->addLogger($auditLogger); - $entityManager->getConnection()->getConfiguration()->setSQLLogger($loggerChain); } public function getSubscribedEvents(): array diff --git a/tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php b/tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php new file mode 100644 index 00000000..f036c365 --- /dev/null +++ b/tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php @@ -0,0 +1,62 @@ +createMock(TransactionManager::class); + $objectManager = $this->createMock(EntityManagerInterface::class); + + $args = new OnFlushEventArgs($objectManager); + + $objectManager + ->method('getConnection') + ->willReturn($connection = $this->createMock(Connection::class)) + ; + + $connection + ->method('getDriver') + ->willReturn($driver = $this->createMock(Driver::class)) + ; + + $connection + ->method('getConfiguration') + ->willReturn($configuration = new Configuration()) + ; + + $configuration->setSQLLogger(new class() implements SQLLogger { + public function startQuery($sql, ?array $params = null, ?array $types = null): void {} + + public function stopQuery(): void {} + }); + + $target = new DoctrineSubscriber($transactionManager); + $target->onFlush($args); + $target->onFlush($args); + $target->onFlush($args); + $target->onFlush($args); + $target->onFlush($args); + + $result = $configuration->getSQLLogger(); + self::assertCount(2, $result->getLoggers()); + } +}