From 31a3c5ea1dc56cf01760408c7bfafe1d735bc315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 9 Oct 2024 16:27:17 +0200 Subject: [PATCH 1/6] Create Event class that extends Symfony Event class --- .../MongoDB/Event/DocumentNotFoundEvent.php | 49 ++++++++++ .../ODM/MongoDB/Event/HasDocumentManager.php | 17 ++++ .../ODM/MongoDB/Event/LifecycleEvent.php | 40 ++++++++ .../MongoDB/Event/LoadClassMetadataEvent.php | 32 +++++++ .../ODM/MongoDB/Event/ManagerEvent.php | 23 +++++ .../Event/OnClassMetadataNotFoundEvent.php | 48 ++++++++++ .../ODM/MongoDB/Event/OnClearEvent.php | 19 ++++ .../ODM/MongoDB/Event/OnFlushEvent.php | 12 +++ .../MongoDB/Event/PostCollectionLoadEvent.php | 33 +++++++ .../ODM/MongoDB/Event/PostFlushEvent.php | 12 +++ .../ODM/MongoDB/Event/PreFlushEvent.php | 12 +++ .../ODM/MongoDB/Event/PreLoadEvent.php | 34 +++++++ .../ODM/MongoDB/Event/PreUpdateEvent.php | 95 +++++++++++++++++++ 13 files changed, 426 insertions(+) create mode 100644 lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/PostCollectionLoadEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreFlushEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreLoadEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php diff --git a/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php b/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php new file mode 100644 index 000000000..f0b4967f9 --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php @@ -0,0 +1,49 @@ +identifier; + } + + /** + * Indicates whether the proxy initialization exception is disabled. + */ + public function isExceptionDisabled(): bool + { + return $this->disableException; + } + + /** + * Disable the throwing of an exception + * + * This method indicates to the proxy initializer that the missing document + * has been handled and no exception should be thrown. This can't be reset. + */ + public function disableException(bool $disableException = true): void + { + $this->disableException = $disableException; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php b/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php new file mode 100644 index 000000000..3dfc7a6e3 --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php @@ -0,0 +1,17 @@ +documentManager; + } +} \ No newline at end of file diff --git a/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php b/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php new file mode 100644 index 000000000..dccd5fd56 --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php @@ -0,0 +1,40 @@ +object; + } + + public function getDocumentManager(): DocumentManager + { + return $this->objectManager; + } + + public function isInTransaction(): bool + { + return $this->session?->isInTransaction() ?? false; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php b/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php new file mode 100644 index 000000000..624ad82dc --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php @@ -0,0 +1,32 @@ +classMetadata; + } + + public function getDocumentManager(): DocumentManager + { + return $this->objectManager; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php b/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php new file mode 100644 index 000000000..a14699d15 --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php @@ -0,0 +1,23 @@ +objectManager; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php new file mode 100644 index 000000000..d500e6d6e --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php @@ -0,0 +1,48 @@ +|null */ + private ?ClassMetadata $foundMetadata = null; + + /** @psalm-param class-string $className */ + public function __construct(private string $className, DocumentManager $dm) + { + parent::__construct($dm); + } + + /** @param ClassMetadata|null $classMetadata */ + public function setFoundMetadata(?ClassMetadata $classMetadata = null): void + { + $this->foundMetadata = $classMetadata; + } + + /** @return ClassMetadata|null */ + public function getFoundMetadata(): ?ClassMetadata + { + return $this->foundMetadata; + } + + /** + * Retrieve class name for which a failed metadata fetch attempt was executed + * + * @psalm-return class-string + */ + public function getClassName(): string + { + return $this->className; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php new file mode 100644 index 000000000..48188406c --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php @@ -0,0 +1,19 @@ + + */ +final class OnClearEvent extends Event +{ + use HasDocumentManager; +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php new file mode 100644 index 000000000..08651a44a --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php @@ -0,0 +1,12 @@ + $collection */ + public function __construct(private PersistentCollectionInterface $collection, DocumentManager $dm) + { + parent::__construct($dm); + } + + /** + * Gets collection that was just initialized (loaded). + * + * @return PersistentCollectionInterface + */ + public function getCollection(): PersistentCollectionInterface + { + return $this->collection; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php b/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php new file mode 100644 index 000000000..694683a4e --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php @@ -0,0 +1,12 @@ + $data */ + public function __construct( + object $document, + DocumentManager $dm, + private array &$data, + ?Session $session = null, + ) { + parent::__construct($document, $dm, $session); + } + + /** + * Get the array of data to be loaded and hydrated. + * + * @return array + */ + public function &getData(): array + { + return $this->data; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php b/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php new file mode 100644 index 000000000..472835294 --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php @@ -0,0 +1,95 @@ + $changeSet */ + public function __construct( + object $document, + DocumentManager $dm, + private array $changeSet, + ?Session $session = null, + ) { + parent::__construct($document, $dm, $session); + } + + /** @return array */ + public function getDocumentChangeSet(): array + { + return $this->changeSet; + } + + public function hasChangedField(string $field): bool + { + return isset($this->changeSet[$field]); + } + + /** + * Gets the old value of the changeset of the changed field. + * + * @return mixed + */ + public function getOldValue(string $field) + { + $this->assertValidField($field); + + return $this->changeSet[$field][0]; + } + + /** + * Gets the new value of the changeset of the changed field. + * + * @return mixed + */ + public function getNewValue(string $field) + { + $this->assertValidField($field); + + return $this->changeSet[$field][1]; + } + + /** + * Sets the new value of this field. + * + * @param mixed $value + */ + public function setNewValue(string $field, $value): void + { + $this->assertValidField($field); + + $this->changeSet[$field][1] = $value; + $this->getDocumentManager()->getUnitOfWork()->setDocumentChangeSet($this->getDocument(), $this->changeSet); + } + + /** + * Asserts the field exists in changeset. + * + * @throws InvalidArgumentException If the field has no changeset. + */ + private function assertValidField(string $field): void + { + if (! isset($this->changeSet[$field])) { + throw new InvalidArgumentException(sprintf( + 'Field "%s" is not a valid field of the document "%s" in PreUpdateEventArgs.', + $field, + get_class($this->getDocument()), + )); + } + } +} From 4907252d44085889ef00ebfb2dc4a2459a1c9ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 9 Oct 2024 18:05:11 +0200 Subject: [PATCH 2/6] Allows Symfony EventDispatcherInterface instead of EventManager --- lib/Doctrine/ODM/MongoDB/DocumentManager.php | 19 +++++++++-- .../ODM/MongoDB/Event/HasDocumentManager.php | 4 ++- .../MongoDB/Event/LoadClassMetadataEvent.php | 1 - .../ODM/MongoDB/Hydrator/HydratorFactory.php | 21 ++++++++---- .../MongoDB/Mapping/ClassMetadataFactory.php | 21 ++++++++---- .../Proxy/Factory/StaticProxyFactory.php | 2 +- lib/Doctrine/ODM/MongoDB/UnitOfWork.php | 32 +++++++++++++++---- .../MongoDB/Utility/LifecycleEventManager.php | 25 +++++++++++---- 8 files changed, 94 insertions(+), 31 deletions(-) diff --git a/lib/Doctrine/ODM/MongoDB/DocumentManager.php b/lib/Doctrine/ODM/MongoDB/DocumentManager.php index 706b23ed8..deb584c22 100644 --- a/lib/Doctrine/ODM/MongoDB/DocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/DocumentManager.php @@ -23,6 +23,7 @@ use Doctrine\Persistence\ObjectManager; use InvalidArgumentException; use Jean85\PrettyVersions; +use LogicException; use MongoDB\Client; use MongoDB\Collection; use MongoDB\Database; @@ -30,6 +31,7 @@ use MongoDB\GridFS\Bucket; use ProxyManager\Proxy\GhostObjectInterface; use RuntimeException; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Throwable; use function array_search; @@ -79,7 +81,7 @@ class DocumentManager implements ObjectManager /** * The event manager that is the central point of the event system. */ - private EventManager $eventManager; + private EventManager|EventDispatcherInterface $eventManager; /** * The Hydrator factory instance. @@ -141,7 +143,7 @@ class DocumentManager implements ObjectManager * Creates a new Document that operates on the given Mongo connection * and uses the given Configuration. */ - protected function __construct(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null) + protected function __construct(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventManager = null) { $this->config = $config ?: new Configuration(); $this->eventManager = $eventManager ?: new EventManager(); @@ -197,16 +199,27 @@ public function getProxyFactory(): ProxyFactory * Creates a new Document that operates on the given Mongo connection * and uses the given Configuration. */ - public static function create(?Client $client = null, ?Configuration $config = null, ?EventManager $eventManager = null): DocumentManager + public static function create(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventManager = null): DocumentManager { return new static($client, $config, $eventManager); } + public function getEventDispatcher(): EventManager|EventDispatcherInterface + { + return $this->eventManager; + } + /** * Gets the EventManager used by the DocumentManager. + * + * @deprecated Use getEventDispatcher() instead */ public function getEventManager(): EventManager { + if (! $this->eventManager instanceof EventManager) { + throw new LogicException('Use getEventDispatcher() instead of getEventManager()'); + } + return $this->eventManager; } diff --git a/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php b/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php index 3dfc7a6e3..d1bcdac98 100644 --- a/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php @@ -1,5 +1,7 @@ documentManager; } -} \ No newline at end of file +} diff --git a/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php b/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php index 624ad82dc..237ece2b3 100644 --- a/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php +++ b/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php @@ -6,7 +6,6 @@ use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; -use Doctrine\Persistence\ObjectManager; use Symfony\Contracts\EventDispatcher\Event; /** diff --git a/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php b/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php index 52c1f3943..6ef48f6c2 100644 --- a/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php @@ -14,6 +14,7 @@ use Doctrine\ODM\MongoDB\Types\Type; use Doctrine\ODM\MongoDB\UnitOfWork; use ProxyManager\Proxy\GhostObjectInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use function array_key_exists; use function chmod; @@ -49,7 +50,7 @@ final class HydratorFactory /** * The EventManager associated with this Hydrator */ - private EventManager $evm; + private EventManager|EventDispatcherInterface $evm; /** * Which algorithm to use to automatically (re)generate hydrator classes. @@ -74,7 +75,7 @@ final class HydratorFactory private array $hydrators = []; /** @throws HydratorException */ - public function __construct(DocumentManager $dm, EventManager $evm, ?string $hydratorDir, ?string $hydratorNs, int $autoGenerate) + public function __construct(DocumentManager $dm, EventManager|EventDispatcherInterface $evm, ?string $hydratorDir, ?string $hydratorNs, int $autoGenerate) { if (! $hydratorDir) { throw HydratorException::hydratorDirectoryRequired(); @@ -433,7 +434,12 @@ public function hydrate(object $document, array $data, array $hints = []): array $metadata->invokeLifecycleCallbacks(Events::preLoad, $document, $args); } - $this->evm->dispatchEvent(Events::preLoad, new PreLoadEventArgs($document, $this->dm, $data)); + $eventArgs = new PreLoadEventArgs($document, $this->dm, $data); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::preLoad); + } else { + $this->evm->dispatchEvent(Events::preLoad, $eventArgs); + } // alsoLoadMethods may transform the document before hydration if (! empty($metadata->alsoLoadMethods)) { @@ -470,8 +476,11 @@ public function hydrate(object $document, array $data, array $hints = []): array $metadata->invokeLifecycleCallbacks(Events::postLoad, $document, [new LifecycleEventArgs($document, $this->dm)]); } - $this->evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($document, $this->dm)); - - return $data; + $eventArgs = new LifecycleEventArgs($document, $this->dm); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::postLoad); + } else { + $this->evm->dispatchEvent(Events::postLoad, $eventArgs); + } } } diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php index 4c11dda38..28eb77a9f 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php @@ -21,6 +21,7 @@ use Doctrine\Persistence\Mapping\Driver\MappingDriver; use Doctrine\Persistence\Mapping\ReflectionService; use ReflectionException; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use function assert; use function get_class_methods; @@ -52,8 +53,8 @@ final class ClassMetadataFactory extends AbstractClassMetadataFactory implements /** @var MappingDriver The used metadata driver. */ private MappingDriver $driver; - /** @var EventManager The event manager instance */ - private EventManager $evm; + /** @var EventManager|EventDispatcherInterface The event manager instance */ + private EventManager|EventDispatcherInterface $evm; public function setDocumentManager(DocumentManager $dm): void { @@ -90,7 +91,11 @@ protected function onNotFoundMetadata($className) $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->dm); - $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::onClassMetadataNotFound); + } else { + $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); + } return $eventArgs->getFoundMetadata(); } @@ -195,10 +200,12 @@ protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonS $class->setParentClasses($nonSuperclassParents); - $this->evm->dispatchEvent( - Events::loadClassMetadata, - new LoadClassMetadataEventArgs($class, $this->dm), - ); + $eventArgs = new LoadClassMetadataEventArgs($class, $this->dm); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::loadClassMetadata); + } else { + $this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs); + } // phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed if ($class->isChangeTrackingNotify()) { diff --git a/lib/Doctrine/ODM/MongoDB/Proxy/Factory/StaticProxyFactory.php b/lib/Doctrine/ODM/MongoDB/Proxy/Factory/StaticProxyFactory.php index 737795fe4..06afad130 100644 --- a/lib/Doctrine/ODM/MongoDB/Proxy/Factory/StaticProxyFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Proxy/Factory/StaticProxyFactory.php @@ -32,7 +32,7 @@ final class StaticProxyFactory implements ProxyFactory public function __construct(DocumentManager $documentManager) { $this->uow = $documentManager->getUnitOfWork(); - $this->lifecycleEventManager = new LifecycleEventManager($documentManager, $this->uow, $documentManager->getEventManager()); + $this->lifecycleEventManager = new LifecycleEventManager($documentManager, $this->uow, $documentManager->getEventDispatcher()); $this->proxyFactory = $documentManager->getConfiguration()->buildGhostObjectFactory(); } diff --git a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php index eb9591f99..6f4adb18a 100644 --- a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php +++ b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php @@ -29,6 +29,7 @@ use MongoDB\Driver\WriteConcern; use ProxyManager\Proxy\GhostObjectInterface; use ReflectionProperty; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use Throwable; use UnexpectedValueException; @@ -236,7 +237,7 @@ final class UnitOfWork implements PropertyChangedListener /** * The EventManager used for dispatching events. */ - private EventManager $evm; + private EventManager|EventDispatcherInterface $evm; /** * Additional documents that are scheduled for removal. @@ -292,7 +293,7 @@ final class UnitOfWork implements PropertyChangedListener /** * Initializes a new UnitOfWork instance, bound to the given DocumentManager. */ - public function __construct(DocumentManager $dm, EventManager $evm, HydratorFactory $hydratorFactory) + public function __construct(DocumentManager $dm, EventManager|EventDispatcherInterface $evm, HydratorFactory $hydratorFactory) { $this->dm = $dm; $this->evm = $evm; @@ -425,7 +426,12 @@ public function commit(array $options = []): void } // Raise preFlush - $this->evm->dispatchEvent(Events::preFlush, new Event\PreFlushEventArgs($this->dm)); + $eventArgs = new Event\PreFlushEventArgs($this->dm); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::preFlush); + } else { + $this->evm->dispatchEvent(Events::preFlush, $eventArgs); + } // Compute changes done since last commit. $this->computeChangeSets(); @@ -454,7 +460,12 @@ public function commit(array $options = []): void } } - $this->evm->dispatchEvent(Events::onFlush, new Event\OnFlushEventArgs($this->dm)); + $eventArgs = new Event\OnFlushEventArgs($this->dm); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::onFlush); + } else { + $this->evm->dispatchEvent(Events::onFlush, $eventArgs); + } if ($this->useTransaction($options)) { $session = $this->dm->getClient()->startSession(); @@ -473,7 +484,12 @@ function (Session $session) use ($options): void { } // Raise postFlush - $this->evm->dispatchEvent(Events::postFlush, new Event\PostFlushEventArgs($this->dm)); + $eventArgs = new Event\PostFlushEventArgs($this->dm); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::postFlush); + } else { + $this->evm->dispatchEvent(Events::postFlush, $eventArgs); + } // Clear up foreach ($this->visitedCollections as $collections) { @@ -2430,7 +2446,11 @@ public function clear(?string $documentName = null): void $event = new Event\OnClearEventArgs($this->dm, $documentName); } - $this->evm->dispatchEvent(Events::onClear, $event); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($event, Events::onClear); + } else { + $this->evm->dispatchEvent(Events::onClear, $event); + } } /** diff --git a/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php b/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php index a44ff8f25..aa47d5a51 100644 --- a/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php +++ b/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php @@ -17,6 +17,7 @@ use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface; use Doctrine\ODM\MongoDB\UnitOfWork; use MongoDB\Driver\Session; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; use function spl_object_hash; @@ -30,7 +31,7 @@ final class LifecycleEventManager /** @var array> */ private array $transactionalEvents = []; - public function __construct(private DocumentManager $dm, private UnitOfWork $uow, private EventManager $evm) + public function __construct(private DocumentManager $dm, private UnitOfWork $uow, private EventManager|EventDispatcherInterface $evm) { } @@ -55,7 +56,11 @@ public function enableTransactionalMode(Session $session): void public function documentNotFound(object $proxy, $id): bool { $eventArgs = new DocumentNotFoundEventArgs($proxy, $this->dm, $id); - $this->evm->dispatchEvent(Events::documentNotFound, $eventArgs); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch(Events::documentNotFound); + } else { + $this->evm->dispatchEvent(Events::documentNotFound, $eventArgs); + } return $eventArgs->isExceptionDisabled(); } @@ -68,7 +73,11 @@ public function documentNotFound(object $proxy, $id): bool public function postCollectionLoad(PersistentCollectionInterface $coll): void { $eventArgs = new PostCollectionLoadEventArgs($coll, $this->dm); - $this->evm->dispatchEvent(Events::postCollectionLoad, $eventArgs); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::postCollectionLoad); + } else { + $this->evm->dispatchEvent(Events::postCollectionLoad, $eventArgs); + } } /** @@ -88,7 +97,7 @@ public function postPersist(ClassMetadata $class, object $document, ?Session $se $eventArgs = new LifecycleEventArgs($document, $this->dm, $session); $class->invokeLifecycleCallbacks(Events::postPersist, $document, [$eventArgs]); - $this->dispatchEvent($class, Events::postPersist, $eventArgs); + $this->dispatchEvent($class, $eventArgs); $this->cascadePostPersist($class, $document, $session); } @@ -294,13 +303,17 @@ private function cascadePostPersist(ClassMetadata $class, object $document, ?Ses } /** @param ClassMetadata $class */ - private function dispatchEvent(ClassMetadata $class, string $eventName, ?EventArgs $eventArgs = null): void + private function dispatchEvent(ClassMetadata $class, ?EventArgs $eventArgs = null): void { if ($class->isView()) { return; } - $this->evm->dispatchEvent($eventName, $eventArgs); + if ($this->evm instanceof EventDispatcherInterface) { + $this->evm->dispatch($eventArgs, Events::postPersist); + } else { + $this->evm->dispatchEvent(Events::postPersist, $eventArgs); + } } private function shouldDispatchEvent(object $document, string $eventName, ?Session $session): bool From affbab3b79d318e50c47cfbd96624cb4f86bc57f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 10 Oct 2024 00:24:22 +0200 Subject: [PATCH 3/6] - --- composer.json | 2 + lib/Doctrine/ODM/MongoDB/DocumentManager.php | 43 +++++++-- .../MongoDB/Event/DocumentNotFoundEvent.php | 49 ---------- .../ODM/MongoDB/Event/LifecycleEvent.php | 40 -------- .../MongoDB/Event/LoadClassMetadataEvent.php | 31 ------ .../ODM/MongoDB/Event/ManagerEvent.php | 23 ----- .../Event/OnClassMetadataNotFoundEvent.php | 48 ---------- .../ODM/MongoDB/Event/OnClearEvent.php | 19 ---- .../ODM/MongoDB/Event/OnFlushEvent.php | 12 --- .../MongoDB/Event/PostCollectionLoadEvent.php | 33 ------- .../ODM/MongoDB/Event/PostFlushEvent.php | 12 --- .../ODM/MongoDB/Event/PreFlushEvent.php | 12 --- .../ODM/MongoDB/Event/PreLoadEvent.php | 34 ------- .../ODM/MongoDB/Event/PreUpdateEvent.php | 95 ------------------- .../ODM/MongoDB/Hydrator/HydratorFactory.php | 16 ++-- .../MongoDB/Mapping/ClassMetadataFactory.php | 17 +--- lib/Doctrine/ODM/MongoDB/UnitOfWork.php | 33 ++----- .../ODM/MongoDB/Utility/EventDispatcher.php | 44 +++++++++ .../MongoDB/Utility/LifecycleEventManager.php | 28 ++---- 19 files changed, 106 insertions(+), 485 deletions(-) delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/PostCollectionLoadEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreFlushEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreLoadEvent.php delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php create mode 100644 lib/Doctrine/ODM/MongoDB/Utility/EventDispatcher.php diff --git a/composer.json b/composer.json index fdcf7c9a2..6f3029854 100644 --- a/composer.json +++ b/composer.json @@ -34,6 +34,7 @@ "psr/cache": "^1.0 || ^2.0 || ^3.0", "symfony/console": "^5.4 || ^6.0 || ^7.0", "symfony/deprecation-contracts": "^2.2 || ^3.0", + "symfony/event-dispatcher": "^7.1", "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { @@ -48,6 +49,7 @@ "phpunit/phpunit": "^10.4", "squizlabs/php_codesniffer": "^3.5", "symfony/cache": "^5.4 || ^6.0 || ^7.0", + "symfony/event-dispatcher-contracts": "^3.5", "vimeo/psalm": "~5.24.0" }, "conflict": { diff --git a/lib/Doctrine/ODM/MongoDB/DocumentManager.php b/lib/Doctrine/ODM/MongoDB/DocumentManager.php index deb584c22..98401fa80 100644 --- a/lib/Doctrine/ODM/MongoDB/DocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/DocumentManager.php @@ -19,6 +19,7 @@ use Doctrine\ODM\MongoDB\Repository\GridFSRepository; use Doctrine\ODM\MongoDB\Repository\RepositoryFactory; use Doctrine\ODM\MongoDB\Repository\ViewRepository; +use Doctrine\ODM\MongoDB\Utility\EventDispatcher; use Doctrine\Persistence\Mapping\ProxyClassNameResolver; use Doctrine\Persistence\ObjectManager; use InvalidArgumentException; @@ -81,7 +82,12 @@ class DocumentManager implements ObjectManager /** * The event manager that is the central point of the event system. */ - private EventManager|EventDispatcherInterface $eventManager; + private ?EventManager $eventManager; + + /** + * The event dispatcher that is the central point of the event system. + */ + private EventDispatcherInterface $eventDispatcher; /** * The Hydrator factory instance. @@ -143,11 +149,23 @@ class DocumentManager implements ObjectManager * Creates a new Document that operates on the given Mongo connection * and uses the given Configuration. */ - protected function __construct(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventManager = null) + protected function __construct(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventDispatcher = null) { - $this->config = $config ?: new Configuration(); - $this->eventManager = $eventManager ?: new EventManager(); - $this->client = $client ?: new Client( + $this->config = $config ?: new Configuration(); + + if ($eventDispatcher instanceof EventDispatcherInterface) { + // This is a new feature, we can accept that the EventManager + // is not available when and EventDispatcher is injected. + $this->eventManager = null; + $this->eventDispatcher = $eventDispatcher; + } else { + // Backward compatibility with Doctrine EventManager + // @todo deprecate and create a new Symfony EventDispatcher instance + $this->eventManager = $eventDispatcher ?? new EventManager(); + $this->eventDispatcher = new EventDispatcher($this->eventManager); + } + + $this->client = $client ?: new Client( 'mongodb://127.0.0.1', [], [ @@ -181,7 +199,7 @@ protected function __construct(?Client $client = null, ?Configuration $config = $this->config->getAutoGenerateHydratorClasses(), ); - $this->unitOfWork = new UnitOfWork($this, $this->eventManager, $this->hydratorFactory); + $this->unitOfWork = new UnitOfWork($this, $this->eventDispatcher, $this->hydratorFactory); $this->schemaManager = new SchemaManager($this, $this->metadataFactory); $this->proxyFactory = new StaticProxyFactory($this); $this->repositoryFactory = $this->config->getRepositoryFactory(); @@ -204,19 +222,24 @@ public static function create(?Client $client = null, ?Configuration $config = n return new static($client, $config, $eventManager); } - public function getEventDispatcher(): EventManager|EventDispatcherInterface + /** + * @todo should we return a {@see Symfony\Component\EventDispatcher\EventDispatcherInterface} instead? + * So that it's explicitly possible to add/remove listeners. Or we just rely on + * the object that is injected and let the user validate the subtype. + */ + public function getEventDispatcher(): EventDispatcherInterface { - return $this->eventManager; + return $this->eventDispatcher; } /** * Gets the EventManager used by the DocumentManager. * - * @deprecated Use getEventDispatcher() instead + * @deprecated Use getEventDispatcher() instead. */ public function getEventManager(): EventManager { - if (! $this->eventManager instanceof EventManager) { + if (! $this->eventManager) { throw new LogicException('Use getEventDispatcher() instead of getEventManager()'); } diff --git a/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php b/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php deleted file mode 100644 index f0b4967f9..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/DocumentNotFoundEvent.php +++ /dev/null @@ -1,49 +0,0 @@ -identifier; - } - - /** - * Indicates whether the proxy initialization exception is disabled. - */ - public function isExceptionDisabled(): bool - { - return $this->disableException; - } - - /** - * Disable the throwing of an exception - * - * This method indicates to the proxy initializer that the missing document - * has been handled and no exception should be thrown. This can't be reset. - */ - public function disableException(bool $disableException = true): void - { - $this->disableException = $disableException; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php b/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php deleted file mode 100644 index dccd5fd56..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/LifecycleEvent.php +++ /dev/null @@ -1,40 +0,0 @@ -object; - } - - public function getDocumentManager(): DocumentManager - { - return $this->objectManager; - } - - public function isInTransaction(): bool - { - return $this->session?->isInTransaction() ?? false; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php b/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php deleted file mode 100644 index 237ece2b3..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/LoadClassMetadataEvent.php +++ /dev/null @@ -1,31 +0,0 @@ -classMetadata; - } - - public function getDocumentManager(): DocumentManager - { - return $this->objectManager; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php b/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php deleted file mode 100644 index a14699d15..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/ManagerEvent.php +++ /dev/null @@ -1,23 +0,0 @@ -objectManager; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php deleted file mode 100644 index d500e6d6e..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/OnClassMetadataNotFoundEvent.php +++ /dev/null @@ -1,48 +0,0 @@ -|null */ - private ?ClassMetadata $foundMetadata = null; - - /** @psalm-param class-string $className */ - public function __construct(private string $className, DocumentManager $dm) - { - parent::__construct($dm); - } - - /** @param ClassMetadata|null $classMetadata */ - public function setFoundMetadata(?ClassMetadata $classMetadata = null): void - { - $this->foundMetadata = $classMetadata; - } - - /** @return ClassMetadata|null */ - public function getFoundMetadata(): ?ClassMetadata - { - return $this->foundMetadata; - } - - /** - * Retrieve class name for which a failed metadata fetch attempt was executed - * - * @psalm-return class-string - */ - public function getClassName(): string - { - return $this->className; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php deleted file mode 100644 index 48188406c..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/OnClearEvent.php +++ /dev/null @@ -1,19 +0,0 @@ - - */ -final class OnClearEvent extends Event -{ - use HasDocumentManager; -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php b/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php deleted file mode 100644 index 08651a44a..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/OnFlushEvent.php +++ /dev/null @@ -1,12 +0,0 @@ - $collection */ - public function __construct(private PersistentCollectionInterface $collection, DocumentManager $dm) - { - parent::__construct($dm); - } - - /** - * Gets collection that was just initialized (loaded). - * - * @return PersistentCollectionInterface - */ - public function getCollection(): PersistentCollectionInterface - { - return $this->collection; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php b/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php deleted file mode 100644 index 694683a4e..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/PostFlushEvent.php +++ /dev/null @@ -1,12 +0,0 @@ - $data */ - public function __construct( - object $document, - DocumentManager $dm, - private array &$data, - ?Session $session = null, - ) { - parent::__construct($document, $dm, $session); - } - - /** - * Get the array of data to be loaded and hydrated. - * - * @return array - */ - public function &getData(): array - { - return $this->data; - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php b/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php deleted file mode 100644 index 472835294..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/PreUpdateEvent.php +++ /dev/null @@ -1,95 +0,0 @@ - $changeSet */ - public function __construct( - object $document, - DocumentManager $dm, - private array $changeSet, - ?Session $session = null, - ) { - parent::__construct($document, $dm, $session); - } - - /** @return array */ - public function getDocumentChangeSet(): array - { - return $this->changeSet; - } - - public function hasChangedField(string $field): bool - { - return isset($this->changeSet[$field]); - } - - /** - * Gets the old value of the changeset of the changed field. - * - * @return mixed - */ - public function getOldValue(string $field) - { - $this->assertValidField($field); - - return $this->changeSet[$field][0]; - } - - /** - * Gets the new value of the changeset of the changed field. - * - * @return mixed - */ - public function getNewValue(string $field) - { - $this->assertValidField($field); - - return $this->changeSet[$field][1]; - } - - /** - * Sets the new value of this field. - * - * @param mixed $value - */ - public function setNewValue(string $field, $value): void - { - $this->assertValidField($field); - - $this->changeSet[$field][1] = $value; - $this->getDocumentManager()->getUnitOfWork()->setDocumentChangeSet($this->getDocument(), $this->changeSet); - } - - /** - * Asserts the field exists in changeset. - * - * @throws InvalidArgumentException If the field has no changeset. - */ - private function assertValidField(string $field): void - { - if (! isset($this->changeSet[$field])) { - throw new InvalidArgumentException(sprintf( - 'Field "%s" is not a valid field of the document "%s" in PreUpdateEventArgs.', - $field, - get_class($this->getDocument()), - )); - } - } -} diff --git a/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php b/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php index 6ef48f6c2..9097b1aae 100644 --- a/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Hydrator/HydratorFactory.php @@ -13,6 +13,7 @@ use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Types\Type; use Doctrine\ODM\MongoDB\UnitOfWork; +use Doctrine\ODM\MongoDB\Utility\EventDispatcher; use ProxyManager\Proxy\GhostObjectInterface; use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; @@ -48,9 +49,9 @@ final class HydratorFactory private DocumentManager $dm; /** - * The EventManager associated with this Hydrator + * The Event Dispatcher associated with this Hydrator */ - private EventManager|EventDispatcherInterface $evm; + private EventDispatcherInterface $evm; /** * Which algorithm to use to automatically (re)generate hydrator classes. @@ -86,7 +87,7 @@ public function __construct(DocumentManager $dm, EventManager|EventDispatcherInt } $this->dm = $dm; - $this->evm = $evm; + $this->evm = $evm instanceof EventManager ? new EventDispatcher($evm) : $evm; $this->hydratorDir = $hydratorDir; $this->hydratorNamespace = $hydratorNs; $this->autoGenerate = $autoGenerate; @@ -476,11 +477,8 @@ public function hydrate(object $document, array $data, array $hints = []): array $metadata->invokeLifecycleCallbacks(Events::postLoad, $document, [new LifecycleEventArgs($document, $this->dm)]); } - $eventArgs = new LifecycleEventArgs($document, $this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::postLoad); - } else { - $this->evm->dispatchEvent(Events::postLoad, $eventArgs); - } + $this->evm->dispatch(new LifecycleEventArgs($document, $this->dm), Events::postLoad); + + return $data; } } diff --git a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php index 28eb77a9f..77ebb726c 100644 --- a/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php +++ b/lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadataFactory.php @@ -4,7 +4,6 @@ namespace Doctrine\ODM\MongoDB\Mapping; -use Doctrine\Common\EventManager; use Doctrine\ODM\MongoDB\Configuration; use Doctrine\ODM\MongoDB\ConfigurationException; use Doctrine\ODM\MongoDB\DocumentManager; @@ -53,8 +52,8 @@ final class ClassMetadataFactory extends AbstractClassMetadataFactory implements /** @var MappingDriver The used metadata driver. */ private MappingDriver $driver; - /** @var EventManager|EventDispatcherInterface The event manager instance */ - private EventManager|EventDispatcherInterface $evm; + /** @var EventDispatcherInterface The event dispatcher instance */ + private EventDispatcherInterface $evm; public function setDocumentManager(DocumentManager $dm): void { @@ -78,24 +77,16 @@ protected function initialize(): void } $this->driver = $driver; - $this->evm = $this->dm->getEventManager(); + $this->evm = $this->dm->getEventDispatcher(); $this->initialized = true; } /** @param string $className */ protected function onNotFoundMetadata($className) { - if (! $this->evm->hasListeners(Events::onClassMetadataNotFound)) { - return null; - } - $eventArgs = new OnClassMetadataNotFoundEventArgs($className, $this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::onClassMetadataNotFound); - } else { - $this->evm->dispatchEvent(Events::onClassMetadataNotFound, $eventArgs); - } + $this->evm->dispatch($eventArgs, Events::onClassMetadataNotFound); return $eventArgs->getFoundMetadata(); } diff --git a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php index 6f4adb18a..ab9738ca3 100644 --- a/lib/Doctrine/ODM/MongoDB/UnitOfWork.php +++ b/lib/Doctrine/ODM/MongoDB/UnitOfWork.php @@ -235,9 +235,9 @@ final class UnitOfWork implements PropertyChangedListener private DocumentManager $dm; /** - * The EventManager used for dispatching events. + * The Event Dispatcher used for dispatching events. */ - private EventManager|EventDispatcherInterface $evm; + private EventDispatcherInterface $evm; /** * Additional documents that are scheduled for removal. @@ -296,7 +296,7 @@ final class UnitOfWork implements PropertyChangedListener public function __construct(DocumentManager $dm, EventManager|EventDispatcherInterface $evm, HydratorFactory $hydratorFactory) { $this->dm = $dm; - $this->evm = $evm; + $this->evm = $evm instanceof EventManager ? new Utility\EventDispatcher($evm) : $evm; $this->hydratorFactory = $hydratorFactory; $this->lifecycleEventManager = new LifecycleEventManager($dm, $this, $evm); $this->reflectionService = new RuntimeReflectionService(); @@ -426,12 +426,7 @@ public function commit(array $options = []): void } // Raise preFlush - $eventArgs = new Event\PreFlushEventArgs($this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::preFlush); - } else { - $this->evm->dispatchEvent(Events::preFlush, $eventArgs); - } + $this->evm->dispatch(new Event\PreFlushEventArgs($this->dm), Events::preFlush); // Compute changes done since last commit. $this->computeChangeSets(); @@ -460,12 +455,7 @@ public function commit(array $options = []): void } } - $eventArgs = new Event\OnFlushEventArgs($this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::onFlush); - } else { - $this->evm->dispatchEvent(Events::onFlush, $eventArgs); - } + $this->evm->dispatch(new Event\OnFlushEventArgs($this->dm), Events::onFlush); if ($this->useTransaction($options)) { $session = $this->dm->getClient()->startSession(); @@ -484,12 +474,7 @@ function (Session $session) use ($options): void { } // Raise postFlush - $eventArgs = new Event\PostFlushEventArgs($this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::postFlush); - } else { - $this->evm->dispatchEvent(Events::postFlush, $eventArgs); - } + $this->evm->dispatch(new Event\PostFlushEventArgs($this->dm), Events::postFlush); // Clear up foreach ($this->visitedCollections as $collections) { @@ -2446,11 +2431,7 @@ public function clear(?string $documentName = null): void $event = new Event\OnClearEventArgs($this->dm, $documentName); } - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($event, Events::onClear); - } else { - $this->evm->dispatchEvent(Events::onClear, $event); - } + $this->evm->dispatch($event, Events::onClear); } /** diff --git a/lib/Doctrine/ODM/MongoDB/Utility/EventDispatcher.php b/lib/Doctrine/ODM/MongoDB/Utility/EventDispatcher.php new file mode 100644 index 000000000..d497a187c --- /dev/null +++ b/lib/Doctrine/ODM/MongoDB/Utility/EventDispatcher.php @@ -0,0 +1,44 @@ +eventManager->dispatchEvent($eventName, $event); + + return $event; + } +} diff --git a/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php b/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php index aa47d5a51..1f95f6403 100644 --- a/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php +++ b/lib/Doctrine/ODM/MongoDB/Utility/LifecycleEventManager.php @@ -31,8 +31,11 @@ final class LifecycleEventManager /** @var array> */ private array $transactionalEvents = []; - public function __construct(private DocumentManager $dm, private UnitOfWork $uow, private EventManager|EventDispatcherInterface $evm) + private EventDispatcherInterface $evm; + + public function __construct(private DocumentManager $dm, private UnitOfWork $uow, EventManager|EventDispatcherInterface $evm) { + $this->evm = $evm instanceof EventManager ? new EventDispatcher($evm) : $evm; } public function clearTransactionalState(): void @@ -56,11 +59,7 @@ public function enableTransactionalMode(Session $session): void public function documentNotFound(object $proxy, $id): bool { $eventArgs = new DocumentNotFoundEventArgs($proxy, $this->dm, $id); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch(Events::documentNotFound); - } else { - $this->evm->dispatchEvent(Events::documentNotFound, $eventArgs); - } + $this->evm->dispatch($eventArgs, Events::documentNotFound); return $eventArgs->isExceptionDisabled(); } @@ -72,12 +71,7 @@ public function documentNotFound(object $proxy, $id): bool */ public function postCollectionLoad(PersistentCollectionInterface $coll): void { - $eventArgs = new PostCollectionLoadEventArgs($coll, $this->dm); - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::postCollectionLoad); - } else { - $this->evm->dispatchEvent(Events::postCollectionLoad, $eventArgs); - } + $this->evm->dispatch(new PostCollectionLoadEventArgs($coll, $this->dm), Events::postCollectionLoad); } /** @@ -97,7 +91,7 @@ public function postPersist(ClassMetadata $class, object $document, ?Session $se $eventArgs = new LifecycleEventArgs($document, $this->dm, $session); $class->invokeLifecycleCallbacks(Events::postPersist, $document, [$eventArgs]); - $this->dispatchEvent($class, $eventArgs); + $this->dispatchEvent($class, Events::postPersist, $eventArgs); $this->cascadePostPersist($class, $document, $session); } @@ -303,17 +297,13 @@ private function cascadePostPersist(ClassMetadata $class, object $document, ?Ses } /** @param ClassMetadata $class */ - private function dispatchEvent(ClassMetadata $class, ?EventArgs $eventArgs = null): void + private function dispatchEvent(ClassMetadata $class, string $eventName, ?EventArgs $eventArgs = null): void { if ($class->isView()) { return; } - if ($this->evm instanceof EventDispatcherInterface) { - $this->evm->dispatch($eventArgs, Events::postPersist); - } else { - $this->evm->dispatchEvent(Events::postPersist, $eventArgs); - } + $this->evm->dispatch($eventArgs, $eventName); } private function shouldDispatchEvent(object $document, string $eventName, ?Session $session): bool From f781f60f699f68a9d539c57093bf30e7220e1c08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 10 Oct 2024 01:18:58 +0200 Subject: [PATCH 4/6] Add tests on event dispatcher injection --- lib/Doctrine/ODM/MongoDB/DocumentManager.php | 6 ++--- .../ODM/MongoDB/Tests/DocumentManagerTest.php | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/Doctrine/ODM/MongoDB/DocumentManager.php b/lib/Doctrine/ODM/MongoDB/DocumentManager.php index 98401fa80..3ad53185a 100644 --- a/lib/Doctrine/ODM/MongoDB/DocumentManager.php +++ b/lib/Doctrine/ODM/MongoDB/DocumentManager.php @@ -193,7 +193,7 @@ protected function __construct(?Client $client = null, ?Configuration $config = $hydratorNs = $this->config->getHydratorNamespace(); $this->hydratorFactory = new HydratorFactory( $this, - $this->eventManager, + $this->eventDispatcher, $hydratorDir, $hydratorNs, $this->config->getAutoGenerateHydratorClasses(), @@ -217,9 +217,9 @@ public function getProxyFactory(): ProxyFactory * Creates a new Document that operates on the given Mongo connection * and uses the given Configuration. */ - public static function create(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventManager = null): DocumentManager + public static function create(?Client $client = null, ?Configuration $config = null, EventManager|EventDispatcherInterface|null $eventDispatcher = null): DocumentManager { - return new static($client, $config, $eventManager); + return new static($client, $config, $eventDispatcher); } /** diff --git a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php index 832037e53..1e1fff465 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php @@ -8,6 +8,7 @@ use Doctrine\Common\EventManager; use Doctrine\ODM\MongoDB\Aggregation\Builder as AggregationBuilder; use Doctrine\ODM\MongoDB\Configuration; +use Doctrine\ODM\MongoDB\DocumentManager; use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM; use Doctrine\ODM\MongoDB\Mapping\ClassMetadata; use Doctrine\ODM\MongoDB\Mapping\ClassMetadataFactory; @@ -36,6 +37,7 @@ use PHPUnit\Framework\Attributes\DataProvider; use RuntimeException; use stdClass; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class DocumentManagerTest extends BaseTestCase { @@ -261,6 +263,31 @@ public function testGetClassNameForAssociationReturnsTargetDocumentWithNullData( $mapping = ClassMetadataTestUtil::getFieldMapping(['targetDocument' => User::class]); self::assertEquals(User::class, $this->dm->getClassNameForAssociation($mapping, null)); } + + public function testCreateWithEventManager(): void + { + $config = static::getConfiguration(); + $client = new Client(self::getUri()); + + $eventManager = new EventManager(); + $dm = DocumentManager::create($client, $config, $eventManager); + self::assertSame($eventManager, $dm->getEventManager()); + self::assertInstanceOf(EventDispatcherInterface::class, $dm->getEventDispatcher()); + } + + public function testCreateWithEventDispatcher(): void + { + $config = static::getConfiguration(); + $client = new Client(self::getUri()); + + $eventDispatcher = $this->createMock(EventDispatcherInterface::class); + $dm = DocumentManager::create($client, $config, $eventDispatcher); + self::assertSame($eventDispatcher, $dm->getEventDispatcher()); + + self::expectException(\LogicException::class); + self::expectExceptionMessage('Use getEventDispatcher() instead of getEventManager()'); + $dm->getEventManager(); + } } #[ODM\Document] From c9b5a431a307c34304761e89d2ced11839928a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 10 Oct 2024 01:42:15 +0200 Subject: [PATCH 5/6] Fix Version --- composer.json | 3 +-- tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 6f3029854..231e99273 100644 --- a/composer.json +++ b/composer.json @@ -34,7 +34,6 @@ "psr/cache": "^1.0 || ^2.0 || ^3.0", "symfony/console": "^5.4 || ^6.0 || ^7.0", "symfony/deprecation-contracts": "^2.2 || ^3.0", - "symfony/event-dispatcher": "^7.1", "symfony/var-dumper": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { @@ -49,7 +48,7 @@ "phpunit/phpunit": "^10.4", "squizlabs/php_codesniffer": "^3.5", "symfony/cache": "^5.4 || ^6.0 || ^7.0", - "symfony/event-dispatcher-contracts": "^3.5", + "symfony/event-dispatcher-contracts": "^2.0 || ^3.0", "vimeo/psalm": "~5.24.0" }, "conflict": { diff --git a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php index 1e1fff465..b6c634976 100644 --- a/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php +++ b/tests/Doctrine/ODM/MongoDB/Tests/DocumentManagerTest.php @@ -32,6 +32,7 @@ use Documents\Tournament\ParticipantSolo; use Documents\User; use InvalidArgumentException; +use LogicException; use MongoDB\BSON\ObjectId; use MongoDB\Client; use PHPUnit\Framework\Attributes\DataProvider; @@ -281,10 +282,10 @@ public function testCreateWithEventDispatcher(): void $client = new Client(self::getUri()); $eventDispatcher = $this->createMock(EventDispatcherInterface::class); - $dm = DocumentManager::create($client, $config, $eventDispatcher); + $dm = DocumentManager::create($client, $config, $eventDispatcher); self::assertSame($eventDispatcher, $dm->getEventDispatcher()); - self::expectException(\LogicException::class); + self::expectException(LogicException::class); self::expectExceptionMessage('Use getEventDispatcher() instead of getEventManager()'); $dm->getEventManager(); } From 75c9bd27b3f36546f595006df2809b2a0659fb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 10 Oct 2024 01:44:17 +0200 Subject: [PATCH 6/6] Delete lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php --- .../ODM/MongoDB/Event/HasDocumentManager.php | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php diff --git a/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php b/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php deleted file mode 100644 index d1bcdac98..000000000 --- a/lib/Doctrine/ODM/MongoDB/Event/HasDocumentManager.php +++ /dev/null @@ -1,19 +0,0 @@ -documentManager; - } -}