Esempio n. 1
0
 /**
  * Gets the specified field's value off the given document.
  *
  * @param object $document
  * @param string $field
  */
 public function getFieldValue($document, $field)
 {
     if ($document instanceof Proxy && !$document->__isInitialized()) {
         if ($field === $this->identifier) {
             return $document->__identifier__;
         } else {
             $document->__load();
         }
     }
     return $this->reflFields[$field]->getValue($document);
 }
 /**
  * @param object $entity
  * @return array
  * @throws NotManageableEntityException
  */
 public function getEntityIdentifier($entity)
 {
     if ($entity instanceof Proxy && !$entity->__isInitialized()) {
         $identifierProperty = new \ReflectionProperty(get_class($entity), '_identifier');
         $identifierProperty->setAccessible(true);
         $identifier = $identifierProperty->getValue($entity);
     } else {
         $entityManager = $this->getEntityManager($entity);
         $metadata = $entityManager->getClassMetadata(get_class($entity));
         $identifier = $metadata->getIdentifierValues($entity);
     }
     return $identifier;
 }
 /**
  * @param object $entity
  * @return object|null
  */
 protected function refreshEntity($entity)
 {
     if ($entity instanceof Proxy && !$entity->__isInitialized()) {
         $entity->__load();
     }
     if (!$this->doctrineHelper->getSingleEntityIdentifier($entity)) {
         return null;
     }
     $entityClass = ClassUtils::getClass($entity);
     /** @var EntityManager $entityManager */
     $entityManager = $this->registry->getManagerForClass($entityClass);
     return $entityManager->merge($entity);
 }
Esempio n. 4
0
 /**
  * Computes changeset for a given document.
  *
  * @param ClassMetadata $class
  * @param object        $document
  */
 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();
     }
 }
Esempio n. 5
0
 /**
  * Tests if an entity is loaded - must either be a loaded proxy or not a proxy
  *
  * @param object $entity
  *
  * @return bool
  */
 private function isLoaded($entity)
 {
     return !$entity instanceof Proxy || $entity->__isInitialized();
 }
Esempio n. 6
0
 /**
  * @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);
             }
         }
     }
 }