From 692448f5e191ba0697cfa1c9ad5f2b5422d7908a Mon Sep 17 00:00:00 2001 From: Nyholm Date: Sat, 13 Oct 2018 14:11:40 +0200 Subject: [PATCH] Add support for "recording" events from entities --- .../EntityMessageCollectionInterface.php | 31 ++++++++++ .../EntityMessage/MessageRecorderTrait.php | 50 +++++++++++++++ .../EntityMessageCollector.php | 61 +++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/EntityMessageCollectionInterface.php create mode 100644 src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/MessageRecorderTrait.php create mode 100644 src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php diff --git a/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/EntityMessageCollectionInterface.php b/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/EntityMessageCollectionInterface.php new file mode 100644 index 0000000000000..48b63d7ded7d0 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/EntityMessageCollectionInterface.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger\EntityMessage; + +/** + * @author Tobias Nyholm + * @author Matthias Noback + */ +interface EntityMessageCollectionInterface +{ + /** + * Fetch recorded messages. + * + * @return object[] + */ + public function getRecordedMessages(): array; + + /** + * Remove all recorded messages. + */ + public function resetRecordedMessages(): void; +} diff --git a/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/MessageRecorderTrait.php b/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/MessageRecorderTrait.php new file mode 100644 index 0000000000000..b08d612578495 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Messenger/EntityMessage/MessageRecorderTrait.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger\EntityMessage; + +/** + * Use this trait in classes which implement EntityMessageCollectionInterface + * to privately record and later release Message instances, like events. + * + * @author Tobias Nyholm + * @author Matthias Noback + */ +trait MessageRecorderTrait +{ + private $messages = []; + + /** + * {@inheritdoc} + */ + public function getRecordedMessages(): array + { + return $this->messages; + } + + /** + * {@inheritdoc} + */ + public function resetRecordedMessages(): void + { + $this->messages = []; + } + + /** + * Record a message. + * + * @param object $message + */ + private function record($message): void + { + $this->messages[] = $message; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php b/src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php new file mode 100644 index 0000000000000..997fc0d792e63 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Messenger/EventSubscriber/EntityMessageCollector.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Messenger\EventSubscriber; + +use Doctrine\Common\EventSubscriber; +use Doctrine\ORM\Event\LifecycleEventArgs; +use Doctrine\ORM\Events; +use Symfony\Bridge\Doctrine\Messenger\EntityMessage\EntityMessageCollectionInterface; +use Symfony\Component\Messenger\MessageBusInterface; +use Symfony\Component\Messenger\Stamp\DispatchAfterCurrentBusStamp; + +/** + * Doctrine listener that listens to Persist, Update and Remove. Every time this is + * invoked we take messages from the entities. + * + * @author Tobias Nyholm + * @author Matthias Noback + */ +class EntityMessageCollector implements EventSubscriber +{ + private $messageBus; + + public function __construct(MessageBusInterface $messageBus) + { + $this->messageBus = $messageBus; + } + + public function getSubscribedEvents() + { + return [ + Events::postFlush, + ]; + } + + public function postFlush(LifecycleEventArgs $event) + { + $this->collectEventsFromEntity($event); + } + + private function collectEventsFromEntity(LifecycleEventArgs $message) + { + $entity = $message->getEntity(); + + if ($entity instanceof EntityMessageCollectionInterface) { + foreach ($entity->getRecordedMessages() as $message) { + $this->messageBus->dispatch($message, [new DispatchAfterCurrentBusStamp()]); + } + + $entity->resetRecordedMessages(); + } + } +}