private function doUpdate(ClassMetadataFactory $metadataFactory, PhpcrMetadata $odmMetadata, CtMetadata $ctMetadata, $document) { $documentId = $odmMetadata->getIdentifierValue($document); foreach ($odmMetadata->childrenMappings as $childrenField) { // if the children field is not managed by the CT component, // continue if (!isset($ctMetadata->propertyMetadata[$childrenField])) { continue; } $children = $odmMetadata->getFieldValue($document, $childrenField); // note that we do not preserve array keys. PHPCR ODM will return a // children collection using the PHPCR property names as keys, so // we currently have no control over how these keys populated. $index = 0; foreach ($children as $child) { $childMetadata = $metadataFactory->getMetadataFor(ClassUtils::getRealClass(get_class($child))); $newId = sprintf('%s/%s', $documentId, $this->encoder->encode($childrenField, $index++)); $childMetadata->setIdentifierValue($child, $newId); } } }
/** * @param ClassMetadata $class * @param object $document * @return void */ private function computeChangeSet(ClassMetadata $class, $document) { if ($document instanceof Proxy && !$document->__isInitialized()) { return; } $actualData = array(); foreach ($class->reflFields as $fieldName => $reflProperty) { $value = $reflProperty->getValue($document); if ($class->isCollectionValuedAssociation($fieldName) && $value !== null && !$value instanceof PersistentCollection) { if (!$value instanceof Collection) { $value = new MultivaluePropertyCollection(new ArrayCollection($value), true); $this->multivaluePropertyCollections[] = $value; } $collection = $value; $class->reflFields[$fieldName]->setValue($document, $collection); $actualData[$fieldName] = $collection; } else { $actualData[$fieldName] = $value; } } // unset the version info fields if they have values, they are not to be managed by the user in write scenarios. if ($class->versionable) { unset($actualData[$class->versionNameField]); unset($actualData[$class->versionCreatedField]); } $oid = spl_object_hash($document); if (!isset($this->originalData[$oid])) { // Document is New and should be inserted $this->originalData[$oid] = $actualData; $this->documentChangesets[$oid] = $actualData; $this->scheduledInserts[$oid] = $document; } else { if (isset($this->originalData[$oid][$class->nodename]) && isset($actualData[$class->nodename]) && $this->originalData[$oid][$class->nodename] !== $actualData[$class->nodename]) { throw new PHPCRException('The Nodename property is immutable (' . $this->originalData[$oid][$class->nodename] . ' !== ' . $actualData[$class->nodename] . '). Please use DocumentManager::move to rename the document: ' . self::objToStr($document, $this->dm)); } if (isset($this->originalData[$oid][$class->parentMapping]) && isset($actualData[$class->parentMapping]) && $this->originalData[$oid][$class->parentMapping] !== $actualData[$class->parentMapping]) { throw new PHPCRException('The ParentDocument property is immutable (' . $class->getIdentifierValue($this->originalData[$oid][$class->parentMapping]) . ' !== ' . $class->getIdentifierValue($actualData[$class->parentMapping]) . '). Please use PHPCR\\Session::move to move the document: ' . self::objToStr($document, $this->dm)); } if (isset($this->originalData[$oid][$class->identifier]) && isset($actualData[$class->identifier]) && $this->originalData[$oid][$class->identifier] !== $actualData[$class->identifier]) { throw new PHPCRException('The Id is immutable (' . $this->originalData[$oid][$class->identifier] . ' !== ' . $actualData[$class->identifier] . '). Please use DocumentManager::move to move the document: ' . self::objToStr($document, $this->dm)); } // Document is "fully" MANAGED: it was already fully persisted before // and we have a copy of the original data $changed = false; foreach ($actualData as $fieldName => $fieldValue) { if (!isset($class->fieldMappings[$fieldName]) && !isset($class->childMappings[$fieldName]) && !isset($class->associationsMappings[$fieldName]) && !isset($class->referrersMappings[$fieldName]) && !isset($class->parentMapping[$fieldName]) && !isset($class->nodename)) { continue; } if ($class->isCollectionValuedAssociation($fieldName)) { if (!$fieldValue instanceof PersistentCollection) { // if its not a persistent collection and the original value changed. otherwise it could just be null $changed = true; break; } elseif ($fieldValue->changed()) { $this->visitedCollections[] = $fieldValue; $changed = true; break; } } elseif ($this->originalData[$oid][$fieldName] !== $fieldValue) { $changed = true; break; } elseif ($fieldValue instanceof ReferenceManyCollection) { if ($fieldValue->changed()) { $changed = true; } } } if (isset($this->documentLocales[$oid]) && $this->documentLocales[$oid]['current'] !== $this->documentLocales[$oid]['original']) { $changed = true; } if ($changed) { $this->documentChangesets[$oid] = $actualData; $this->scheduledUpdates[$oid] = $document; } } if ($class->parentMapping && isset($actualData[$class->parentMapping])) { $parent = $actualData[$class->parentMapping]; $parentClass = $this->dm->getClassMetadata(get_class($parent)); $state = $this->getDocumentState($parent); if ($state === self::STATE_MANAGED) { $this->computeChangeSet($parentClass, $parent); } } $id = $class->getIdentifierValue($document); foreach ($class->childMappings as $name => $childMapping) { if ($actualData[$name]) { if ($this->originalData[$oid][$name] && $this->originalData[$oid][$name] !== $actualData[$name]) { throw new PHPCRException('Cannot move/copy children by assignment as it would be ambiguous. Please use the DocumentManager::move() or PHPCR\\Session::copy() operations for this: ' . self::objToStr($document, $this->dm)); } $this->computeChildChanges($childMapping, $actualData[$name], $id); } } foreach ($class->associationsMappings as $assocName => $assoc) { if ($actualData[$assocName]) { if (is_array($actualData[$assocName]) || $actualData[$assocName] instanceof Collection) { foreach ($actualData[$assocName] as $ref) { if ($ref !== null) { $this->computeReferenceChanges($ref); } } } else { $this->computeReferenceChanges($actualData[$assocName]); } } } foreach ($class->referrersMappings as $name => $referrerMapping) { if ($this->originalData[$oid][$name]) { foreach ($this->originalData[$oid][$name] as $referrer) { $this->computeReferrerChanges($referrer); } } } }