/**
  * @inheritdoc
  */
 function hydrate($document, $data, array $hints = [])
 {
     $hydratedData = [];
     foreach ($this->metadata->fieldMappings as $fieldName => $mapping) {
         $name = $mapping['name'];
         $propertyValue = isset($data[$name]) ? $data[$name] : null;
         if (!isset($mapping['association'])) {
             if ($propertyValue === null) {
                 continue;
             }
             $type = Type::getType($mapping['type']);
             $value = $type->convertToPHPValue($propertyValue);
             $this->metadata->reflFields[$fieldName]->setValue($document, $value);
             $hydratedData[$fieldName] = $value;
             continue;
         }
         if ($mapping['association'] & ClassMetadata::TO_MANY) {
             $coll = new PersistentCollection(new ArrayCollection(), $this->dm, $this->uow);
             $coll->setOwner($document, $mapping);
             $coll->setInitialized(false);
             if ($propertyValue) {
                 $coll->setData($propertyValue);
             }
             $this->metadata->reflFields[$fieldName]->setValue($document, $coll);
             $hydratedData[$fieldName] = $coll;
             continue;
         }
         if ($propertyValue === null) {
             continue;
         }
         if ($mapping['association'] === ClassMetadata::LINK) {
             if (is_string($propertyValue)) {
                 $link = $this->dm->getReference($propertyValue);
             } else {
                 $link = $this->uow->getOrCreateDocument($propertyValue);
             }
             $this->metadata->reflFields[$fieldName]->setValue($document, $link);
             $hydratedData[$fieldName] = $link;
             continue;
         }
         if ($mapping['association'] === ClassMetadata::EMBED) {
             // an embed one must have @class, we would support generic JSON properties via another mapping type
             if (!isset($propertyValue[self::ORIENT_PROPERTY_CLASS])) {
                 throw new HydratorException(sprintf("missing @class for embedded property '%s'", $name));
             }
             $oclass = $propertyValue[self::ORIENT_PROPERTY_CLASS];
             $embeddedMetadata = $this->dm->getMetadataFactory()->getMetadataForOClass($oclass);
             $doc = $embeddedMetadata->newInstance();
             $embeddedData = $this->dm->getHydratorFactory()->hydrate($doc, $propertyValue, $hints);
             $this->uow->registerManaged($doc, null, $embeddedData);
             $this->metadata->reflFields[$fieldName]->setValue($document, $doc);
             $hydratedData[$fieldName] = $doc;
             continue;
         }
     }
     return $hydratedData;
 }
Example #2
0
 /**
  * OProperty constructor.
  *
  * @param OClass $class
  * @param array  $meta
  *
  */
 public function __construct(OClass $class, array $meta)
 {
     parent::__construct($meta['name'], $class);
     $this->_meta = $meta;
     $this->_type = Type::getType(strtolower($meta['type']));
 }
 private function getDocReference($ref)
 {
     $oid = spl_object_hash($ref);
     if (isset($this->references[$oid])) {
         return $this->references[$oid];
     }
     /** @var ClassMetadata $rmd */
     $rmd = $this->metadataFactory->getMetadataFor(get_class($ref));
     $rid = $rmd->getIdentifierValue($ref);
     if ($rid === null) {
         throw new ODMOrientDbException('missing reference');
     }
     static $rid_type;
     if (!isset($rid_type)) {
         $rid_type = Type::getType('rid');
     }
     return $rid_type->convertToDatabaseValue($rid);
 }
Example #4
0
 private function computeOrRecomputeChangeSet(ClassMetadata $class, $document, $recompute = false)
 {
     $oid = spl_object_hash($document);
     $actualData = $this->getDocumentActualData($document);
     $isNewDocument = !isset($this->originalDocumentData[$oid]);
     if ($isNewDocument) {
         // Document is either NEW or MANAGED but not yet fully persisted (only has an id).
         // These result in an INSERT.
         $this->originalDocumentData[$oid] = $actualData;
         $changeSet = [];
         foreach ($actualData as $propName => $actualValue) {
             $changeSet[$propName] = [null, $actualValue];
         }
         $this->documentChangeSets[$oid] = $changeSet;
     } else {
         // Document is "fully" MANAGED: it was already fully persisted before
         // and we have a copy of the original data
         $originalData = $this->originalDocumentData[$oid];
         $changeSet = [];
         foreach ($actualData as $propName => $actualValue) {
             $orgValue = isset($originalData[$propName]) ? $originalData[$propName] : null;
             // skip if value has not changed
             if ($orgValue === $actualValue) {
                 continue;
             }
             // if relationship is a embed-one, schedule orphan removal to trigger cascade remove operations
             $field =& $class->fieldMappings[$propName];
             if (isset($field['embedded']) && $field['association'] === ClassMetadata::EMBED) {
                 if ($orgValue !== null) {
                     $this->scheduleOrphanRemoval($orgValue);
                 }
                 $changeSet[$propName] = [$orgValue, $actualValue];
                 continue;
             }
             // if owning side of reference-one relationship
             if (isset($field['reference'])) {
                 if ($field['association'] === ClassMetadata::LINK && $field['isOwningSide']) {
                     if ($orgValue !== null && $field['orphanRemoval']) {
                         $this->scheduleOrphanRemoval($orgValue);
                     }
                     $changeSet[$propName] = [$orgValue, $actualValue];
                     continue;
                 }
                 // ignore inverse side of reference-many relationship
                 if ($field['association'] & ClassMetadata::TO_MANY && !$field['isOwningSide']) {
                     continue;
                 }
             }
             // Persistent collection was exchanged with the "originally"
             // created one. This can only mean it was cloned and replaced
             // on another document.
             if ($actualValue instanceof PersistentCollection) {
                 $owner = $actualValue->getOwner();
                 if ($owner === null) {
                     // cloned
                     $actualValue->setOwner($document, $field);
                 } elseif ($owner !== $document) {
                     // no clone, we have to fix
                     if (!$actualValue->isInitialized()) {
                         $actualValue->initialize();
                         // we have to do this otherwise the cols share state
                     }
                     $newValue = clone $actualValue;
                     $newValue->setOwner($document, $field);
                     $class->reflFields[$propName]->setValue($document, $newValue);
                 }
             }
             // if embed-many or reference-many relationship
             if (isset($field['association']) && $field['association'] & ClassMetadata::TO_MANY) {
                 $changeSet[$propName] = [$orgValue, $actualValue];
                 if ($orgValue instanceof PersistentCollection) {
                     $this->collectionDeletions[] = $orgValue;
                 }
                 continue;
             }
             // skip equivalent date values
             if (isset($field['type']) && $field['type'] === 'date') {
                 $dateType = Type::getType('date');
                 if ($dateType->equalsPHP($orgValue, $actualValue)) {
                     continue;
                 }
             }
             // regular field
             $changeSet[$propName] = [$orgValue, $actualValue];
         }
         if ($changeSet) {
             $this->documentChangeSets[$oid] = $recompute && isset($this->documentChangeSets[$oid]) ? $changeSet + $this->documentChangeSets[$oid] : $changeSet;
             $this->originalDocumentData[$oid] = $actualData;
             $this->documentUpdates[$oid] = $document;
         }
     }
     // Look for changes in associations of the document
     foreach ($class->associationMappings as $fieldName => $mapping) {
         $value = $class->reflFields[$fieldName]->getValue($document);
         if ($value !== null) {
             $this->computeAssociationChanges($document, $mapping, $value);
             if (isset($mapping['reference'])) {
                 continue;
             }
             // embedded documents must set the state of their parent
             $values = $value;
             if ($mapping['association'] & ClassMetadata::TO_ONE) {
                 $values = [$values];
             } elseif ($values instanceof PersistentCollection) {
                 if ($values->isDirty()) {
                     $this->documentChangeSets[$oid][$mapping['fieldName']] = [$value, $value];
                     if (!$isNewDocument) {
                         $this->documentUpdates[$oid] = $document;
                     }
                     continue;
                 }
                 $values = $values->unwrap();
             }
             foreach ($values as $obj) {
                 $oid2 = spl_object_hash($obj);
                 if (isset($this->documentChangeSets[$oid2])) {
                     $this->documentChangeSets[$oid][$mapping['fieldName']] = [$value, $value];
                     if (!$isNewDocument) {
                         $this->documentUpdates[$oid] = $document;
                     }
                     break;
                 }
             }
         }
     }
 }