/** * 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) { $rawValue = $this->_getFieldValue($mapping, $document, $data); if (!isset($rawValue)) { continue; } if (isset($mapping['embedded'])) { $embeddedMetadata = $this->_dm->getClassMetadata($mapping['targetDocument']); $embeddedDocument = $embeddedMetadata->newInstance(); if ($mapping['type'] === 'many') { $documents = new ArrayCollection(); foreach ($rawValue 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, $rawValue); $metadata->setFieldValue($document, $mapping['fieldName'], $value); } } elseif (isset($mapping['reference'])) { $targetMetadata = $this->_dm->getClassMetadata($mapping['targetDocument']); $targetDocument = $targetMetadata->newInstance(); if ($mapping['type'] === 'one' && isset($rawValue[$this->_cmd . 'id'])) { $id = $targetMetadata->getPHPIdentifierValue($rawValue[$this->_cmd . 'id']); $proxy = $this->_dm->getReference($mapping['targetDocument'], $id); $metadata->setFieldValue($document, $mapping['fieldName'], $proxy); } elseif ($mapping['type'] === 'many' && (is_array($rawValue) || $rawValue instanceof Collection)) { $documents = new PersistentCollection($this->_dm, $targetMetadata, new ArrayCollection()); $documents->setInitialized(false); foreach ($rawValue as $v) { $id = $targetMetadata->getPHPIdentifierValue($v[$this->_cmd . 'id']); $proxy = $this->_dm->getReference($mapping['targetDocument'], $id); $documents->add($proxy); } $metadata->setFieldValue($document, $mapping['fieldName'], $documents); } } else { $value = Type::getType($mapping['type'])->convertToPHPValue($rawValue); $metadata->setFieldValue($document, $mapping['fieldName'], $value); } if (isset($value)) { $values[$mapping['fieldName']] = $value; } } if (isset($data['_id'])) { $metadata->setIdentifierValue($document, $data['_id']); } return $values; }
/** * @param ClassMetadata $class * @param object $document * @throws \InvalidArgumentException If there is something wrong with document's identifier. */ private function persistNew(ClassMetadata $class, $document) { $oid = spl_object_hash($document); if (!empty($class->lifecycleCallbacks[Events::prePersist])) { $class->invokeLifecycleCallbacks(Events::prePersist, $document); } if ($this->evm->hasListeners(Events::prePersist)) { $this->evm->dispatchEvent(Events::prePersist, new LifecycleEventArgs($document, $this->dm)); } $upsert = false; if ($class->identifier) { $idValue = $class->getIdentifierValue($document); $upsert = !$class->isEmbeddedDocument && $idValue !== null; if ($class->generatorType === ClassMetadata::GENERATOR_TYPE_NONE && $idValue === null) { throw new \InvalidArgumentException(sprintf("%s uses NONE identifier generation strategy but no identifier was provided when persisting.", get_class($document))); } // \MongoId::isValid($idValue) was introduced in 1.5.0 so it's no good if ($class->generatorType === ClassMetadata::GENERATOR_TYPE_AUTO && $idValue !== null && !preg_match('/^[0-9a-f]{24}$/', $idValue)) { throw new \InvalidArgumentException(sprintf("%s uses AUTO identifier generation strategy but provided identifier is not valid MongoId.", get_class($document))); } if ($class->generatorType !== ClassMetadata::GENERATOR_TYPE_NONE && $idValue === null) { $idValue = $class->idGenerator->generate($this->dm, $document); $idValue = $class->getPHPIdentifierValue($class->getDatabaseIdentifierValue($idValue)); $class->setIdentifierValue($document, $idValue); } $this->documentIdentifiers[$oid] = $idValue; } else { // this is for embedded documents without identifiers $this->documentIdentifiers[$oid] = $oid; } $this->documentStates[$oid] = self::STATE_MANAGED; if ($upsert) { $this->scheduleForUpsert($class, $document); } else { $this->scheduleForInsert($class, $document); } }
/** * Executes all document insertions for documents of the specified type. * * @param Doctrine\ODM\MongoDB\Mapping\ClassMetadata $class * @param array $options Array of options to be used with batchInsert() */ private function executeInserts($class, array $options = array()) { $className = $class->name; $persister = $this->getDocumentPersister($className); $collection = $this->dm->getDocumentCollection($className); $hasLifecycleCallbacks = isset($class->lifecycleCallbacks[Events::postPersist]); $hasListeners = $this->evm->hasListeners(Events::postPersist); if ($hasLifecycleCallbacks || $hasListeners) { $documents = array(); } $inserts = array(); foreach ($this->documentInsertions as $oid => $document) { if (get_class($document) === $className) { $persister->addInsert($document); unset($this->documentInsertions[$oid]); if ($hasLifecycleCallbacks || $hasListeners) { $documents[] = $document; } } } $postInsertIds = $persister->executeInserts($options); if ($postInsertIds) { foreach ($postInsertIds as $pair) { list($id, $document) = $pair; $oid = spl_object_hash($document); $class->setIdentifierValue($document, $id); $this->documentIdentifiers[$oid] = $id; $this->documentStates[$oid] = self::STATE_MANAGED; $this->originalDocumentData[$oid][$class->identifier] = $id; $this->addToIdentityMap($document); if ($hasLifecycleCallbacks || $hasListeners) { if ($hasLifecycleCallbacks) { $class->invokeLifecycleCallbacks(Events::postPersist, $document); } if ($hasListeners) { $this->evm->dispatchEvent(Events::postPersist, new LifecycleEventArgs($document, $this->dm)); } } $this->cascadePostPersist($class, $document); } } }