1
0
mirror of synced 2025-01-29 19:41:45 +03:00

Use bitmask of subscribed event systems.

This commit is contained in:
Fabio B. Silva 2012-11-09 16:46:56 -02:00 committed by fabio.silva
parent 7b0f59ed7c
commit 6d7b3863b5
3 changed files with 101 additions and 174 deletions

View File

@ -19,8 +19,8 @@
namespace Doctrine\ORM\Event; namespace Doctrine\ORM\Event;
use Doctrine\ORM\Mapping\EntityListenerResolver;
use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\EntityManager;
use Doctrine\Common\EventArgs; use Doctrine\Common\EventArgs;
/** /**
@ -31,48 +31,90 @@ use Doctrine\Common\EventArgs;
*/ */
class ListenersInvoker class ListenersInvoker
{ {
const INVOKE_NONE = 0;
const INVOKE_LISTENERS = 1;
const INVOKE_CALLBACKS = 2;
const INVOKE_MANAGER = 4;
/** /**
* @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver. * @var \Doctrine\ORM\Mapping\EntityListenerResolver The Entity listener resolver.
*/ */
private $resolver; private $resolver;
/** /**
* @param \Doctrine\ORM\Mapping\EntityListenerResolver $resolver * The EventManager used for dispatching events.
*
* @var \Doctrine\Common\EventManager
*/ */
public function __construct(EntityListenerResolver $resolver) private $eventManager;
/**
* Initializes a new ListenersInvoker instance.
*
* @param \Doctrine\ORM\EntityManager $em
*/
public function __construct(EntityManager $em)
{ {
$this->resolver = $resolver; $this->eventManager = $em->getEventManager();
$this->resolver = $em->getConfiguration()->getEntityListenerResolver();
} }
/** /**
* Dispatches the lifecycle event of the given entity to the registered lifecycle callbacks. * Get the subscribed event systems
* *
* @param string $eventName The entity lifecycle event. * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata.
* @param \Object $entity The Entity on which the event occured. * @param string $eventName The entity lifecycle event.
* @param \Doctrine\Common\EventArgs $event The Event args. *
* @return integer Bitmask of subscribed event systems.
*/ */
public function invokeLifecycleCallbacks(ClassMetadata $metadata, $eventName, $entity, EventArgs $event) public function getSubscribedSystems(ClassMetadata $metadata, $eventName)
{ {
foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) { $invoke = self::INVOKE_NONE;
$entity->$callback($event);
if (isset($metadata->lifecycleCallbacks[$eventName])) {
$invoke |= self::INVOKE_CALLBACKS;
} }
if (isset($metadata->entityListeners[$eventName])) {
$invoke |= self::INVOKE_LISTENERS;
}
if ($this->eventManager->hasListeners($eventName)) {
$invoke |= self::INVOKE_MANAGER;
}
return $invoke;
} }
/** /**
* Dispatches the lifecycle event of the given entity to the registered entity listeners. * Dispatches the lifecycle event of the given entity.
* *
* @param string $eventName The entity lifecycle event. * @param \Doctrine\ORM\Mapping\ClassMetadata $metadata The entity metadata.
* @param object $entity The Entity on which the event occured. * @param string $eventName The entity lifecycle event.
* @param \Doctrine\Common\EventArgs $event The Event args. * @param object $entity The Entity on which the event occured.
* @param \Doctrine\Common\EventArgs $event The Event args.
* @param integer $invoke Bitmask to invoke listeners.
*/ */
public function invokeEntityListeners(ClassMetadata $metadata, $eventName, $entity, EventArgs $event) public function invoke(ClassMetadata $metadata, $eventName, $entity, EventArgs $event, $invoke)
{ {
foreach ($metadata->entityListeners[$eventName] as $listener) { if($invoke & self::INVOKE_CALLBACKS) {
$class = $listener['class']; foreach ($metadata->lifecycleCallbacks[$eventName] as $callback) {
$method = $listener['method']; $entity->$callback($event);
$instance = $this->resolver->resolve($class); }
}
$instance->$method($entity, $event); if($invoke & self::INVOKE_LISTENERS) {
foreach ($metadata->entityListeners[$eventName] as $listener) {
$class = $listener['class'];
$method = $listener['method'];
$instance = $this->resolver->resolve($class);
$instance->$method($entity, $event);
}
}
if($invoke & self::INVOKE_MANAGER) {
$this->eventManager->dispatchEvent($eventName, $event);
} }
} }
} }

View File

@ -2432,10 +2432,10 @@ class ClassMetadataInfo implements ClassMetadata
* *
* @return void * @return void
*/ */
public function invokeLifecycleCallbacks($lifecycleEvent, $entity, EventArgs $event) public function invokeLifecycleCallbacks($lifecycleEvent, $entity)
{ {
foreach ($this->lifecycleCallbacks[$lifecycleEvent] as $callback) { foreach ($this->lifecycleCallbacks[$lifecycleEvent] as $callback) {
$entity->$callback($event); $entity->$callback();
} }
} }

View File

@ -256,7 +256,7 @@ class UnitOfWork implements PropertyChangedListener
{ {
$this->em = $em; $this->em = $em;
$this->evm = $em->getEventManager(); $this->evm = $em->getEventManager();
$this->listenersInvoker = new ListenersInvoker($em->getConfiguration()->getEntityListenerResolver()); $this->listenersInvoker = new ListenersInvoker($em);
} }
/** /**
@ -511,13 +511,7 @@ class UnitOfWork implements PropertyChangedListener
*/ */
public function computeChangeSet(ClassMetadata $class, $entity) public function computeChangeSet(ClassMetadata $class, $entity)
{ {
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
$hasEntityListeners = isset($class->entityListeners[Events::preFlush]);
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::preFlush]);
if ($hasEntityListeners || $hasLifecycleCallbacks) {
$event = new PreFlushEventArgs($entity, $this->em);
}
if (isset($this->readOnlyObjects[$oid])) { if (isset($this->readOnlyObjects[$oid])) {
return; return;
@ -527,14 +521,10 @@ class UnitOfWork implements PropertyChangedListener
$class = $this->em->getClassMetadata(get_class($entity)); $class = $this->em->getClassMetadata(get_class($entity));
} }
// Fire PreFlush lifecycle callbacks $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preFlush);
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preFlush, $entity, $event);
}
// Fire PreFlush entity listeners if ($invoke != ListenersInvoker::INVOKE_NONE) {
if ($hasEntityListeners) { $this->listenersInvoker->invoke($class, Events::preFlush, $entity, new PreFlushEventArgs($entity, $this->em), $invoke);
$this->listenersInvoker->invokeEntityListeners($class, Events::preFlush, $entity, $event);
} }
$actualData = array(); $actualData = array();
@ -831,25 +821,11 @@ class UnitOfWork implements PropertyChangedListener
*/ */
private function persistNew($class, $entity) private function persistNew($class, $entity)
{ {
$oid = spl_object_hash($entity); $oid = spl_object_hash($entity);
$hasListeners = $this->evm->hasListeners(Events::prePersist); $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::prePersist);
$hasEntityListeners = isset($class->entityListeners[Events::prePersist]);
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::prePersist]);
if ($hasListeners || $hasEntityListeners || $hasLifecycleCallbacks) { if ($invoke != ListenersInvoker::INVOKE_NONE) {
$event = new LifecycleEventArgs($entity, $this->em); $this->listenersInvoker->invoke($class, Events::prePersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
}
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::prePersist, $entity, $event);
}
if ($hasEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::prePersist, $entity, $event);
}
if ($hasListeners) {
$this->evm->dispatchEvent(Events::prePersist, $event);
} }
$idGen = $class->idGenerator; $idGen = $class->idGenerator;
@ -945,13 +921,10 @@ class UnitOfWork implements PropertyChangedListener
*/ */
private function executeInserts($class) private function executeInserts($class)
{ {
$className = $class->name; $entities = array();
$persister = $this->getEntityPersister($className); $className = $class->name;
$entities = array(); $persister = $this->getEntityPersister($className);
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postPersist);
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postPersist]);
$hasEntityListeners = isset($class->entityListeners[Events::postPersist]);
$hasListeners = $this->evm->hasListeners(Events::postPersist);
foreach ($this->entityInsertions as $oid => $entity) { foreach ($this->entityInsertions as $oid => $entity) {
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
@ -962,7 +935,7 @@ class UnitOfWork implements PropertyChangedListener
unset($this->entityInsertions[$oid]); unset($this->entityInsertions[$oid]);
if ($hasLifecycleCallbacks || $hasEntityListeners || $hasListeners) { if ($invoke != ListenersInvoker::INVOKE_NONE) {
$entities[] = $entity; $entities[] = $entity;
} }
} }
@ -984,23 +957,9 @@ class UnitOfWork implements PropertyChangedListener
$this->addToIdentityMap($entity); $this->addToIdentityMap($entity);
} }
} }
foreach ($entities as $entity) { foreach ($entities as $entity) {
if ($hasListeners || $hasEntityListeners | $hasLifecycleCallbacks) { $this->listenersInvoker->invoke($class, Events::postPersist, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
$event = new LifecycleEventArgs($entity, $this->em);
}
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postPersist, $entity, $event);
}
if ($hasEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::postPersist, $entity, $event);
}
if ($hasListeners) {
$this->evm->dispatchEvent(Events::postPersist, $event);
}
} }
} }
@ -1013,60 +972,29 @@ class UnitOfWork implements PropertyChangedListener
*/ */
private function executeUpdates($class) private function executeUpdates($class)
{ {
$className = $class->name; $className = $class->name;
$persister = $this->getEntityPersister($className); $persister = $this->getEntityPersister($className);
$preUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preUpdate);
$hasPreUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::preUpdate]); $postUpdateInvoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postUpdate);
$hasPreUpdateEntityListeners = isset($class->entityListeners[Events::preUpdate]);
$hasPreUpdateListeners = $this->evm->hasListeners(Events::preUpdate);
$hasPostUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postUpdate]);
$hasPostUpdateEntityListeners = isset($class->entityListeners[Events::postUpdate]);
$hasPostUpdateListeners = $this->evm->hasListeners(Events::postUpdate);
foreach ($this->entityUpdates as $oid => $entity) { foreach ($this->entityUpdates as $oid => $entity) {
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
continue; continue;
} }
if ($hasPreUpdateListeners || $hasPreUpdateEntityListeners || $hasPreUpdateLifecycleCallbacks) { if ($preUpdateInvoke != ListenersInvoker::INVOKE_NONE) {
$preEvent = new PreUpdateEventArgs($entity, $this->em, $this->entityChangeSets[$oid]); $this->listenersInvoker->invoke($class, Events::preUpdate, $entity, new PreUpdateEventArgs($entity, $this->em, $this->entityChangeSets[$oid]), $preUpdateInvoke);
}
if ($hasPostUpdateListeners || $hasPostUpdateEntityListeners || $hasPostUpdateLifecycleCallbacks) {
$postEvent = new LifecycleEventArgs($entity, $this->em);
}
if ($hasPreUpdateLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preUpdate, $entity, $preEvent);
$this->recomputeSingleEntityChangeSet($class, $entity); $this->recomputeSingleEntityChangeSet($class, $entity);
} }
if ($hasPreUpdateEntityListeners) { if ( ! empty($this->entityChangeSets[$oid])) {
$this->listenersInvoker->invokeEntityListeners($class, Events::preUpdate, $entity, $preEvent);
}
if ($hasPreUpdateListeners) {
$this->evm->dispatchEvent(Events::preUpdate, $preEvent);
}
if (!empty($this->entityChangeSets[$oid])) {
$persister->update($entity); $persister->update($entity);
} }
unset($this->entityUpdates[$oid]); unset($this->entityUpdates[$oid]);
if ($hasPostUpdateLifecycleCallbacks) { if ($postUpdateInvoke != ListenersInvoker::INVOKE_NONE) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postUpdate, $entity, $postEvent); $this->listenersInvoker->invoke($class, Events::postUpdate, $entity, new LifecycleEventArgs($entity, $this->em), $postUpdateInvoke);
}
if ($hasPostUpdateEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::postUpdate, $entity, $postEvent);
}
if ($hasPostUpdateListeners) {
$this->evm->dispatchEvent(Events::postUpdate, $postEvent);
} }
} }
} }
@ -1080,12 +1008,9 @@ class UnitOfWork implements PropertyChangedListener
*/ */
private function executeDeletions($class) private function executeDeletions($class)
{ {
$className = $class->name; $className = $class->name;
$persister = $this->getEntityPersister($className); $persister = $this->getEntityPersister($className);
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postRemove);
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postRemove]);
$hasEntityListeners = isset($class->entityListeners[Events::postRemove]);
$hasListeners = $this->evm->hasListeners(Events::postRemove);
foreach ($this->entityDeletions as $oid => $entity) { foreach ($this->entityDeletions as $oid => $entity) {
if ($this->em->getClassMetadata(get_class($entity))->name !== $className) { if ($this->em->getClassMetadata(get_class($entity))->name !== $className) {
@ -1108,20 +1033,8 @@ class UnitOfWork implements PropertyChangedListener
$class->reflFields[$class->identifier[0]]->setValue($entity, null); $class->reflFields[$class->identifier[0]]->setValue($entity, null);
} }
if ($hasListeners || $hasEntityListeners || $hasLifecycleCallbacks) { if ($invoke != ListenersInvoker::INVOKE_NONE) {
$event = new LifecycleEventArgs($entity, $this->em); $this->listenersInvoker->invoke($class, Events::postRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
}
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postRemove, $entity, $event);
}
if ($hasEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::postRemove, $entity, $event);
}
if ($hasListeners) {
$this->evm->dispatchEvent(Events::postRemove, $event);
} }
} }
} }
@ -1761,24 +1674,10 @@ class UnitOfWork implements PropertyChangedListener
break; break;
case self::STATE_MANAGED: case self::STATE_MANAGED:
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::preRemove]); $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::preRemove);
$hasEntityListeners = isset($class->entityListeners[Events::preRemove]);
$hasListeners = $this->evm->hasListeners(Events::preRemove);
if ($hasListeners || $hasEntityListeners || $hasLifecycleCallbacks) { if ($invoke != ListenersInvoker::INVOKE_NONE) {
$event = new LifecycleEventArgs($entity, $this->em); $this->listenersInvoker->invoke($class, Events::preRemove, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
}
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::preRemove, $entity, $event);
}
if ($hasEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::preRemove, $entity, $event);
}
if ($hasListeners) {
$this->evm->dispatchEvent(Events::preRemove, $event);
} }
$this->scheduleForDelete($entity); $this->scheduleForDelete($entity);
@ -2777,24 +2676,10 @@ class UnitOfWork implements PropertyChangedListener
} }
if ($overrideLocalValues) { if ($overrideLocalValues) {
$hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postLoad]); $invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad);
$hasEntityListeners = isset($class->entityListeners[Events::postLoad]);
$hasListeners = $this->evm->hasListeners(Events::postLoad);
if ($hasListeners || $hasEntityListeners || $hasLifecycleCallbacks) { if ($invoke != ListenersInvoker::INVOKE_NONE) {
$event = new LifecycleEventArgs($entity, $this->em); $this->listenersInvoker->invoke($class, Events::postLoad, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
}
if ($hasLifecycleCallbacks) {
$this->listenersInvoker->invokeLifecycleCallbacks($class, Events::postLoad, $entity, $event);
}
if ($hasEntityListeners) {
$this->listenersInvoker->invokeEntityListeners($class, Events::postLoad, $entity, $event);
}
if ($hasListeners) {
$this->evm->dispatchEvent(Events::postLoad, $event);
} }
} }