Skip to content

Commit

Permalink
move listeners invocation from ClassMetadataInfo to ListenerInvoker
Browse files Browse the repository at this point in the history
  • Loading branch information
FabioBatSilva authored and fabio.silva committed Jan 29, 2013
1 parent c60e3e4 commit 0d0f91a
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 94 deletions.
78 changes: 78 additions & 0 deletions lib/Doctrine/ORM/Event/ListenersInvoker.php
@@ -0,0 +1,78 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the MIT license. For more information, see
* <http://www.doctrine-project.org>.
*/

namespace Doctrine\ORM\Event;

use Doctrine\ORM\Mapping\EntityListenerResolver;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Common\EventArgs;

/**
* A method invoker based on entity lifecycle.
*
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
* @since 2.4
*/
class ListenersInvoker
{
/**
* @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver.
*/
private $resolver;

/**
* @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver
*/
public function __construct(EntityListenerResolver $resolver)
{
$this->resolver = $resolver;
}

/**
* Dispatches the lifecycle event of the given entity to the registered lifecycle callbacks.
*
* @param string $eventName The entity lifecycle event.
* @param \Object $entity The Entity on which the event occured.
* @param \Doctrine\Common\EventArgs $event The Event args.
*/
public function invokeLifecycleCallbacks(ClassMetadata $metadata, $eventName, $entity, EventArgs $event)
{
foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) {
$entity->$callback($event);
}
}

/**
* Dispatches the lifecycle event of the given entity to the registered entity listeners.
*
* @param string $eventName The entity lifecycle event.
* @param object $entity The Entity on which the event occured.
* @param \Doctrine\Common\EventArgs $event The Event args.
*/
public function invokeEntityListeners(ClassMetadata $metadata, $eventName, $entity, EventArgs $event)
{
foreach ($metadata->entityListeners[$eventName] as $listener) {
$class = $listener['class'];
$method = $listener['method'];
$instance = $this->resolver->resolve($class);

$instance->{$method}($entity, $event);
}
}
}
22 changes: 2 additions & 20 deletions lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php
Expand Up @@ -27,7 +27,6 @@
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\Common\ClassLoader;
use Doctrine\Common\EventArgs;
use Doctrine\ORM\Mapping\EntityListenerResolver;

/**
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata
Expand Down Expand Up @@ -2426,6 +2425,8 @@ public function setCustomRepositoryClass($repositoryClassName)
* Dispatches the lifecycle event of the given entity to the registered
* lifecycle callbacks and lifecycle listeners.
*
* @deprecated Deprecated since version 2.4 in favor of \Doctrine\ORM\Event\ListenersInvoker
*
* @param string $lifecycleEvent The lifecycle event.
* @param object $entity The Entity on which the event occured.
*
Expand Down Expand Up @@ -2513,25 +2514,6 @@ public function addEntityListener($eventName, $class, $method)
);
}

/**
* Call the entity listeners.
*
* @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver The Entity listener resolver.
* @param string $eventName The event name.
* @param object $entity An instance of the mapped entity
* @param \Doctrine\Common\EventArgs $arg The Event args
*/
public function dispatchEntityListeners(EntityListenerResolver $resolver, $eventName, $entity, EventArgs $arg)
{
foreach ($this->entityListeners[$eventName] as $listener) {
$class = $listener['class'];
$method = $listener['method'];
$instance = $resolver->resolve($class);

$instance->{$method}($entity, $arg);
}
}

/**
* Sets the discriminator column definition.
*
Expand Down
45 changes: 23 additions & 22 deletions lib/Doctrine/ORM/UnitOfWork.php
Expand Up @@ -36,6 +36,7 @@
use Doctrine\ORM\Event\PreFlushEventArgs;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Event\PostFlushEventArgs;
use Doctrine\ORM\Event\ListenersInvoker;

/**
* The UnitOfWork is responsible for tracking changes to objects during an
Expand Down Expand Up @@ -219,11 +220,11 @@ class UnitOfWork implements PropertyChangedListener
private $evm;

/**
* The EntityListenerResolver used for dispatching events.
* The ListenersInvoker used for dispatching events.
*
* @var \Doctrine\ORM\Mapping\EntityListenerResolver
* @var \Doctrine\ORM\Event\ListenersInvoker
*/
private $entityListenerResolver;
private $listenersInvoker;

/**
* Orphaned entities that are scheduled for removal.
Expand Down Expand Up @@ -253,9 +254,9 @@ class UnitOfWork implements PropertyChangedListener
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
$this->evm = $em->getEventManager();
$this->entityListenerResolver = $em->getConfiguration()->getEntityListenerResolver();
$this->em = $em;
$this->evm = $em->getEventManager();
$this->listenersInvoker = new ListenersInvoker($em->getConfiguration()->getEntityListenerResolver());
}

/**
Expand Down Expand Up @@ -528,12 +529,12 @@ public function computeChangeSet(ClassMetadata $class, $entity)

// Fire PreFlush lifecycle callbacks
if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preFlush, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preFlush, $entity, $event);
}

// Fire PreFlush entity listeners
if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::preFlush, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::preFlush, $entity, $event);
}

$actualData = array();
Expand Down Expand Up @@ -840,11 +841,11 @@ private function persistNew($class, $entity)
}

if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::prePersist, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::prePersist, $entity, $event);
}

if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::prePersist, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::prePersist, $entity, $event);
}

if ($hasListeners) {
Expand Down Expand Up @@ -990,11 +991,11 @@ private function executeInserts($class)
}

if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::postPersist, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postPersist, $entity, $event);
}

if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::postPersist, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::postPersist, $entity, $event);
}

if ($hasListeners) {
Expand Down Expand Up @@ -1037,13 +1038,13 @@ private function executeUpdates($class)
}

if ($hasPreUpdateLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity, $preEvent);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preUpdate, $entity, $preEvent);

$this->recomputeSingleEntityChangeSet($class, $entity);
}

if ($hasPreUpdateEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::preUpdate, $entity, $preEvent);
$this->listenersInvoker->invokeEntityListeners($class, Events::preUpdate, $entity, $preEvent);
}

if ($hasPreUpdateListeners) {
Expand All @@ -1057,11 +1058,11 @@ private function executeUpdates($class)
unset($this->entityUpdates[$oid]);

if ($hasPostUpdateLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::postUpdate, $entity, $postEvent);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postUpdate, $entity, $postEvent);
}

if ($hasPostUpdateEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::postUpdate, $entity, $postEvent);
$this->listenersInvoker->invokeEntityListeners($class, Events::postUpdate, $entity, $postEvent);
}

if ($hasPostUpdateListeners) {
Expand Down Expand Up @@ -1112,11 +1113,11 @@ private function executeDeletions($class)
}

if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::postRemove, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postRemove, $entity, $event);
}

if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::postRemove, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::postRemove, $entity, $event);
}

if ($hasListeners) {
Expand Down Expand Up @@ -1769,11 +1770,11 @@ private function doRemove($entity, array &$visited)
}

if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preRemove, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preRemove, $entity, $event);
}

if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::preRemove, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::preRemove, $entity, $event);
}

if ($hasListeners) {
Expand Down Expand Up @@ -2785,11 +2786,11 @@ public function createEntity($className, array $data, &$hints = array())
}

if ($hasLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::postLoad, $entity, $event);
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postLoad, $entity, $event);
}

if ($hasEntityListeners) {
$class->dispatchEntityListeners($this->entityListenerResolver, Events::postLoad, $entity, $event);
$this->listenersInvoker->invokeEntityListeners($class, Events::postLoad, $entity, $event);
}

if ($hasListeners) {
Expand Down
52 changes: 0 additions & 52 deletions tests/Doctrine/Tests/ORM/Mapping/AbstractMappingDriverTest.php
Expand Up @@ -804,58 +804,6 @@ public function testEntityListeners()
$this->assertEquals('Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener', $prePersist['class']);
$this->assertEquals('prePersistHandler2', $prePersist['method']);
}

/**
* @group DDC-1955
*/
public function testCallEntityListeners()
{
$em = $this->_getTestEntityManager();
$factory = $this->createClassMetadataFactory($em);
$resolver = $em->getConfiguration()->getEntityListenerResolver();
$flexClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFixContract');
$fixClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFlexContract');
$ultraClass = $factory->getMetadataFor('Doctrine\Tests\Models\Company\CompanyFlexUltraContract');
$contractListener = $resolver->resolve('Doctrine\Tests\Models\Company\CompanyContractListener');
$ultraContractListener = $resolver->resolve('Doctrine\Tests\Models\Company\CompanyFlexUltraContractListener');

$contractListener->prePersistCalls = array();
$contractListener->postPersistCalls = array();
$ultraContractListener->prePersistCalls = array();

$fix = new CompanyFixContract();
$fixArg = new LifecycleEventArgs($fix, $em);

$flex = new CompanyFlexContract();
$flexArg = new LifecycleEventArgs($fix, $em);

$ultra = new CompanyFlexContract();
$ultraArg = new LifecycleEventArgs($ultra, $em);

$fixClass->dispatchEntityListeners($resolver, Events::prePersist, $fix, $fixArg);
$flexClass->dispatchEntityListeners($resolver, Events::prePersist, $flex, $flexArg);
$ultraClass->dispatchEntityListeners($resolver, Events::prePersist, $ultra, $ultraArg);

$this->assertCount(3, $contractListener->prePersistCalls);
$this->assertCount(2, $ultraContractListener->prePersistCalls);

$this->assertSame($fix, $contractListener->prePersistCalls[0][0]);
$this->assertSame($fixArg, $contractListener->prePersistCalls[0][1]);

$this->assertSame($flex, $contractListener->prePersistCalls[1][0]);
$this->assertSame($flexArg, $contractListener->prePersistCalls[1][1]);

$this->assertSame($ultra, $contractListener->prePersistCalls[2][0]);
$this->assertSame($ultraArg, $contractListener->prePersistCalls[2][1]);

$this->assertSame($ultra, $ultraContractListener->prePersistCalls[0][0]);
$this->assertSame($ultraArg, $ultraContractListener->prePersistCalls[0][1]);

$this->assertSame($ultra, $ultraContractListener->prePersistCalls[1][0]);
$this->assertSame($ultraArg, $ultraContractListener->prePersistCalls[1][1]);

$this->assertEmpty($contractListener->postPersistCalls);
}
}

/**
Expand Down

0 comments on commit 0d0f91a

Please sign in to comment.