Skip to content

Commit

Permalink
add failing test
Browse files Browse the repository at this point in the history
possible fix for issue doctrine#659

fix cs
  • Loading branch information
uwej711 committed Nov 2, 2015
1 parent 320c840 commit 902aa89
Show file tree
Hide file tree
Showing 2 changed files with 236 additions and 72 deletions.
146 changes: 74 additions & 72 deletions lib/Doctrine/ODM/PHPCR/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -1420,7 +1420,7 @@ private function computeChildrenChanges($document, $class, $oid, $isNew, $change
* @param ClassMetadata $class
* @param object $document
*/
public function computeChangeSet(ClassMetadata $class, $document)
public function computeChangeSet(ClassMetadata $class, $document, $fieldsOnly = false)
{
if ($document instanceof Proxy && !$document->__isInitialized()) {
return;
Expand All @@ -1446,7 +1446,7 @@ public function computeChangeSet(ClassMetadata $class, $document)
}
}

if ($class->parentMapping && isset($changeSet[$class->parentMapping])) {
if (!$fieldsOnly && $class->parentMapping && isset($changeSet[$class->parentMapping])) {
$parent = $changeSet[$class->parentMapping];
$parentClass = $this->dm->getClassMetadata(get_class($parent));
$state = $this->getDocumentState($parent);
Expand All @@ -1456,90 +1456,92 @@ public function computeChangeSet(ClassMetadata $class, $document)
}
}

foreach ($class->childMappings as $fieldName) {
if ($changeSet[$fieldName]) {
if (is_array($changeSet[$fieldName]) || $changeSet[$fieldName] instanceof Collection) {
throw PHPCRException::childFieldIsArray(
self::objToStr($document, $this->dm),
$fieldName
);
}
if (!$fieldsOnly) {
foreach ($class->childMappings as $fieldName) {
if ($changeSet[$fieldName]) {
if (is_array($changeSet[$fieldName]) || $changeSet[$fieldName] instanceof Collection) {
throw PHPCRException::childFieldIsArray(
self::objToStr($document, $this->dm),
$fieldName
);
}

if (!is_object($changeSet[$fieldName])) {
throw PHPCRException::childFieldNoObject(
self::objToStr($document, $this->dm),
$fieldName,
gettype($changeSet[$fieldName])
);
}
if (!is_object($changeSet[$fieldName])) {
throw PHPCRException::childFieldNoObject(
self::objToStr($document, $this->dm),
$fieldName,
gettype($changeSet[$fieldName])
);
}

$mapping = $class->mappings[$fieldName];
$changeSet[$fieldName] = $this->computeChildChanges($mapping, $changeSet[$fieldName], $id, $mapping['nodeName']);
$mapping = $class->mappings[$fieldName];
$changeSet[$fieldName] = $this->computeChildChanges($mapping, $changeSet[$fieldName], $id, $mapping['nodeName']);
}
}
}

$this->computeAssociationChanges($document, $class, $oid, $isNew, $changeSet, 'reference');
$this->computeAssociationChanges($document, $class, $oid, $isNew, $changeSet, 'referrer');
$this->computeAssociationChanges($document, $class, $oid, $isNew, $changeSet, 'reference');
$this->computeAssociationChanges($document, $class, $oid, $isNew, $changeSet, 'referrer');

foreach ($class->mixedReferrersMappings as $fieldName) {
if ($changeSet[$fieldName]
&& $changeSet[$fieldName] instanceof PersistentCollection
&& $changeSet[$fieldName]->isDirty()
) {
throw new PHPCRException("The immutable mixed referrer collection in field $fieldName is dirty");
foreach ($class->mixedReferrersMappings as $fieldName) {
if ($changeSet[$fieldName]
&& $changeSet[$fieldName] instanceof PersistentCollection
&& $changeSet[$fieldName]->isDirty()
) {
throw new PHPCRException("The immutable mixed referrer collection in field $fieldName is dirty");
}
}
}

$this->computeChildrenChanges($document, $class, $oid, $isNew, $changeSet);

if (!$isNew) {
// collect assignment move operations
$destPath = $destName = false;

if (isset($this->originalData[$oid][$class->parentMapping])
&& isset($changeSet[$class->parentMapping])
&& $this->originalData[$oid][$class->parentMapping] !== $changeSet[$class->parentMapping]
) {
$destPath = $this->getDocumentId($changeSet[$class->parentMapping]);
}
$this->computeChildrenChanges($document, $class, $oid, $isNew, $changeSet);

if (isset($this->originalData[$oid][$class->nodename])
&& isset($changeSet[$class->nodename])
&& $this->originalData[$oid][$class->nodename] !== $changeSet[$class->nodename]
) {
$destName = $changeSet[$class->nodename];
}
if (!$isNew) {
// collect assignment move operations
$destPath = $destName = false;

// there was assignment move
if ($destPath || $destName) {
// add the other field if only one was changed
if (false === $destPath) {
$destPath = isset($changeSet[$class->parentMapping])
? $this->getDocumentId($changeSet[$class->parentMapping])
: PathHelper::getParentPath($this->getDocumentId($document));
}
if (false === $destName) {
$destName = $class->nodename !== null && $changeSet[$class->nodename]
? $changeSet[$class->nodename]
: PathHelper::getNodeName($this->getDocumentId($document));
if (isset($this->originalData[$oid][$class->parentMapping])
&& isset($changeSet[$class->parentMapping])
&& $this->originalData[$oid][$class->parentMapping] !== $changeSet[$class->parentMapping]
) {
$destPath = $this->getDocumentId($changeSet[$class->parentMapping]);
}

// make sure destination nodename is okay
if ($exception = $class->isValidNodename($destName)) {
throw IdException::illegalName($document, $class->nodename, $destName);
if (isset($this->originalData[$oid][$class->nodename])
&& isset($changeSet[$class->nodename])
&& $this->originalData[$oid][$class->nodename] !== $changeSet[$class->nodename]
) {
$destName = $changeSet[$class->nodename];
}

// prevent path from becoming "//foobar" when moving to root node.
$targetPath = ('/' == $destPath) ? "/$destName" : "$destPath/$destName";
// there was assignment move
if ($destPath || $destName) {
// add the other field if only one was changed
if (false === $destPath) {
$destPath = isset($changeSet[$class->parentMapping])
? $this->getDocumentId($changeSet[$class->parentMapping])
: PathHelper::getParentPath($this->getDocumentId($document));
}
if (false === $destName) {
$destName = $class->nodename !== null && $changeSet[$class->nodename]
? $changeSet[$class->nodename]
: PathHelper::getNodeName($this->getDocumentId($document));
}

$this->scheduleMove($document, $targetPath);
}
// make sure destination nodename is okay
if ($exception = $class->isValidNodename($destName)) {
throw IdException::illegalName($document, $class->nodename, $destName);
}

if (isset($this->originalData[$oid][$class->identifier])
&& isset($changeSet[$class->identifier])
&& $this->originalData[$oid][$class->identifier] !== $changeSet[$class->identifier]
) {
throw new PHPCRException('The Id is immutable ('.$this->originalData[$oid][$class->identifier].' !== '.$changeSet[$class->identifier].'). Please use DocumentManager::move to move the document: '.self::objToStr($document, $this->dm));
// prevent path from becoming "//foobar" when moving to root node.
$targetPath = ('/' == $destPath) ? "/$destName" : "$destPath/$destName";

$this->scheduleMove($document, $targetPath);
}

if (isset($this->originalData[$oid][$class->identifier])
&& isset($changeSet[$class->identifier])
&& $this->originalData[$oid][$class->identifier] !== $changeSet[$class->identifier]
) {
throw new PHPCRException('The Id is immutable ('.$this->originalData[$oid][$class->identifier].' !== '.$changeSet[$class->identifier].'). Please use DocumentManager::move to move the document: '.self::objToStr($document, $this->dm));
}
}
}

Expand Down Expand Up @@ -2458,7 +2460,7 @@ private function executeUpdates($documents, $dispatchEvents = true)
$invoke
);
$this->changesetComputed = array_diff($this->changesetComputed, array($oid));
$this->computeChangeSet($class, $document);
$this->computeChangeSet($class, $document, true);
}
}

Expand Down
162 changes: 162 additions & 0 deletions tests/Doctrine/Tests/ODM/PHPCR/Functional/RenameChildTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<?php

namespace Doctrine\Tests\ODM\PHPCR\Functional;

use Doctrine\ODM\PHPCR\Mapping\Annotations as PHPCRODM;
use Doctrine\ODM\PHPCR\Translation\LocaleChooser\LocaleChooser;
use Doctrine\Tests\Models\Translation\Article;
use PHPCR\PropertyType;
use Doctrine\Tests\Models\CMS\CmsTeamUser;

/**
* @group functional
*/
class RenameChildTest extends \Doctrine\Tests\ODM\PHPCR\PHPCRFunctionalTestCase
{
/**
* @var \Doctrine\ODM\PHPCR\DocumentManager
*/
private $dm;

private $type;

private $node;

public function setUp()
{
$this->dm = $this->createDocumentManager(array(__DIR__));
$this->node = $this->resetFunctionalNode($this->dm);

$parent = new RCTParent();
$parent->id = '/functional/parent';
$parent->title = 'Test';

$child = new RCTChild();
$child->parent = $parent;
$child->nodename = 'test';
$child->title = 'Testchild';

$this->dm->persist($parent);
$this->dm->persist($child);

$this->dm->flush();
}

public function testRenameWithOneChild()
{
$this->dm->clear();

$parent = $this->dm->find(null, '/functional/parent');
foreach ($parent->children as $name => $child) {
// just make sure the children collection is initialized
}

$child = $this->dm->find(null, '/functional/parent/test');
$this->assertEquals('test', $child->nodename);

$child->nodename = 'renamed';
$this->dm->flush();

$renamed = $this->dm->find(null, '/functional/parent/renamed');

$this->assertNotNull($renamed);
$this->assertEquals('Testchild', $renamed->title);
}

public function testRenameWithParentChange()
{
$this->dm->clear();

$parent = $this->dm->find(null, '/functional/parent');
foreach ($parent->children as $name => $child) {
// just make sure the children collection is initialized
}

$child = $this->dm->find(null, '/functional/parent/test');
$this->assertEquals('test', $child->nodename);

$child->nodename = 'renamed';
$parent->title = 'Changed Test';

$this->dm->flush();

$renamed = $this->dm->find(null, '/functional/parent/renamed');

$this->assertNotNull($renamed);
$this->assertEquals('Testchild', $renamed->title);
$this->assertEquals('Changed Test', $renamed->parent->title);
}

public function testRenameWithTwoChildren()
{
$this->dm->clear();

$parent = $this->dm->find(null, '/functional/parent');
$secondChild = new RCTChild();

$secondChild->parent = $parent;
$secondChild->nodename = 'test2';

$secondChild->title = 'Testchild 2';

$this->dm->persist($secondChild);
$this->dm->flush();

$this->dm->clear();

$parent = $this->dm->find(null, '/functional/parent');
foreach ($parent->children as $name => $child) {
// just make sure the children collection is initialized
}

$child = $this->dm->find(null, '/functional/parent/test');
$this->assertEquals('test', $child->nodename);

$child->nodename = 'renamed';
$this->dm->flush();

$renamed = $this->dm->find(null, '/functional/parent/renamed');

$this->assertNotNull($renamed);
$this->assertEquals('Testchild', $renamed->title);
}
}

/**
* @PHPCRODM\Document()
*/
class RCTParent
{
/** @PHPCRODM\Id */
public $id;

/** @PHPCRODM\Field(type="string") */
public $title;

/** @PHPCRODM\Children */
public $children;

/** @PHPCRODM\PreUpdate */
public function preUpdate()
{
// NOOP
}
}

/**
* @PHPCRODM\Document()
*/
class RCTChild
{
/** @PHPCRODM\Id */
public $id;

/** @PHPCRODM\ParentDocument */
public $parent;

/** @PHPCRODM\Nodename */
public $nodename;

/** @PHPCRODM\Field(type="string") */
public $title;
}

0 comments on commit 902aa89

Please sign in to comment.