Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-andreyev committed Oct 31, 2023
1 parent 2fd4f3e commit 7b50c7e
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 19 deletions.
52 changes: 33 additions & 19 deletions src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

class DoctrineSubscriber implements EventSubscriber
{
/** @var Transaction[] */
private array $transactions = [];

private TransactionManager $transactionManager;

private ?SQLLogger $loggerBackup = null;
Expand All @@ -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);

Expand All @@ -48,27 +55,34 @@ 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);
}
} elseif ($this->loggerBackup instanceof SQLLogger) {
$loggerChain->addLogger($this->loggerBackup);
$currentLogger = $entityManager->getConnection()->getConfiguration()->getSQLLogger();

// current logger is not a LoggerChain, wrap it
if (!$currentLogger instanceof LoggerChain) {
// backup current logger
$this->loggerBackup = $currentLogger;

// create a new LoggerChain with the new AuditLogger
$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();
$loggerChain->addLogger($currentLogger);
$loggerChain->addLogger($auditLogger);

$entityManager->getConnection()->getConfiguration()->setSQLLogger($loggerChain);
}
$loggerChain->addLogger($auditLogger);
$entityManager->getConnection()->getConfiguration()->setSQLLogger($loggerChain);
}

public function getSubscribedEvents(): array
Expand Down
58 changes: 58 additions & 0 deletions tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

namespace DH\Auditor\Tests\Provider\Doctrine\Event;

use DH\Auditor\Provider\Doctrine\Auditing\Event\DoctrineSubscriber;
use DH\Auditor\Provider\Doctrine\Auditing\Logger\LoggerChain;
use DH\Auditor\Provider\Doctrine\Auditing\Transaction\TransactionManager;
use Doctrine\DBAL\Configuration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Logging\SQLLogger;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\Persistence\ObjectManager;
use PHPUnit\Framework\TestCase;

class DoctrineSubscriberTest extends TestCase
{
public function testMemoryUsage(): void
{
$transactionManager = $this->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)
{
}

public function stopQuery()
{
}
});

$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());
}
}

0 comments on commit 7b50c7e

Please sign in to comment.