1
0
mirror of synced 2025-01-10 11:07:10 +03:00
doctrine2/lib/Doctrine/ORM/Internal/HydrationCompleteHandler.php
Strate 35ea399d33 DDC-3005 Defer invoking of postLoad event to the end of hydration cycle.
1. Refactor handling of hydration complete: delegate this task to special object
2. Write test case for situation, when inside postLoad listener other entity is loading.
3. Make test, written on second step, be able to pass :)
2015-01-12 22:34:24 +01:00

109 lines
3.5 KiB
PHP

<?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\Internal;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\Event\ListenersInvoker;
use Doctrine\ORM\Events;
use Doctrine\ORM\UnitOfWork;
/**
* Class, which can handle completion of hydration cycle and produce some of tasks.
* In current implementation triggers deferred postLoad event.
*
* TODO Move deferred eager loading here
*
* @author Artur Eshenbrener <strate@yandex.ru>
* @since 2.5
*/
class HydrationCompleteHandler
{
/** @var \Doctrine\ORM\UnitOfWork */
private $uow;
/** @var \Doctrine\ORM\Event\ListenersInvoker */
private $listenersInvoker;
/** @var \Doctrine\ORM\EntityManager */
private $em;
/** @var array */
private $deferredPostLoadInvocations = array();
/**
* Constructor for this object
*
* @param UnitOfWork $uow
* @param \Doctrine\ORM\Event\ListenersInvoker $listenersInvoker
* @param \Doctrine\ORM\EntityManager $em
*
* @since 2.5
*/
public function __construct(UnitOfWork $uow, ListenersInvoker $listenersInvoker, EntityManager $em)
{
$this->uow = $uow;
$this->listenersInvoker = $listenersInvoker;
$this->em = $em;
}
/**
* Method schedules invoking of postLoad entity to the very end of current hydration cycle.
*
* @since 2.5
*
* @param ClassMetadata $class
* @param object $entity
*/
public function deferPostLoadInvoking(ClassMetadata $class, $entity)
{
$this->deferredPostLoadInvocations[] = array($class, $entity);
}
/**
* This method should me called after any hydration cycle completed.
* @since 2.5
*/
public function hydrationComplete()
{
$this->invokeAllDeferredPostLoadEvents();
}
/**
* Method fires all deferred invocations of postLoad events
* @since 2.5
*/
private function invokeAllDeferredPostLoadEvents()
{
$toInvoke = $this->deferredPostLoadInvocations;
$this->deferredPostLoadInvocations = array();
foreach ($toInvoke as $classAndEntity) {
list($class, $entity) = $classAndEntity;
$invoke = $this->listenersInvoker->getSubscribedSystems($class, Events::postLoad);
if ($invoke !== ListenersInvoker::INVOKE_NONE) {
$this->listenersInvoker->invoke($class, Events::postLoad, $entity, new LifecycleEventArgs($entity, $this->em), $invoke);
}
}
}
}