Skip to content

Commit

Permalink
Doctrine ORM 3.x support (#207)
Browse files Browse the repository at this point in the history
* Allow `doctrine/orm:^3.2`

* Fix `Error: Call to undefined method Doctrine\ORM\EntityManager::create()`

* Fix `Error: Class "Doctrine\ORM\Mapping\ClassMetadataInfo" not found`

* Association mapping is an object in doctrine/orm 3.x
  • Loading branch information
DamienHarper authored Sep 1, 2024
1 parent 6cd9580 commit f1eafc6
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 22 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"require": {
"php": ">=8.2",
"doctrine/dbal": "^2.13.1|^3.2",
"doctrine/orm": "^2.13",
"doctrine/orm": "^2.13|^3.2",
"symfony/cache": "^5.4|^6.0|^7.0",
"symfony/event-dispatcher": "^5.4|^6.0|^7.0",
"symfony/lock": "^5.4|^6.0|^7.0",
Expand All @@ -40,7 +40,7 @@
},
"scripts": {
"test": "XDEBUG_MODE=coverage ./vendor/bin/phpunit --colors=always",
"cs-fix": "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.php --using-cache=no --verbose --ansi",
"cs-fix": "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --using-cache=no --verbose --ansi",
"cs-check": "tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --using-cache=no --verbose --ansi --dry-run",
"phpstan": "tools/phpstan/vendor/bin/phpstan --memory-limit=1G --ansi analyse src",
"rector": "tools/rector/vendor/bin/rector",
Expand Down
1 change: 1 addition & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
SymfonySetList::SYMFONY_54,
PHPUnitSetList::PHPUNIT_110,
DoctrineSetList::DOCTRINE_CODE_QUALITY,
DoctrineSetList::DOCTRINE_ORM_29,
DoctrineSetList::DOCTRINE_DBAL_40,
])
->withAttributesSets(
Expand Down
13 changes: 8 additions & 5 deletions src/Provider/Doctrine/Auditing/Event/DoctrineSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Doctrine\Common\EventSubscriber;
use Doctrine\DBAL\Driver;
use Doctrine\DBAL\Driver\Middleware\AbstractDriverMiddleware;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;

Expand All @@ -18,7 +19,10 @@ final class DoctrineSubscriber implements EventSubscriber
/** @var Transaction[] */
private array $transactions = [];

public function __construct(private readonly TransactionManagerInterface $transactionManager) {}
public function __construct(
private readonly TransactionManagerInterface $transactionManager,
private readonly EntityManagerInterface $entityManager
) {}

/**
* It is called inside EntityManager#flush() after the changes to all the managed entities
Expand All @@ -28,16 +32,15 @@ public function __construct(private readonly TransactionManagerInterface $transa
*/
public function onFlush(OnFlushEventArgs $args): void
{
$entityManager = $args->getObjectManager();
$entityManagerId = spl_object_id($entityManager);
$entityManagerId = spl_object_id($this->entityManager);

// cached transaction model, if it holds same EM no need to create a new one
$transaction = ($this->transactions[$entityManagerId] ??= new Transaction($entityManager));
$transaction = ($this->transactions[$entityManagerId] ??= new Transaction($this->entityManager));

// Populate transaction
$this->transactionManager->populate($transaction);

$driver = $entityManager->getConnection()->getDriver();
$driver = $this->entityManager->getConnection()->getDriver();

if (!$driver instanceof DHDriver) {
$driver = $this->getWrappedDriver($driver);
Expand Down
11 changes: 10 additions & 1 deletion src/Provider/Doctrine/Auditing/Transaction/AuditTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,35 @@ private function id(EntityManagerInterface $entityManager, object $entity): mixe
}

if (isset($meta->fieldMappings[$pk])) {
\assert(\is_string($meta->fieldMappings[$pk]['type']));
$type = Type::getType($meta->fieldMappings[$pk]['type']);

\assert(\is_object($meta->getReflectionProperty($pk)));

return $this->value($entityManager, $type, $meta->getReflectionProperty($pk)->getValue($entity));
}

/**
/*
* Primary key is not part of fieldMapping.
*
* @see https://github.com/DamienHarper/auditor-bundle/issues/40
* @see https://www.doctrine-project.org/projects/doctrine-orm/en/latest/tutorials/composite-primary-keys.html#identity-through-foreign-entities
* We try to get it from associationMapping (will throw a MappingException if not available)
*/
\assert(\is_object($meta->getReflectionProperty($pk)));
$targetEntity = $meta->getReflectionProperty($pk)->getValue($entity);

$mapping = $meta->getAssociationMapping($pk);

\assert(\is_string($mapping['targetEntity']));
$meta = $entityManager->getClassMetadata($mapping['targetEntity']);
$pk = $meta->getSingleIdentifierFieldName();

\assert(\is_string($meta->fieldMappings[$pk]['type']));
$type = Type::getType($meta->fieldMappings[$pk]['type']);

\assert(\is_object($targetEntity));
\assert(\is_object($meta->getReflectionProperty($pk)));

return $this->value($entityManager, $type, $meta->getReflectionProperty($pk)->getValue($targetEntity));
}
Expand Down Expand Up @@ -151,6 +159,7 @@ private function diff(EntityManagerInterface $entityManager, object $entity, arr
&& $this->provider->isAuditedField($entity, $fieldName)
) {
$mapping = $meta->fieldMappings[$fieldName];
\assert(\is_string($mapping['type']));
$type = Type::getType($mapping['type']);
$o = $this->value($entityManager, $type, $old);
$n = $this->value($entityManager, $type, $new);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use DH\Auditor\Provider\Doctrine\Model\Transaction;
use DH\Auditor\Transaction\TransactionHydratorInterface;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\AssociationMapping;
use Doctrine\ORM\PersistentCollection;

final class TransactionHydrator implements TransactionHydratorInterface
Expand Down Expand Up @@ -86,8 +87,9 @@ private function hydrateWithScheduledCollectionUpdates(Transaction $transaction,
if (null !== $owner && $this->provider->isAudited($owner)) {
$mapping = $collection->getMapping();

if (!\is_array($mapping)) {
continue;
// TODO: backward compatibility code until we drop doctrine/orm <3.0
if ($mapping instanceof AssociationMapping) {
$mapping = $mapping->toArray();
}

/** @var object $entity */
Expand Down Expand Up @@ -126,8 +128,9 @@ private function hydrateWithScheduledCollectionDeletions(Transaction $transactio
if (null !== $owner && $this->provider->isAudited($owner)) {
$mapping = $collection->getMapping();

if (!\is_array($mapping)) {
continue;
// TODO: backward compatibility code until we drop doctrine/orm <3.0
if ($mapping instanceof AssociationMapping) {
$mapping = $mapping->toArray();
}

/** @var object $entity */
Expand Down
2 changes: 1 addition & 1 deletion src/Provider/Doctrine/DoctrineProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public function registerAuditingService(AuditingServiceInterface $service): Prov
// Register subscribers
$evm->addEventListener([Events::loadClassMetadata], new TableSchemaListener($this));
$evm->addEventListener([ToolEvents::postGenerateSchemaTable], new CreateSchemaListener($this));
$evm->addEventSubscriber(new DoctrineSubscriber($this->transactionManager));
$evm->addEventSubscriber(new DoctrineSubscriber($this->transactionManager, $entityManager));

return $this;
}
Expand Down
10 changes: 5 additions & 5 deletions src/Provider/Doctrine/Persistence/Event/CreateSchemaListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use DH\Auditor\Provider\Doctrine\Service\AuditingService;
use DH\Auditor\Provider\Doctrine\Service\StorageService;
use DH\Auditor\Tests\Provider\Doctrine\Persistence\Event\CreateSchemaListenerTest;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Tools\Event\GenerateSchemaTableEventArgs;

/**
Expand All @@ -25,9 +25,9 @@ public function postGenerateSchemaTable(GenerateSchemaTableEventArgs $eventArgs)

// check inheritance type and returns if unsupported
if (!\in_array($metadata->inheritanceType, [
ClassMetadataInfo::INHERITANCE_TYPE_NONE,
ClassMetadataInfo::INHERITANCE_TYPE_JOINED,
ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE,
ClassMetadata::INHERITANCE_TYPE_NONE,
ClassMetadata::INHERITANCE_TYPE_JOINED,
ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE,
], true)) {
throw new \Exception(\sprintf('Inheritance type "%s" is not yet supported', $metadata->inheritanceType));
}
Expand All @@ -38,7 +38,7 @@ public function postGenerateSchemaTable(GenerateSchemaTableEventArgs $eventArgs)
$audited = false;
if (
$metadata->rootEntityName === $metadata->name
&& ClassMetadataInfo::INHERITANCE_TYPE_SINGLE_TABLE === $metadata->inheritanceType
&& ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE === $metadata->inheritanceType
) {
foreach ($metadata->subClasses as $subClass) {
if ($this->provider->isAuditable($subClass)) {
Expand Down
6 changes: 3 additions & 3 deletions tests/Provider/Doctrine/Event/DoctrineSubscriberTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function process($transaction): void
->willReturn($driver)
;

$target = new DoctrineSubscriber($transactionManager);
$target = new DoctrineSubscriber($transactionManager, $objectManager);
$target->onFlush($args);

foreach ($dhDriver->getFlusherList() as $item) {
Expand Down Expand Up @@ -117,7 +117,7 @@ public function createDatabasePlatformForVersion($version): void {}
->willReturn($driver)
;

$target = new DoctrineSubscriber($transactionManager);
$target = new DoctrineSubscriber($transactionManager, $objectManager);
$target->onFlush($args);

foreach ($dhDriver->getFlusherList() as $item) {
Expand Down Expand Up @@ -171,7 +171,7 @@ public function createDatabasePlatformForVersion($version): void {}
->willReturn($configuration = $this->createMock(Configuration::class))
;

$target = new DoctrineSubscriber($transactionManager);
$target = new DoctrineSubscriber($transactionManager, $objectManager);
$target->onFlush($args);

$this->assertTrue(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ private function createEntityManager(?array $paths = null, string $connectionNam

$connection = $this->getConnection($connectionName, $params);

$em = EntityManager::create($connection, $configuration);
$em = new EntityManager($connection, $configuration);
$evm = $em->getEventManager();
$allListeners = method_exists($evm, 'getAllListeners') ? $evm->getAllListeners() : $evm->getListeners();
foreach ($allListeners as $event => $listeners) {
Expand Down

0 comments on commit f1eafc6

Please sign in to comment.