/** * Take a id to turn it into a embed document array representation * * @param mixed $document * * @return array */ public function fromEntityToDb($document) { $unitOfWork = $this->documentManager->getUnitOfWork(); $persistenceBuilder = new PersistenceBuilder($this->documentManager, $unitOfWork); $mapping = array('targetDocument' => $this->documentClass); return $persistenceBuilder->prepareEmbeddedDocumentValue($mapping, $document, true); }
/** * Inserts new rows for a PersistentCollection instance. * * @param PersistentCollection $coll * @param array $options */ private function insertRows(PersistentCollection $coll, array $options) { $mapping = $coll->getMapping(); list($propertyPath, $parent) = $this->getPathAndParent($coll); if ($mapping['strategy'] === 'set') { $setData = array(); foreach ($coll as $document) { if (isset($mapping['reference'])) { $setData[] = $this->pb->prepareReferencedDocumentValue($mapping, $document); } else { $setData[] = $this->pb->prepareEmbeddedDocumentValue($mapping, $document); } } $query = array($this->cmd . 'set' => array($propertyPath => $setData)); $this->executeQuery($parent, $query, $options); } else { $strategy = isset($mapping['strategy']) ? $mapping['strategy'] : 'pushAll'; $insertDiff = $coll->getInsertDiff(); if ($insertDiff) { $query = array($this->cmd . $strategy => array()); foreach ($insertDiff as $key => $document) { if (isset($mapping['reference'])) { $query[$this->cmd . $strategy][$propertyPath][] = $this->pb->prepareReferencedDocumentValue($mapping, $document); } else { $query[$this->cmd . $strategy][$propertyPath][] = $this->pb->prepareEmbeddedDocumentValue($mapping, $document); } } $this->executeQuery($parent, $query, $options); } } }
/** * Prepares a query value and converts the PHP value to the database value * if it is an identifier. * * It also handles converting $fieldName to the database name if they are different. * * @param string $fieldName * @param mixed $value * @param ClassMetadata $class Defaults to $this->class * @param boolean $prepareValue Whether or not to prepare the value * @return array Prepared field name and value */ private function prepareQueryElement($fieldName, $value = null, $class = null, $prepareValue = true) { $class = isset($class) ? $class : $this->class; // @todo Consider inlining calls to ClassMetadataInfo methods // Process all non-identifier fields by translating field names if ($class->hasField($fieldName) && !$class->isIdentifier($fieldName)) { $mapping = $class->fieldMappings[$fieldName]; $fieldName = $mapping['name']; if (!$prepareValue) { return array($fieldName, $value); } // Prepare mapped, embedded objects if (!empty($mapping['embedded']) && is_object($value) && !$this->dm->getMetadataFactory()->isTransient(get_class($value))) { return array($fieldName, $this->pb->prepareEmbeddedDocumentValue($mapping, $value)); } // No further preparation unless we're dealing with a simple reference // We can't have expressions in empty() with PHP < 5.5, so store it in a variable $arrayValue = (array) $value; if (empty($mapping['reference']) || empty($mapping['simple']) || empty($arrayValue)) { return array($fieldName, $value); } // Additional preparation for one or more simple reference values $targetClass = $this->dm->getClassMetadata($mapping['targetDocument']); if (!is_array($value)) { return array($fieldName, $targetClass->getDatabaseIdentifierValue($value)); } // Objects without operators or with DBRef fields can be converted immediately if (!$this->hasQueryOperators($value) || $this->hasDBRefFields($value)) { return array($fieldName, $targetClass->getDatabaseIdentifierValue($value)); } return array($fieldName, $this->prepareQueryExpression($value, $targetClass)); } // Process identifier fields if ($class->hasField($fieldName) && $class->isIdentifier($fieldName) || $fieldName === '_id') { $fieldName = '_id'; if (!$prepareValue) { return array($fieldName, $value); } if (!is_array($value)) { return array($fieldName, $class->getDatabaseIdentifierValue($value)); } // Objects without operators or with DBRef fields can be converted immediately if (!$this->hasQueryOperators($value) || $this->hasDBRefFields($value)) { return array($fieldName, $class->getDatabaseIdentifierValue($value)); } return array($fieldName, $this->prepareQueryExpression($value, $class)); } // No processing for unmapped, non-identifier, non-dotted field names if (strpos($fieldName, '.') === false) { return array($fieldName, $value); } /* Process "fieldName.objectProperty" queries (on arrays or objects). * * We can limit parsing here, since at most three segments are * significant: "fieldName.objectProperty" with an optional index or key * for collections stored as either BSON arrays or objects. */ $e = explode('.', $fieldName, 4); // No further processing for unmapped fields if (!isset($class->fieldMappings[$e[0]])) { return array($fieldName, $value); } $mapping = $class->fieldMappings[$e[0]]; $e[0] = $mapping['name']; // Hash and raw fields will not be prepared beyond the field name if ($mapping['type'] === Type::HASH || $mapping['type'] === Type::RAW) { $fieldName = implode('.', $e); return array($fieldName, $value); } if (isset($mapping['strategy']) && CollectionHelper::isHash($mapping['strategy']) && isset($e[2])) { $objectProperty = $e[2]; $objectPropertyPrefix = $e[1] . '.'; $nextObjectProperty = implode('.', array_slice($e, 3)); } elseif ($e[1] != '$') { $fieldName = $e[0] . '.' . $e[1]; $objectProperty = $e[1]; $objectPropertyPrefix = ''; $nextObjectProperty = implode('.', array_slice($e, 2)); } elseif (isset($e[2])) { $fieldName = $e[0] . '.' . $e[1] . '.' . $e[2]; $objectProperty = $e[2]; $objectPropertyPrefix = $e[1] . '.'; $nextObjectProperty = implode('.', array_slice($e, 3)); } else { $fieldName = $e[0] . '.' . $e[1]; return array($fieldName, $value); } // No further processing for fields without a targetDocument mapping if (!isset($mapping['targetDocument'])) { if ($nextObjectProperty) { $fieldName .= '.' . $nextObjectProperty; } return array($fieldName, $value); } $targetClass = $this->dm->getClassMetadata($mapping['targetDocument']); // No further processing for unmapped targetDocument fields if (!$targetClass->hasField($objectProperty)) { if ($nextObjectProperty) { $fieldName .= '.' . $nextObjectProperty; } return array($fieldName, $value); } $targetMapping = $targetClass->getFieldMapping($objectProperty); $objectPropertyIsId = $targetClass->isIdentifier($objectProperty); // Prepare DBRef identifiers or the mapped field's property path $fieldName = $objectPropertyIsId && !empty($mapping['reference']) && empty($mapping['simple']) ? $e[0] . '.$id' : $e[0] . '.' . $objectPropertyPrefix . $targetMapping['name']; // Process targetDocument identifier fields if ($objectPropertyIsId) { if (!$prepareValue) { return array($fieldName, $value); } if (!is_array($value)) { return array($fieldName, $targetClass->getDatabaseIdentifierValue($value)); } // Objects without operators or with DBRef fields can be converted immediately if (!$this->hasQueryOperators($value) || $this->hasDBRefFields($value)) { return array($fieldName, $targetClass->getDatabaseIdentifierValue($value)); } return array($fieldName, $this->prepareQueryExpression($value, $targetClass)); } /* The property path may include a third field segment, excluding the * collection item pointer. If present, this next object property must * be processed recursively. */ if ($nextObjectProperty) { // Respect the targetDocument's class metadata when recursing $nextTargetClass = isset($targetMapping['targetDocument']) ? $this->dm->getClassMetadata($targetMapping['targetDocument']) : null; list($key, $value) = $this->prepareQueryElement($nextObjectProperty, $value, $nextTargetClass, $prepareValue); $fieldName .= '.' . $key; } return array($fieldName, $value); }