Commit a1a80938 authored by romanb's avatar romanb

[2.0] First draft for onFlush event.

parent 7badced1
......@@ -72,7 +72,7 @@ class AnnotationReader
$this->_parser = new Parser;
$this->_cache = $cache ?: new Doctrine\Common\Cache\ArrayCache;
}
/**
* Sets the default namespace that the AnnotationReader should assume for annotations
* with not fully qualified names.
......@@ -83,7 +83,7 @@ class AnnotationReader
{
$this->_parser->setDefaultAnnotationNamespace($defaultNamespace);
}
/**
* Sets an alias for an annotation namespace.
*
......@@ -94,7 +94,7 @@ class AnnotationReader
{
$this->_parser->setAnnotationNamespaceAlias($namespace, $alias);
}
/**
* Gets the annotations applied to a class.
*
......
......@@ -249,7 +249,7 @@ class Parser
$name = implode('\\', $nameParts);
}
// If it really an annotation class?
// Is it really an annotation class?
if (
(! $this->_isNestedAnnotation && $this->_lexer->lookahead != null &&
! $this->_lexer->isNextToken(Lexer::T_OPEN_PARENTHESIS) &&
......
......@@ -22,7 +22,8 @@
namespace Doctrine\ORM\Event;
/**
* Lifecycle Events are triggered by the UnitOfWork
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
* of entities.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
......
<?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;
/**
* Provides event arguments for the preFlush event.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OnFlushEventArgs extends \Doctrine\Common\EventArgs
{
/**
* @var EntityManager
*/
private $_em;
//private $_entitiesToPersist = array();
//private $_entitiesToRemove = array();
public function __construct($em)
{
$this->_em = $em;
}
/**
* @return EntityManager
*/
public function getEntityManager()
{
return $this->_em;
}
/*
public function addEntityToPersist($entity)
{
}
public function addEntityToRemove($entity)
{
}
public function addEntityToUpdate($entity)
{
}
public function getEntitiesToPersist()
{
return $this->_entitiesToPersist;
}
*/
}
\ No newline at end of file
......@@ -108,4 +108,15 @@ final class Events
* @var string
*/
const loadClassMetadata = 'loadClassMetadata';
/**
* The onFlush event occurs when the EntityManager#flush() operation is invoked,
* after any changes to managed entities have been determined but before any
* actual database operations are executed. The event is only raised if there is
* actually something to do for the underlying UnitOfWork. If nothing needs to be done,
* the onFlush event is not raised.
*
* @var string
*/
const onFlush = 'onFlush';
}
\ No newline at end of file
......@@ -339,10 +339,10 @@ class StandardEntityPersister
if (isset($this->_class->associationMappings[$field])) {
$assocMapping = $this->_class->associationMappings[$field];
// Only owning side of x-1 associations can have a FK column.
if ( ! $assocMapping->isOneToOne() || ! $assocMapping->isOwningSide) {
if ( ! $assocMapping->isOwningSide || ! $assocMapping->isOneToOne()) {
continue;
}
if ($newVal !== null) {
$oid = spl_object_hash($newVal);
if (isset($this->_queuedInserts[$oid]) || $uow->isScheduledForInsert($newVal)) {
......
......@@ -271,6 +271,11 @@ class UnitOfWork implements PropertyChangedListener
}
}
// Raise onFlush
if ($this->_evm->hasListeners(Events::onFlush)) {
$this->_evm->dispatchEvent(Events::onFlush, new Event\OnFlushEventArgs($this->_em));
}
// Now we need a commit order to maintain referential integrity
$commitOrder = $this->_getCommitOrder();
......@@ -945,7 +950,8 @@ class UnitOfWork implements PropertyChangedListener
}
/**
* Registers a deleted entity.
* INTERNAL:
* Schedules an entity for deletion.
*
* @param object $entity
*/
......@@ -2064,4 +2070,34 @@ class UnitOfWork implements PropertyChangedListener
$this->_entityUpdates[$oid] = $entity;
}
}
/**
* Gets the currently scheduled entity insertions in this UnitOfWork.
*
* @return array
*/
public function getScheduledEntityInsertions()
{
return $this->_entityInsertions;
}
/**
* Gets the currently scheduled entity updates in this UnitOfWork.
*
* @return array
*/
public function getScheduledEntityUpdates()
{
return $this->_entityUpdates;
}
/**
* Gets the currently scheduled entity deletions in this UnitOfWork.
*
* @return array
*/
public function getScheduledEntityDeletions()
{
return $this->_entityDeletions;
}
}
......@@ -106,7 +106,7 @@ DOCBLOCK;
*/
public function testAnnotationNamespaceAlias()
{
$parser = new Parser;
$parser = $this->createTestParser();
$parser->setAnnotationNamespaceAlias('Doctrine\Tests\Common\Annotations\\', 'alias');
$docblock = <<<DOCBLOCK
/**
......
<?php
namespace Doctrine\Tests\ORM\Functional;
use Doctrine\Tests\Models\CMS\CmsUser;
use Doctrine\Tests\Models\CMS\CmsPhonenumber;
use Doctrine\ORM\Event\OnFlushEventArgs;
use Doctrine\ORM\Events;
require_once __DIR__ . '/../../TestInit.php';
/**
* FlushEventTest
*
* @author robo
*/
class FlushEventTest extends \Doctrine\Tests\OrmFunctionalTestCase
{
protected function setUp() {
$this->useModelSet('cms');
parent::setUp();
}
public function testPersistNewEntitiesOnPreFlush()
{
//$this->_em->getConnection()->getConfiguration()->setSqlLogger(new \Doctrine\DBAL\Logging\EchoSqlLogger);
$this->_em->getEventManager()->addEventListener(Events::onFlush, new OnFlushListener);
$user = new CmsUser;
$user->username = 'romanb';
$user->name = 'Roman';
$user->status = 'Dev';
$this->_em->persist($user);
$this->assertEquals(0, $user->phonenumbers->count());
$this->_em->flush();
$this->assertEquals(1, $user->phonenumbers->count());
$this->assertTrue($this->_em->contains($user->phonenumbers->get(0)));
$this->assertTrue($user->phonenumbers->get(0)->getUser() === $user);
$this->assertFalse($user->phonenumbers->isDirty());
// Can be used together with SQL Logging to check that a subsequent flush has
// nothing to do. This proofs the correctness of the changes that happened in onFlush.
//echo "SECOND FLUSH";
//$this->_em->flush();
}
}
class OnFlushListener
{
public function onFlush(OnFlushEventArgs $args)
{
//echo "---preFlush".PHP_EOL;
$em = $args->getEntityManager();
$uow = $em->getUnitOfWork();
foreach ($uow->getScheduledEntityInsertions() as $entity) {
if ($entity instanceof CmsUser) {
// Adds a phonenumber to every newly persisted CmsUser ...
$phone = new CmsPhonenumber;
$phone->phonenumber = 12345;
// Update object model
$entity->addPhonenumber($phone);
// Invoke regular persist call
$em->persist($phone);
// Explicitly calculate the changeset since onFlush is raised
// after changeset calculation!
$uow->computeChangeSet($em->getClassMetadata(get_class($phone)), $phone);
// Take a snapshot because the UoW wont do this for us, because
// the UoW did not visit this collection.
// Alternatively we could provide an ->addVisitedCollection() method
// on the UoW.
$entity->getPhonenumbers()->takeSnapshot();
}
/*foreach ($uow->getEntityChangeSet($entity) as $field => $change) {
list ($old, $new) = $change;
var_dump($old);
}*/
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment