1
0
mirror of synced 2025-01-18 22:41:43 +03:00

[2.0] DDC-358 - Refactored UnitOfWork Event triggering capabilities

This commit is contained in:
beberlei 2010-02-21 21:55:39 +00:00
parent 30712c6cb5
commit ac62e4d9bb
3 changed files with 100 additions and 58 deletions

View File

@ -11,7 +11,7 @@ class ArrayType extends Type
{
public function getSqlDeclaration(array $fieldDeclaration, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)
{
return $platform->getClobDeclarationSql($fieldDeclaration);
return $platform->getClobTypeDeclarationSql($fieldDeclaration);
}
public function convertToDatabaseValue($value, \Doctrine\DBAL\Platforms\AbstractPlatform $platform)

View File

@ -1,26 +1,66 @@
<?php
/*
* $Id$
*
* 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 LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Event;
use Doctrine\ORM\EntityManager;
/**
* Lifecycle Events are triggered by the UnitOfWork
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 1.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class LifecycleEventArgs extends \Doctrine\Common\EventArgs
{
//private $_em;
/**
* @var EntityManager
*/
private $_em;
/**
* @var object
*/
private $_entity;
public function __construct($entity)
public function __construct($entity, EntityManager $em)
{
$this->_entity = $entity;
$this->_em = $em;
}
public function getEntity()
{
return $this->_entity;
}
/*
/**
* @return EntityManager
*/
public function getEntityManager()
{
return $this->_em;
}
*/
}

View File

@ -365,6 +365,29 @@ class UnitOfWork implements PropertyChangedListener
return array();
}
/**
* Method can be used to compute the change-set of any entity.
*
* @Internal
*
* @Todo inline _computeChangeSet to here?
*
* @param ClassMetadata $class
* @param object $entity
* @return void
*/
public function computeChangeSet($class, $entity)
{
$this->_computeEntityChanges($class, $entity);
// Look for changes in associations of the entity
foreach ($class->associationMappings as $assoc) {
$val = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
if ($val !== null) {
$this->_computeAssociationChanges($assoc, $val);
}
}
}
/**
* Computes all the changes that have been done to entities and collections
* since the last commit and stores these changes in the _entityChangeSet map
@ -375,14 +398,7 @@ class UnitOfWork implements PropertyChangedListener
// Compute changes for INSERTed entities first. This must always happen.
foreach ($this->_entityInsertions as $entity) {
$class = $this->_em->getClassMetadata(get_class($entity));
$this->_computeEntityChanges($class, $entity);
// Look for changes in associations of the entity
foreach ($class->associationMappings as $assoc) {
$val = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
if ($val !== null) {
$this->_computeAssociationChanges($assoc, $val);
}
}
$this->computeChangeSet($class, $entity);
}
// Compute changes for other MANAGED entities. Change tracking policies take effect here.
@ -406,14 +422,7 @@ class UnitOfWork implements PropertyChangedListener
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION are processed here.
$oid = spl_object_hash($entity);
if ( ! isset($this->_entityInsertions[$oid]) && isset($this->_entityStates[$oid])) {
$this->_computeEntityChanges($class, $entity);
// Look for changes in associations of the entity
foreach ($class->associationMappings as $assoc) {
$val = $class->reflFields[$assoc->sourceFieldName]->getValue($entity);
if ($val !== null) {
$this->_computeAssociationChanges($assoc, $val);
}
}
$this->computeChangeSet($class, $entity);
}
}
}
@ -528,11 +537,26 @@ class UnitOfWork implements PropertyChangedListener
}
}
if ($changeSet) {
if ($entityIsDirty) {
$this->_entityUpdates[$oid] = $entity;
}
$this->_entityChangeSets[$oid] = $changeSet;
$this->_originalEntityData[$oid] = $actualData;
if ($entityIsDirty) {
$hasPreUpdateListeners = $this->_evm->hasListeners(Events::preUpdate);
if (isset($class->lifecycleCallbacks[Events::preUpdate])) {
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
if ( ! $hasPreUpdateListeners) {
// Need to recompute entity changeset to detect changes made in the callback.
$this->recomputeSingleEntityChangeSet($class, $entity);
}
}
if ($hasPreUpdateListeners) {
$this->_evm->dispatchEvent(Events::preUpdate, new LifecycleEventArgs($entity, $this->_em));
// Need to recompute entity changeset to detect changes made in the listener.
$this->recomputeSingleEntityChangeSet($class, $entity);
}
$this->_entityUpdates[$oid] = $entity;
}
}
}
}
@ -576,7 +600,7 @@ class UnitOfWork implements PropertyChangedListener
$targetClass->invokeLifecycleCallbacks(Events::prePersist, $entry);
}
if ($this->_evm->hasListeners(Events::prePersist)) {
$this->_evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entry));
$this->_evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entry, $this->_em));
}
// Get identifier, if possible (not post-insert)
@ -595,15 +619,8 @@ class UnitOfWork implements PropertyChangedListener
// NEW entities are INSERTed within the current unit of work.
$this->_entityInsertions[$oid] = $entry;
$this->_computeEntityChanges($targetClass, $entry);
// Look for changes in associations of the entity
foreach ($targetClass->associationMappings as $assoc2) {
$val = $targetClass->reflFields[$assoc2->sourceFieldName]->getValue($entry);
if ($val !== null) {
$this->_computeAssociationChanges($assoc2, $val);
}
}
$this->computeChangeSet($targetClass, $entry);
} else if ($state == self::STATE_REMOVED) {
throw ORMException::removedEntityInCollectionDetected($entity, $assoc);
@ -627,7 +644,7 @@ class UnitOfWork implements PropertyChangedListener
* @param object $entity The entity for which to (re)calculate the change set.
* @throws InvalidArgumentException If the passed entity is not MANAGED.
*/
public function computeSingleEntityChangeSet($class, $entity)
public function recomputeSingleEntityChangeSet($class, $entity)
{
$oid = spl_object_hash($entity);
@ -718,7 +735,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::postPersist, $entity);
}
if ($hasListeners) {
$this->_evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($entity, $this->_em));
}
}
}
@ -734,26 +751,11 @@ class UnitOfWork implements PropertyChangedListener
$className = $class->name;
$persister = $this->getEntityPersister($className);
$hasPreUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::preUpdate]);
$hasPreUpdateListeners = $this->_evm->hasListeners(Events::preUpdate);
$hasPostUpdateLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postUpdate]);
$hasPostUpdateListeners = $this->_evm->hasListeners(Events::postUpdate);
foreach ($this->_entityUpdates as $oid => $entity) {
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
if ($hasPreUpdateLifecycleCallbacks) {
$class->invokeLifecycleCallbacks(Events::preUpdate, $entity);
if ( ! $hasPreUpdateListeners) {
// Need to recompute entity changeset to detect changes made in the callback.
$this->computeSingleEntityChangeSet($class, $entity);
}
}
if ($hasPreUpdateListeners) {
$this->_evm->dispatchEvent(Events::preUpdate, new LifecycleEventArgs($entity));
// Need to recompute entity changeset to detect changes made in the listener.
$this->computeSingleEntityChangeSet($class, $entity);
}
if (get_class($entity) == $className || $entity instanceof Proxy && $entity instanceof $className) {
$persister->update($entity);
unset($this->_entityUpdates[$oid]);
@ -761,7 +763,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::postUpdate, $entity);
}
if ($hasPostUpdateListeners) {
$this->_evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::postUpdate, new LifecycleEventArgs($entity, $this->_em));
}
}
}
@ -796,7 +798,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::postRemove, $entity);
}
if ($hasListeners) {
$this->_evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::postRemove, new LifecycleEventArgs($entity, $this->_em));
}
}
}
@ -1198,7 +1200,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::prePersist, $entity);
}
if ($this->_evm->hasListeners(Events::prePersist)) {
$this->_evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($entity, $this->_em));
}
$idGen = $class->idGenerator;
@ -1276,7 +1278,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::preRemove, $entity);
}
if ($this->_evm->hasListeners(Events::preRemove)) {
$this->_evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::preRemove, new LifecycleEventArgs($entity, $this->_em));
}
$this->scheduleForDelete($entity);
break;
@ -1835,7 +1837,7 @@ class UnitOfWork implements PropertyChangedListener
$class->invokeLifecycleCallbacks(Events::postLoad, $entity);
}
if ($this->_evm->hasListeners(Events::postLoad)) {
$this->_evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity));
$this->_evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity, $this->_em));
}
return $entity;