Skip to content

Commit

Permalink
Updated tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
romanb committed Jul 30, 2010
1 parent e69c7c7 commit 954a8c3
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 58 deletions.
78 changes: 49 additions & 29 deletions lib/Doctrine/ORM/UnitOfWork.php
Expand Up @@ -1344,34 +1344,51 @@ public function merge($entity)
*/
private function doMerge($entity, array &$visited, $prevManagedCopy = null, $assoc = null)
{
$class = $this->em->getClassMetadata(get_class($entity));
$id = $class->getIdentifierValues($entity);

if ( ! $id) {
throw new InvalidArgumentException('New entity detected during merge.'
. ' Persist the new entity before merging.');
$oid = spl_object_hash($entity);
if (isset($visited[$oid])) {
return; // Prevent infinite recursion
}

// MANAGED entities are ignored by the merge operation
$class = $this->em->getClassMetadata(get_class($entity));

// First we assume DETACHED, although it can still be NEW but we can avoid
// an extra db-roundtrip this way. If it is DETACHED or NEW, we need to fetch
// it from the db anyway in order to merge.
// MANAGED entities are ignored by the merge operation.
if ($this->getEntityState($entity, self::STATE_DETACHED) == self::STATE_MANAGED) {
$managedCopy = $entity;
} else {
// Try to look the entity up in the identity map.
$managedCopy = $this->tryGetById($id, $class->rootEntityName);
if ($managedCopy) {
// We have the entity in-memory already, just make sure its not removed.
if ($this->getEntityState($managedCopy) == self::STATE_REMOVED) {
throw new InvalidArgumentException('Removed entity detected during merge.'
. ' Can not merge with a removed entity.');
}
$id = $class->getIdentifierValues($entity);

// If there is no ID, it is actually NEW.
if ( ! $id) {
$managedCopy = $class->newInstance();
$this->persistNew($class, $managedCopy);
} else {
// We need to fetch the managed copy in order to merge.
$managedCopy = $this->em->find($class->name, $id);
}
$managedCopy = $this->tryGetById($id, $class->rootEntityName);
if ($managedCopy) {
// We have the entity in-memory already, just make sure its not removed.
if ($this->getEntityState($managedCopy) == self::STATE_REMOVED) {
throw new InvalidArgumentException('Removed entity detected during merge.'
. ' Can not merge with a removed entity.');
}
} else {
// We need to fetch the managed copy in order to merge.
$managedCopy = $this->em->find($class->name, $id);
}

if ($managedCopy === null) {
throw new InvalidArgumentException('New entity detected during merge.'
. ' Persist the new entity before merging.');
if ($managedCopy === null) {
// If the identifier is ASSIGNED, it is NEW, otherwise an error
// since the managed entity was not found.
if ($class->isIdentifierNatural()) {
$managedCopy = $class->newInstance();
$class->setIdentifierValues($managedCopy, $id);
$this->persistNew($class, $managedCopy);
} else {
throw new EntityNotFoundException;
}
}
}

if ($class->isVersioned) {
Expand All @@ -1388,17 +1405,20 @@ private function doMerge($entity, array &$visited, $prevManagedCopy = null, $ass
if ( ! isset($class->associationMappings[$name])) {
$prop->setValue($managedCopy, $prop->getValue($entity));
} else {
// why $assoc2? See the method signature, there is $assoc already!
$assoc2 = $class->associationMappings[$name];
if ($assoc2->isOneToOne()) {
if ( ! $assoc2->isCascadeMerge) {
$other = $class->reflFields[$name]->getValue($entity); //TODO: Just $prop->getValue($entity)?
$other = $prop->getValue($entity);
if ($other !== null) {
$targetClass = $this->em->getClassMetadata($assoc2->targetEntityName);
$id = $targetClass->getIdentifierValues($other);
$proxy = $this->em->getProxyFactory()->getProxy($assoc2->targetEntityName, $id);
$prop->setValue($managedCopy, $proxy);
$this->registerManaged($proxy, $id, array());
if ($this->getEntityState($other, self::STATE_DETACHED) == self::STATE_MANAGED) {
$prop->setValue($managedCopy, $other);
} else {
$targetClass = $this->em->getClassMetadata($assoc2->targetEntityName);
$id = $targetClass->getIdentifierValues($other);
$proxy = $this->em->getProxyFactory()->getProxy($assoc2->targetEntityName, $id);
$prop->setValue($managedCopy, $proxy);
$this->registerManaged($proxy, $id, array());
}
}
}
} else {
Expand All @@ -1421,8 +1441,8 @@ private function doMerge($entity, array &$visited, $prevManagedCopy = null, $ass
//TODO: put changed fields in changeset...?
}
}
if ($class->isChangeTrackingDeferredExplicit()) {
//TODO: Mark $managedCopy for dirty check...? ($this->scheduledForDirtyCheck)
if ( ! $class->isChangeTrackingDeferredImplicit()) {
$this->scheduleForDirtyCheck($entity);
}
}

Expand Down
60 changes: 31 additions & 29 deletions tests/Doctrine/Tests/ORM/Functional/BasicFunctionalTest.php
Expand Up @@ -768,37 +768,39 @@ public function testGetPartialReferenceToUpdateObjectWithoutLoadingIt()

$this->assertEquals('Stephan', $this->_em->find(get_class($user), $userId)->name);
}

//DRAFT OF EXPECTED/DESIRED BEHAVIOR
/*public function testPersistentCollectionContainsDoesNeverInitialize()

public function testMergePersistsNewEntities()
{
$user = new CmsUser;
$user->name = 'Guilherme';
$user->username = 'gblanco';
$user->status = 'developer';
$group = new CmsGroup;
$group->name = 'Developers';
$user->addGroup($group);
$this->_em->persist($user);
$user = new CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin E.";
$user->status = 'active';

$managedUser = $this->_em->merge($user);
$this->assertEquals('beberlei', $managedUser->username);
$this->assertEquals('Benjamin E.', $managedUser->name);
$this->assertEquals('active', $managedUser->status);

$this->assertTrue($user !== $managedUser);
$this->assertTrue($this->_em->contains($managedUser));

$this->_em->flush();
$userId = $managedUser->id;
$this->_em->clear();
$group = $this->_em->find(get_class($group), $group->getId());
$user2 = new CmsUser;
$user2->id = $user->getId();
$this->assertFalse($group->getUsers()->contains($user2));
$this->assertFalse($group->getUsers()->isInitialized());
$user2 = $this->_em->getReference(get_class($user), $user->getId());
$this->assertTrue($group->getUsers()->contains($user2));
$this->assertFalse($group->getUsers()->isInitialized());

$this->assertTrue($this->_em->find(get_class($managedUser), $userId) instanceof CmsUser);
}

public function testMergeThrowsExceptionIfEntityWithGeneratedIdentifierDoesNotExist()
{
$user = new CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin E.";
$user->status = 'active';
$user->id = 42;
try {
$this->_em->merge($user);
$this->fail();
} catch (\Doctrine\ORM\EntityNotFoundException $enfe) {}
}
*/
}
36 changes: 36 additions & 0 deletions tests/Doctrine/Tests/ORM/Functional/Ticket/DDC518Test.php
@@ -0,0 +1,36 @@
<?php
namespace Doctrine\Tests\ORM\Functional\Ticket;

require_once __DIR__ . '/../../../TestInit.php';

class DDC518Test extends \Doctrine\Tests\OrmFunctionalTestCase
{
public function setUp()
{
$this->useModelSet('cms');
parent::setUp();
}

public function testMergeWithRelatedNew()
{
$article = new \Doctrine\Tests\Models\CMS\CmsArticle();
$article->text = "foo";
$article->topic = "bar";

$this->_em->persist($article);
$this->_em->flush();
$this->_em->detach($article);
$this->_em->clear();

$user = new \Doctrine\Tests\Models\CMS\CmsUser();
$user->username = "beberlei";
$user->name = "Benjamin Eberlei";
$user->status = "active";
$article->user = $user;

$this->_em->persist($user);
$managedArticle = $this->_em->merge($article);

$this->assertSame($article->user, $managedArticle->user);
}
}

0 comments on commit 954a8c3

Please sign in to comment.