Skip to content
Browse files

[PHPCR-98] allow replacing child documents via automatic merge()

  • Loading branch information...
1 parent e8b7619 commit 2d1bd507d1a7a6702050c1033e2191aaa1afd2c0 @lsmith77 lsmith77 committed Feb 25, 2013
Showing with 37 additions and 22 deletions.
  1. +22 −20 lib/Doctrine/ODM/PHPCR/UnitOfWork.php
  2. +15 −2 tests/Doctrine/Tests/ODM/PHPCR/Functional/ChildTest.php
View
42 lib/Doctrine/ODM/PHPCR/UnitOfWork.php
@@ -952,7 +952,7 @@ private function computeChangeSet(ClassMetadata $class, $document)
if ($actualData[$fieldName]) {
foreach ($actualData[$fieldName] as $nodename => $child) {
$nodename = $this->getChildNodename($id, $nodename, $child);
- $this->computeChildChanges($mapping, $child, $id, $nodename, $document);
+ $actualData[$fieldName][$nodename] = $this->computeChildChanges($mapping, $child, $id, $nodename, $document);
$childNames[] = $nodename;
}
}
@@ -971,11 +971,8 @@ private function computeChangeSet(ClassMetadata $class, $document)
foreach ($class->childMappings as $fieldName) {
if ($actualData[$fieldName]) {
- if ($this->originalData[$oid][$fieldName] && $this->originalData[$oid][$fieldName] !== $actualData[$fieldName]) {
- throw PHPCRException::cannotMoveByAssignment(self::objToStr($actualData[$fieldName], $this->dm));
- }
$mapping = $class->mappings[$fieldName];
- $this->computeChildChanges($mapping, $actualData[$fieldName], $id);
+ $actualData[$fieldName] = $this->computeChildChanges($mapping, $actualData[$fieldName], $id, $mapping['name']);
}
}
@@ -1070,7 +1067,7 @@ private function computeChangeSet(ClassMetadata $class, $document)
if ($actualData[$fieldName]) {
foreach ($actualData[$fieldName] as $nodename => $child) {
$nodename = $this->getChildNodename($id, $nodename, $child);
- $this->computeChildChanges($mapping, $child, $id, $nodename, $document);
+ $actualData[$fieldName][$nodename] = $this->computeChildChanges($mapping, $child, $id, $nodename, $document);
$childNames[] = $nodename;
}
}
@@ -1164,8 +1161,10 @@ private function computeChangeSet(ClassMetadata $class, $document)
* @param string $parentId
* @param string $nodename
* @param mixed $parent
+ *
+ * @return object the child instance (if we are replacing a child this can be a different instance than was originally provided)
*/
- private function computeChildChanges($mapping, $child, $parentId, $nodename = null, $parent = null)
+ private function computeChildChanges($mapping, $child, $parentId, $nodename, $parent = null)
{
$targetClass = $this->dm->getClassMetadata(get_class($child));
$state = $this->getDocumentState($child);
@@ -1175,16 +1174,23 @@ private function computeChildChanges($mapping, $child, $parentId, $nodename = nu
if (!($mapping['cascade'] & ClassMetadata::CASCADE_PERSIST) ) {
throw CascadeException::newDocumentFound(self::objToStr($child));
}
- $nodename = $nodename ?: $mapping['name'];
- if ($nodename) {
- $targetClass->setIdentifierValue($child, $parentId.'/'.$nodename);
+
+ $childId = $parentId.'/'.$nodename;
+ $targetClass->setIdentifierValue($child, $childId);
+
+ if ($this->getDocumentById($childId)) {
+ $child = $this->merge($child);
+ } else {
+ $this->persistNew($targetClass, $child, ClassMetadata::GENERATOR_TYPE_ASSIGNED, $parent);
}
- $this->persistNew($targetClass, $child, ClassMetadata::GENERATOR_TYPE_ASSIGNED, $parent);
+
$this->computeChangeSet($targetClass, $child);
break;
case self::STATE_DETACHED:
throw new \InvalidArgumentException('A detached document was found through a child relationship during cascading a persist operation: '.self::objToStr($child, $this->dm));
}
+
+ return $child;
}
/**
@@ -1953,15 +1959,11 @@ private function executeUpdates($documents, $dispatchEvents = true)
}
}
} elseif ('child' === $mapping['type']) {
- if ($fieldValue === null) {
- if ($node->hasNode($mapping['name'])) {
- $child = $node->getNode($mapping['name']);
- $childDocument = $this->getOrCreateDocument(null, $child);
- $this->purgeChildren($childDocument);
- $child->remove();
- }
- } elseif ($this->originalData[$oid][$fieldName] && $this->originalData[$oid][$fieldName] !== $fieldValue) {
- throw PHPCRException::cannotMoveByAssignment(self::objToStr($fieldValue, $this->dm));
+ if ($fieldValue === null && $node->hasNode($mapping['name'])) {
+ $child = $node->getNode($mapping['name']);
+ $childDocument = $this->getOrCreateDocument(null, $child);
+ $this->purgeChildren($childDocument);
+ $child->remove();
}
}
}
View
17 tests/Doctrine/Tests/ODM/PHPCR/Functional/ChildTest.php
@@ -225,7 +225,6 @@ public function testChildSetNull()
$this->assertNull($parent->child);
}
- /* this fails as the newChild is not persisted */
public function testChildReplace()
{
$parent = new ChildTestObj();
@@ -244,9 +243,21 @@ public function testChildReplace()
$newChild->name = 'new name';
$parent->child = $newChild;
- $this->setExpectedException('Doctrine\ODM\PHPCR\PHPCRException');
+ $this->dm->flush();
+ $this->dm->clear();
+
+ $parent = $this->dm->find($this->type, '/functional/childtest');
+ $this->assertEquals('new name', $parent->child->name);
+
+ $newerChild = new ChildChildTestObj();
+ $newerChild->name = 'newer name';
+ $parent->children['test2'] = $newerChild;
$this->dm->flush();
+ $this->dm->clear();
+
+ $parent = $this->dm->find($this->type, '/functional/childtest');
+ $this->assertEquals('newer name', $parent->children['test2']->name);
}
public function testModificationAfterPersist()
@@ -331,6 +342,8 @@ class ChildTestObj
public $name;
/** @PHPCRODM\Child(name="test", cascade="persist") */
public $child;
+ /** @PHPCRODM\Children(cascade="persist") */
+ public $children;
}
/**

0 comments on commit 2d1bd50

Please sign in to comment.
Something went wrong with that request. Please try again.