/**
* @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);
}
}
}
}