private function computeChildrenChanges($document, $class, $oid, $isNew, $changeSet)
{
$id = $this->getDocumentId($document, false);
foreach ($class->childrenMappings as $fieldName) {
if ($changeSet[$fieldName] instanceof PersistentCollection) {
if (!$changeSet[$fieldName]->isInitialized()) {
continue;
}
} else {
if (null === $changeSet[$fieldName]) {
$changeSet[$fieldName] = array();
}
if (!is_array($changeSet[$fieldName]) && !$changeSet[$fieldName] instanceof Collection) {
throw PHPCRException::childrenFieldNoArray(self::objToStr($document, $this->dm), $fieldName);
}
$filter = isset($mapping['filter']) ? $mapping['filter'] : null;
$fetchDepth = isset($mapping['fetchDepth']) ? $mapping['fetchDepth'] : null;
// convert to a PersistentCollection
$changeSet[$fieldName] = ChildrenCollection::createFromCollection($this->dm, $document, $changeSet[$fieldName], $filter, $fetchDepth, !$isNew);
$class->setFieldValue($document, $fieldName, $changeSet[$fieldName]);
$this->originalData[$oid][$fieldName] = $changeSet[$fieldName];
}
$mapping = $class->mappings[$fieldName];
$childNames = $movedChildNames = array();
$coid = spl_object_hash($changeSet[$fieldName]);
$this->visitedCollections[$coid] = $changeSet[$fieldName];
foreach ($changeSet[$fieldName] as $originalNodename => $child) {
if (!is_object($child)) {
throw PHPCRException::childrenContainsNonObject(self::objToStr($document, $this->dm), $fieldName, gettype($child));
}
$nodename = $this->getChildNodename($id, $originalNodename, $child, $document);
$changeSet[$fieldName][$nodename] = $this->computeChildChanges($mapping, $child, $id, $nodename, $document);
if (0 !== strcmp($originalNodename, $nodename)) {
unset($changeSet[$fieldName][$originalNodename]);
$movedChildNames[] = (string) $originalNodename;
}
$childNames[] = $nodename;
}
if ($isNew) {
continue;
}
if (!$this->originalData[$oid][$fieldName] instanceof ChildrenCollection) {
throw new RuntimeException("OriginalData for a children association contains something else than a ChildrenCollection.");
}
$this->originalData[$oid][$fieldName]->initialize();
$originalNames = $this->originalData[$oid][$fieldName]->getOriginalNodenames();
foreach ($originalNames as $key => $childName) {
// check moved children to not accidentally remove a child that simply moved away.
if (!(in_array($childName, $childNames) || in_array($childName, $movedChildNames))) {
$child = $this->getDocumentById($id . '/' . $childName);
$this->scheduleRemove($child);
unset($originalNames[$key]);
}
}
if (!empty($childNames) && isset($originalNames)) {
// reindex the arrays to avoid holes in the indexes
$originalNames = array_values($originalNames);
$originalNames = array_merge($originalNames, array_diff($childNames, $originalNames));
if ($originalNames !== $childNames) {
$reordering = NodeHelper::calculateOrderBefore($originalNames, $childNames);
if (empty($this->documentChangesets[$oid])) {
$this->documentChangesets[$oid] = array('reorderings' => array($reordering));
} else {
$this->documentChangesets[$oid]['reorderings'][] = $reordering;
}
$this->scheduledUpdates[$oid] = $document;
} elseif (empty($this->documentChangesets[$oid]['fields'])) {
unset($this->documentChangesets[$oid]);
unset($this->scheduledUpdates[$oid]);
} else {
$this->documentChangesets[$oid]['reorderings'] = array();
}
}
}
}