Doctrine\ODM\PHPCR\UnitOfWork::computeChangeSet PHP Метод

computeChangeSet() публичный Метод

Computes changeset for a given document.
public computeChangeSet ( ClassMetadata $class, object $document )
$class Doctrine\ODM\PHPCR\Mapping\ClassMetadata
$document object
    public function computeChangeSet(ClassMetadata $class, $document)
    {
        if ($document instanceof Proxy && !$document->__isInitialized()) {
            return;
        }
        $oid = spl_object_hash($document);
        if (in_array($oid, $this->changesetComputed)) {
            return;
        }
        $this->changesetComputed[] = $oid;
        $changeSet = $actualData = $this->getDocumentActualData($class, $document);
        $id = $this->getDocumentId($document, false);
        $isNew = !isset($this->originalData[$oid]);
        if ($isNew) {
            // Document is New and should be inserted
            $this->originalData[$oid] = $changeSet;
        } elseif (!empty($this->documentChangesets[$oid]['fields'])) {
            foreach ($this->documentChangesets[$oid]['fields'] as $fieldName => $data) {
                $this->originalData[$oid][$fieldName] = $data[0];
            }
        }
        if ($class->parentMapping && isset($changeSet[$class->parentMapping])) {
            $parent = $changeSet[$class->parentMapping];
            $parentClass = $this->dm->getClassMetadata(get_class($parent));
            $state = $this->getDocumentState($parent);
            if ($state === self::STATE_MANAGED) {
                $this->computeChangeSet($parentClass, $parent);
            }
        }
        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]));
                }
                $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');
        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]);
            }
            if (isset($this->originalData[$oid][$class->nodename]) && isset($changeSet[$class->nodename]) && $this->originalData[$oid][$class->nodename] !== $changeSet[$class->nodename]) {
                $destName = $changeSet[$class->nodename];
            }
            // 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));
                }
                // make sure destination nodename is okay
                if ($exception = $class->isValidNodename($destName)) {
                    throw IdException::illegalName($document, $class->nodename, $destName);
                }
                // 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));
            }
        }
        $fields = array_intersect_key($changeSet, $class->mappings);
        if ($this->isDocumentTranslatable($class)) {
            $locale = $this->getCurrentLocale($document, $class);
            // ensure we do not bind a previously removed translation
            if (!$this->isTranslationRemoved($document, $locale)) {
                $this->doBindTranslation($document, $locale, $class);
            }
        }
        if ($isNew) {
            $this->documentChangesets[$oid]['fields'] = $fields;
            $this->scheduledInserts[$oid] = $document;
            return;
        }
        $translationChanges = false;
        if ($this->isDocumentTranslatable($class)) {
            $oid = spl_object_hash($document);
            if (isset($this->documentTranslations[$oid])) {
                foreach ($this->documentTranslations[$oid] as $localeToCheck => $data) {
                    // a translation was removed
                    if (empty($data)) {
                        $translationChanges = true;
                        break;
                    }
                    // a translation was added
                    if (empty($this->originalTranslatedData[$oid][$localeToCheck])) {
                        $translationChanges = true;
                        break;
                    }
                    // a translation was changed
                    foreach ($data as $fieldName => $fieldValue) {
                        if ($this->originalTranslatedData[$oid][$localeToCheck][$fieldName] !== $fieldValue) {
                            $translationChanges = true;
                            break;
                        }
                    }
                }
            }
            // ensure that locale changes are not considered a change in the document
            if ($class->localeMapping && array_key_exists($class->localeMapping, $fields)) {
                unset($fields[$class->localeMapping]);
            }
        }
        foreach ($fields as $fieldName => $fieldValue) {
            $keepChange = false;
            if ($fieldValue instanceof ReferenceManyCollection || $fieldValue instanceof ReferrersCollection) {
                if ($fieldValue->changed()) {
                    $keepChange = true;
                }
            } elseif ($this->originalData[$oid][$fieldName] !== $fieldValue) {
                $keepChange = true;
            }
            if ($keepChange) {
                $fields[$fieldName] = array($this->originalData[$oid][$fieldName], $fieldValue);
            } else {
                unset($fields[$fieldName]);
            }
        }
        if (!empty($fields) || $translationChanges) {
            $this->documentChangesets[$oid]['fields'] = $fields;
            $this->originalData[$oid] = $actualData;
            $this->scheduledUpdates[$oid] = $document;
        } elseif (empty($this->documentChangesets[$oid]['reorderings'])) {
            unset($this->documentChangesets[$oid]);
            unset($this->scheduledUpdates[$oid]);
        } else {
            $this->documentChangesets[$oid]['fields'] = array();
        }
    }
UnitOfWork