Skip to content

Commit

Permalink
Fix 185 (#186)
Browse files Browse the repository at this point in the history
* fixes #185

* PHP-CS-Fixer

---------

Co-authored-by: Damien Harper <[email protected]>
  • Loading branch information
oleg-andreyev and DamienHarper authored Dec 19, 2023
1 parent 5a9dbc2 commit 07235c1
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 18 deletions.
48 changes: 30 additions & 18 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,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
Expand Down
62 changes: 62 additions & 0 deletions tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

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

use DH\Auditor\Provider\Doctrine\Auditing\Event\DoctrineSubscriber;
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 PHPUnit\Framework\TestCase;

/**
* @internal
*
* @small
*/
final class DoctrineSubscriberTest extends TestCase
{
public function testIssue185(): 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): 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());
}
}

0 comments on commit 07235c1

Please sign in to comment.