/** * Hydrate array of MongoDB document data into the given document object * based on the mapping information provided in the ClassMetadata instance. * * @param ClassMetadata $metadata The ClassMetadata instance for mapping information. * @param string $document The document object to hydrate the data into. * @param array $data The array of document data. * @return array $values The array of hydrated values. */ public function hydrate(ClassMetadata $metadata, $document, $data) { $values = array(); foreach ($metadata->fieldMappings as $mapping) { if (!isset($data[$mapping['fieldName']])) { continue; } if (isset($mapping['embedded'])) { $embeddedMetadata = $this->_dm->getClassMetadata($mapping['targetDocument']); $embeddedDocument = $embeddedMetadata->newInstance(); if ($mapping['type'] === 'many') { $documents = new ArrayCollection(); foreach ($data[$mapping['fieldName']] as $docArray) { $doc = clone $embeddedDocument; $this->hydrate($embeddedMetadata, $doc, $docArray); $documents->add($doc); } $metadata->setFieldValue($document, $mapping['fieldName'], $documents); $value = $documents; } else { $value = clone $embeddedDocument; $this->hydrate($embeddedMetadata, $value, $data[$mapping['fieldName']]); $metadata->setFieldValue($document, $mapping['fieldName'], $value); } } elseif (isset($mapping['reference'])) { $targetMetadata = $this->_dm->getClassMetadata($mapping['targetDocument']); $targetDocument = $targetMetadata->newInstance(); $value = isset($data[$mapping['fieldName']]) ? $data[$mapping['fieldName']] : null; if ($mapping['type'] === 'one' && isset($value['$id'])) { $id = (string) $value['$id']; $proxy = $this->_dm->getReference($mapping['targetDocument'], $id); $metadata->setFieldValue($document, $mapping['fieldName'], $proxy); } elseif ($mapping['type'] === 'many' && (is_array($value) || $value instanceof Collection)) { $documents = new PersistentCollection($this->_dm, $targetMetadata, new ArrayCollection()); $documents->setInitialized(false); foreach ($value as $v) { $id = (string) $v['$id']; $proxy = $this->_dm->getReference($mapping['targetDocument'], $id); $documents->add($proxy); } $metadata->setFieldValue($document, $mapping['fieldName'], $documents); } } else { $value = $data[$mapping['fieldName']]; $value = Type::getType($mapping['type'])->convertToPHPValue($value); $metadata->setFieldValue($document, $mapping['fieldName'], $value); } if (isset($value)) { $values[$mapping['fieldName']] = $value; } } if (isset($data['_id'])) { $metadata->setIdentifierValue($document, (string) $data['_id']); } return $values; }
/** * Updates the already persisted document if it has any new changesets. * * @param object $document * @param array $options Array of options to be used with update() */ public function update($document, array $options = array()) { $id = $this->uow->getDocumentIdentifier($document); $update = $this->dp->prepareUpdateData($document); if ( ! empty($update)) { $id = $this->class->getDatabaseIdentifierValue($id); $query = array('_id' => $id); // Include versioning updates if ($this->class->isVersioned) { $versionMapping = $this->class->fieldMappings[$this->class->versionField]; $currentVersion = $this->class->getFieldValue($document, $this->class->versionField); if ($versionMapping['type'] === 'int') { $nextVersion = $currentVersion + 1; $update[$this->cmd . 'inc'][$versionMapping['name']] = 1; $query[$versionMapping['name']] = $currentVersion; $this->class->setFieldValue($document, $this->class->versionField, $nextVersion); } elseif ($versionMapping['type'] === 'date') { $nextVersion = new \DateTime(); $update[$this->cmd . 'set'][$versionMapping['name']] = new \MongoDate($nextVersion->getTimestamp()); $query[$versionMapping['name']] = new \MongoDate($currentVersion->getTimestamp()); $this->class->setFieldValue($document, $this->class->versionField, $nextVersion); } $options['safe'] = true; } if ($this->class->isLockable) { $isLocked = $this->class->getFieldValue($document, $this->class->lockField); $lockMapping = $this->class->fieldMappings[$this->class->lockField]; if ($isLocked) { $update[$this->cmd . 'unset'] = array($lockMapping['name'] => true); } else { $query[$lockMapping['name']] = array($this->cmd . 'exists' => false); } } if ($this->dm->getEventManager()->hasListeners(Events::onUpdatePrepared)) { $this->dm->getEventManager()->dispatchEvent( Events::onUpdatePrepared, new OnUpdatePreparedArgs($this->dm, $document, $update) ); } $result = $this->collection->update($query, $update, $options); if (($this->class->isVersioned || $this->class->isLockable) && ! $result['n']) { throw LockException::lockFailed($document); } } }
/** * @param $object * @param $fieldName * @return ArrayCollection|mixed * @throws \NForms\Exceptions\MetadataException */ protected function getCollection($object, $fieldName) { if ($this->isSingleValuedAssociation($fieldName)) { throw new MetadataException("Can't get collection from association toOne."); } $collection = $this->classMetadata->getFieldValue($object, $fieldName); if ($collection === NULL) { $collection = new ArrayCollection(); $this->classMetadata->setFieldValue($object, $fieldName, $collection); } if (!$collection instanceof Collection) { throw new MetadataException('Expected Doctrine\\Common\\Collections\\Collection, given ' . (is_object($collection) ? get_class($collection) : gettype($collection))); } return $collection; }