diff --git a/src/EventListener/CollectsEventsFromEntities.php b/src/EventListener/CollectsEventsFromEntities.php index 74e0e48..ff893ad 100644 --- a/src/EventListener/CollectsEventsFromEntities.php +++ b/src/EventListener/CollectsEventsFromEntities.php @@ -3,8 +3,10 @@ namespace SimpleBus\DoctrineORMBridge\EventListener; use Doctrine\Common\EventSubscriber; -use Doctrine\ORM\Event\LifecycleEventArgs; use Doctrine\ORM\Events; +use Doctrine\ORM\Proxy\Proxy; +use Doctrine\ORM\Event\PreFlushEventArgs; +use Doctrine\ORM\Event\PostFlushEventArgs; use SimpleBus\Message\Recorder\ContainsRecordedMessages; class CollectsEventsFromEntities implements EventSubscriber, ContainsRecordedMessages @@ -14,25 +16,40 @@ class CollectsEventsFromEntities implements EventSubscriber, ContainsRecordedMes public function getSubscribedEvents() { return array( - Events::postPersist, - Events::postUpdate, - Events::postRemove, + Events::preFlush, + Events::postFlush ); } - public function postPersist(LifecycleEventArgs $event) + public function preFlush(PreFlushEventArgs $eventArgs) { - $this->collectEventsFromEntity($event); - } - - public function postUpdate(LifecycleEventArgs $event) - { - $this->collectEventsFromEntity($event); + $em = $eventArgs->getEntityManager(); + $uow = $em->getUnitOfWork(); + foreach ($uow->getIdentityMap() as $entities) { + foreach ($entities as $entity){ + $this->collectEventsFromEntity($entity); + } + } + foreach ($uow->getScheduledEntityDeletions() as $entity) { + $this->collectEventsFromEntity($entity); + } } - public function postRemove(LifecycleEventArgs $event) + /** + * We need to listen on postFlush for Lifecycle Events + * All Lifecycle callback events are triggered after the onFlush event + * + * @param PostFlushEventArgs $eventArgs + */ + public function postFlush(PostFlushEventArgs $eventArgs) { - $this->collectEventsFromEntity($event); + $em = $eventArgs->getEntityManager(); + $uow = $em->getUnitOfWork(); + foreach ($uow->getIdentityMap() as $entities) { + foreach ($entities as $entity){ + $this->collectEventsFromEntity($entity); + } + } } public function recordedMessages() @@ -45,15 +62,16 @@ public function eraseMessages() $this->collectedEvents = array(); } - private function collectEventsFromEntity(LifecycleEventArgs $event) + private function collectEventsFromEntity($entity) { - $entity = $event->getEntity(); - - if ($entity instanceof ContainsRecordedMessages) { + if ($entity instanceof ContainsRecordedMessages + && ( !$entity instanceof Proxy + || ($entity instanceof Proxy && $entity->__isInitialized__) + ) + ) { foreach ($entity->recordedMessages() as $event) { $this->collectedEvents[] = $event; } - $entity->eraseMessages(); } } diff --git a/tests/EventListener/CollectsEventsFromEntitiesTest.php b/tests/EventListener/CollectsEventsFromEntitiesTest.php index 1f2538c..3c8e268 100644 --- a/tests/EventListener/CollectsEventsFromEntitiesTest.php +++ b/tests/EventListener/CollectsEventsFromEntitiesTest.php @@ -7,7 +7,10 @@ use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Entity\EventRecordingEntity; use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityAboutToBeRemoved; use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityChanged; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityChangedPreUpdate; use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityCreated; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityCreatedPrePersist; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityNotDirty; use SimpleBus\Message\Recorder\ContainsRecordedMessages; class CollectsEventsFromEntitiesTest extends AbstractTestCaseWithEntityManager @@ -38,8 +41,7 @@ public function it_collects_events_from_persisted_entities_and_erases_them_after $entity = new EventRecordingEntity(); $this->persistAndFlush($entity); - - $this->assertEquals([new EntityCreated()], $this->eventSubscriber->recordedMessages()); + $this->assertContains( new EntityCreated(), $this->eventSubscriber->recordedMessages(), '', false, false ); $this->assertEntityHasNoRecordedEvents($entity); } @@ -56,7 +58,7 @@ public function it_collects_events_from_modified_entities_and_erases_them_afterw $entity->changeSomething(); $this->persistAndFlush($entity); - $this->assertEquals([new EntityChanged()], $this->eventSubscriber->recordedMessages()); + $this->assertContains( new EntityChanged(), $this->eventSubscriber->recordedMessages(), '', false, false ); $this->assertEntityHasNoRecordedEvents($entity); } @@ -78,6 +80,53 @@ public function it_collects_events_from_removed_entities_and_erases_them_afterwa $this->assertEntityHasNoRecordedEvents($entity); } + /** + * @test + */ + public function it_collects_events_from_not_dirty_entities_and_erases_them_afterwards() + { + $entity = new EventRecordingEntity(); + $this->persistAndFlush($entity); + $this->eraseRecordedMessages(); + + $entity->recordMessageWithoutStateChange(); + $this->persistAndFlush($entity); + + $this->assertEquals([new EntityNotDirty()], $this->eventSubscriber->recordedMessages()); + + $this->assertEntityHasNoRecordedEvents($entity); + } + + /** + * @test + */ + public function it_collects_events_from_pre_persist_lifecycle_callbacks_of_entities_and_erases_them_afterwards() + { + $entity = new EventRecordingEntity(); + $this->persistAndFlush($entity); + + $this->assertContains( new EntityCreatedPrePersist(), $this->eventSubscriber->recordedMessages(), '', false, false ); + + $this->assertEntityHasNoRecordedEvents($entity); + } + + /** + * @test + */ + public function it_collects_events_from_pre_update_lifecycle_callbacks_of_dirty_entities_and_erases_them_afterwards() + { + $entity = new EventRecordingEntity(); + $this->persistAndFlush($entity); + $this->eraseRecordedMessages(); + + $entity->changeSomethingWithoutRecording(); + $this->persistAndFlush($entity); + + $this->assertEquals([new EntityChangedPreUpdate()], $this->eventSubscriber->recordedMessages()); + + $this->assertEntityHasNoRecordedEvents($entity); + } + private function persistAndFlush($entity) { $this->getEntityManager()->persist($entity); diff --git a/tests/EventListener/Fixtures/Entity/EventRecordingEntity.php b/tests/EventListener/Fixtures/Entity/EventRecordingEntity.php index 79fa160..004f7c4 100644 --- a/tests/EventListener/Fixtures/Entity/EventRecordingEntity.php +++ b/tests/EventListener/Fixtures/Entity/EventRecordingEntity.php @@ -5,11 +5,15 @@ use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityAboutToBeRemoved; use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityChanged; use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityCreated; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityCreatedPrePersist; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityChangedPreUpdate; +use SimpleBus\DoctrineORMBridge\Tests\EventListener\Fixtures\Event\EntityNotDirty; use SimpleBus\Message\Recorder\ContainsRecordedMessages; use SimpleBus\Message\Recorder\PrivateMessageRecorderCapabilities; /** * @Entity + * @HasLifecycleCallbacks() */ class EventRecordingEntity implements ContainsRecordedMessages { @@ -41,10 +45,36 @@ public function changeSomething() $this->record(new EntityChanged()); } + public function changeSomethingWithoutRecording() + { + $this->something = 'changed value'; + } + public function prepareForRemoval() { $this->something = 'changed for the last time'; $this->record(new EntityAboutToBeRemoved()); } + + public function recordMessageWithoutStateChange() + { + $this->record(new EntityNotDirty()); + } + + /** + * @PrePersist + */ + public function recordMessageDuringPrePersistLifecycleCallback() + { + $this->record(new EntityCreatedPrePersist()); + } + + /** + * @PreUpdate + */ + public function recordMessageDuringPreUpdateLifecycleCallback() + { + $this->record(new EntityChangedPreUpdate()); + } } diff --git a/tests/EventListener/Fixtures/Event/EntityChangedPreUpdate.php b/tests/EventListener/Fixtures/Event/EntityChangedPreUpdate.php new file mode 100644 index 0000000..414cfa0 --- /dev/null +++ b/tests/EventListener/Fixtures/Event/EntityChangedPreUpdate.php @@ -0,0 +1,7 @@ +