From 04a6a1e0a2300734e7990030f031a0737b6a817b Mon Sep 17 00:00:00 2001 From: Damien Harper Date: Wed, 10 Feb 2021 18:18:14 +0100 Subject: [PATCH] Table creation events come from auditing entity managers (#24) * Table creation events come from auditing entity managers * Removed useless code * Fixed auditing and storage services inversions --- src/Provider/Doctrine/DoctrineProvider.php | 30 +++++++++++-------- .../Event/CreateSchemaListener.php | 12 +++++++- .../Doctrine/Persistence/Reader/Reader.php | 20 +++++++------ .../Doctrine/Traits/DoctrineProviderTrait.php | 2 +- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/Provider/Doctrine/DoctrineProvider.php b/src/Provider/Doctrine/DoctrineProvider.php index 2d20167e..a45db5e4 100644 --- a/src/Provider/Doctrine/DoctrineProvider.php +++ b/src/Provider/Doctrine/DoctrineProvider.php @@ -3,6 +3,7 @@ namespace DH\Auditor\Provider\Doctrine; use DH\Auditor\Event\LifecycleEvent; +use DH\Auditor\Exception\InvalidArgumentException; use DH\Auditor\Exception\ProviderException; use DH\Auditor\Provider\AbstractProvider; use DH\Auditor\Provider\ConfigurationInterface; @@ -17,6 +18,7 @@ use DH\Auditor\Provider\Service\AuditingServiceInterface; use DH\Auditor\Provider\Service\StorageServiceInterface; use Doctrine\ORM\EntityManagerInterface; +use Exception; class DoctrineProvider extends AbstractProvider { @@ -40,6 +42,7 @@ public function registerAuditingService(AuditingServiceInterface $service): Prov $evm = $entityManager->getEventManager(); // Register subscribers + $evm->addEventSubscriber(new CreateSchemaListener($this)); $evm->addEventSubscriber(new DoctrineSubscriber($this->transactionManager)); $this->loadAnnotations($entityManager); @@ -47,23 +50,26 @@ public function registerAuditingService(AuditingServiceInterface $service): Prov return $this; } - public function registerStorageService(StorageServiceInterface $service): ProviderInterface + public function isStorageMapperRequired(): bool { - parent::registerStorageService($service); + return \count($this->getStorageServices()) > 1; + } - \assert($service instanceof StorageService); // helps PHPStan - $entityManager = $service->getEntityManager(); - $evm = $entityManager->getEventManager(); + public function getAuditingServiceForEntity(string $entity): AuditingServiceInterface + { + foreach ($this->auditingServices as $name => $service) { + \assert($service instanceof AuditingService); // helps PHPStan - // Register subscribers - $evm->addEventSubscriber(new CreateSchemaListener($this)); + try { + // entity is managed by the entity manager of this service + $service->getEntityManager()->getClassMetadata($entity)->getTableName(); - return $this; - } + return $service; + } catch (Exception $e) { + } + } - public function isStorageMapperRequired(): bool - { - return \count($this->getStorageServices()) > 1; + throw new InvalidArgumentException(sprintf('Auditing service not found for "%s".', $entity)); } public function getStorageServiceForEntity(string $entity): StorageServiceInterface diff --git a/src/Provider/Doctrine/Persistence/Event/CreateSchemaListener.php b/src/Provider/Doctrine/Persistence/Event/CreateSchemaListener.php index 595e9758..fda51bd9 100644 --- a/src/Provider/Doctrine/Persistence/Event/CreateSchemaListener.php +++ b/src/Provider/Doctrine/Persistence/Event/CreateSchemaListener.php @@ -4,6 +4,7 @@ use DH\Auditor\Provider\Doctrine\DoctrineProvider; use DH\Auditor\Provider\Doctrine\Persistence\Schema\SchemaManager; +use DH\Auditor\Provider\Doctrine\Service\StorageService; use Doctrine\Common\EventSubscriber; use Doctrine\ORM\Mapping\ClassMetadataInfo; use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs; @@ -58,8 +59,17 @@ public function postGenerateSchemaTable(GenerateSchemaTableEventArgs $eventArgs) } } + $storageService = $this->provider->getStorageServiceForEntity($metadata->name); + \assert($storageService instanceof StorageService); // helps PHPStan + $connection = $storageService->getEntityManager()->getConnection(); + $storageSchemaManager = $connection->getSchemaManager(); + $fromSchema = $storageSchemaManager->createSchema(); + $sqls = []; + $updater = new SchemaManager($this->provider); - $updater->createAuditTable($metadata->name, $eventArgs->getClassTable(), $eventArgs->getSchema()); + $toSchema = $updater->createAuditTable($metadata->name, $eventArgs->getClassTable(), clone $fromSchema); + $sqls[$storageService->getName()] = $fromSchema->getMigrateToSql($toSchema, $storageSchemaManager->getDatabasePlatform()); + $updater->updateAuditSchema($sqls); } /** diff --git a/src/Provider/Doctrine/Persistence/Reader/Reader.php b/src/Provider/Doctrine/Persistence/Reader/Reader.php index bbbdd174..a4ec9a3c 100644 --- a/src/Provider/Doctrine/Persistence/Reader/Reader.php +++ b/src/Provider/Doctrine/Persistence/Reader/Reader.php @@ -8,6 +8,7 @@ use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Security; use DH\Auditor\Provider\Doctrine\Configuration; use DH\Auditor\Provider\Doctrine\DoctrineProvider; +use DH\Auditor\Provider\Doctrine\Service\AuditingService; use DH\Auditor\Provider\Doctrine\Service\StorageService; use Doctrine\ORM\Mapping\ClassMetadata as ORMMetadata; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -45,9 +46,8 @@ public function createQuery(string $entity, array $options = []): Query /** @var StorageService $storageService */ $storageService = $this->provider->getStorageServiceForEntity($entity); - $entityManager = $storageService->getEntityManager(); - $query = new Query($this->getEntityAuditTableName($entity), $entityManager->getConnection()); + $query = new Query($this->getEntityAuditTableName($entity), $storageService->getEntityManager()->getConnection()); $query ->addOrderBy(Query::CREATED_AT, 'DESC') ->addOrderBy(Query::ID, 'DESC') @@ -69,7 +69,9 @@ public function createQuery(string $entity, array $options = []): Query $query->limit($config['page_size'], ($config['page'] - 1) * $config['page_size']); } - $metadata = $entityManager->getClassMetadata($entity); + /** @var AuditingService $auditingService */ + $auditingService = $this->provider->getAuditingServiceForEntity($entity); + $metadata = $auditingService->getEntityManager()->getClassMetadata($entity); if ( $config['strict'] && $metadata instanceof ORMMetadata @@ -157,10 +159,10 @@ public function paginate(Query $query, int $page = 1, int $pageSize = self::PAGE */ public function getEntityTableName(string $entity): string { - /** @var StorageService $storageService */ - $storageService = $this->provider->getStorageServiceForEntity($entity); + /** @var AuditingService $auditingService */ + $auditingService = $this->provider->getAuditingServiceForEntity($entity); - return $storageService->getEntityManager()->getClassMetadata($entity)->getTableName(); + return $auditingService->getEntityManager()->getClassMetadata($entity)->getTableName(); } /** @@ -171,9 +173,9 @@ public function getEntityAuditTableName(string $entity): string /** @var Configuration $configuration */ $configuration = $this->provider->getConfiguration(); - /** @var StorageService $storageService */ - $storageService = $this->provider->getStorageServiceForEntity($entity); - $entityManager = $storageService->getEntityManager(); + /** @var AuditingService $auditingService */ + $auditingService = $this->provider->getAuditingServiceForEntity($entity); + $entityManager = $auditingService->getEntityManager(); $schema = ''; if ($entityManager->getClassMetadata($entity)->getSchemaName()) { $schema = $entityManager->getClassMetadata($entity)->getSchemaName().'.'; diff --git a/tests/Provider/Doctrine/Traits/DoctrineProviderTrait.php b/tests/Provider/Doctrine/Traits/DoctrineProviderTrait.php index 20c736f0..5eb5fb55 100644 --- a/tests/Provider/Doctrine/Traits/DoctrineProviderTrait.php +++ b/tests/Provider/Doctrine/Traits/DoctrineProviderTrait.php @@ -67,7 +67,7 @@ private function createDoctrineProviderWith1AEM2SEM(?Configuration $configuratio // Entity manager "aem1" is used for auditing only $provider->registerAuditingService(new AuditingService('aem1', $this->createEntityManager([ __DIR__.'/../../../../src/Provider/Doctrine/Auditing/Annotation', - __DIR__.'/../Fixtures/Entity/Standard', + __DIR__.'/../Fixtures/Entity', ]))); $db = self::getConnectionParameters();