Repository: DamienHarper/auditor (php)

Issue:
Calling flush multiple times before committing causes additional audit-logs
I have an entity which should get audited and if I call flush more than once before calling commit, the audit-events will get logged with each subsequent commit again. In this example I end up with 11 identical insert audits:

```
        $this->orm->beginTransaction();
        $e = new Enity();
        $this->orm->persist($e);
        $this->orm->flush();
        $this->orm->flush();
        $this->orm->commit(); // Logs the insert once.

        // Logs an additional 10 inserts for the entity added above:
        for ($n=1;$n<=10;$n++) {
            $this->orm->beginTransaction();
            $this->orm->commit();
        }
```

I believe the issue is caused by `DoctrineSubscriber::onFlush`, which simply copies the current SQL-Logger to a class-variable and then tries to restore that value on commit, while not checking if the Audit-Logger is already installed.

Pull request:
Resets transaction once processed by the `onFlush` event subscriber. …
…Fixes #44

Patch:
diff --git a/src/Model/Transaction.php b/src/Model/Transaction.php
index 73f2c85..7cef33b 100644
--- a/src/Model/Transaction.php
+++ b/src/Model/Transaction.php
@@ -77,6 +77,16 @@ class Transaction implements TransactionInterface
         return $this->dissociated;
     }
 
+    public function reset(): void
+    {
+        $this->transaction_hash = null;
+        $this->inserted = [];
+        $this->updated = [];
+        $this->removed = [];
+        $this->associated = [];
+        $this->dissociated = [];
+    }
+
     public function trackAuditEvent(string $type, array $data): void
     {
         switch ($type) {
diff --git a/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php b/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php
index 1d71d82..f19100e 100644
--- a/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php
+++ b/src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php
@@ -45,6 +45,7 @@ class DoctrineSubscriber implements EventSubscriber
             // 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.


Test patch:
diff --git a/tests/Provider/Doctrine/Issues/Issue44Test.php b/tests/Provider/Doctrine/Issues/Issue44Test.php
new file mode 100644
index 0000000..1feb450
--- /dev/null
+++ b/tests/Provider/Doctrine/Issues/Issue44Test.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace DH\Auditor\Tests\Provider\Doctrine\Issues;
+
+use DH\Auditor\Model\Transaction;
+use DH\Auditor\Tests\Provider\Doctrine\Fixtures\Entity\Standard\DummyEntity;
+use DH\Auditor\Tests\Provider\Doctrine\Traits\ReaderTrait;
+use DH\Auditor\Tests\Provider\Doctrine\Traits\Schema\SchemaSetupTrait;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * @internal
+ */
+final class Issue44Test extends TestCase
+{
+    use ReaderTrait;
+    use SchemaSetupTrait;
+
+    public function testIssue44(): void
+    {
+        $reader = $this->createReader();
+
+        $em = $this->provider->getStorageServiceForEntity(DummyEntity::class)->getEntityManager();
+        $em->beginTransaction();
+        $entity = new DummyEntity();
+        $entity->setLabel('entity1');
+        $em->persist($entity);
+        $em->flush();
+        $em->flush();
+        $em->commit();
+        for ($n = 1; $n <= 10; ++$n) {
+            $em->beginTransaction();
+            $em->commit();
+        }
+
+        $audits = $reader->createQuery(DummyEntity::class)->execute();
+        self::assertCount(1, $audits, 'results count ok.');
+        self::assertSame(Transaction::INSERT, $audits[0]->getType(), 'Reader::INSERT operation.');
+    }
+
+    private function configureEntities(): void
+    {
+        $this->provider->getConfiguration()->setEntities([
+            DummyEntity::class => ['enabled' => true],
+        ]);
+    }
+}