/** * Checks that the current field includes a reference to the supplied document. */ public function includesReferenceTo($document) { if ($this->currentField) { $this->query[$this->currentField][$this->cmd . 'elemMatch'] = $this->class ? $this->dm->createDBRef($document, $this->class->getFieldMapping($this->currentField)) : $this->dm->createDBRef($document); } else { $this->query[$this->cmd . 'elemMatch'] = $this->dm->createDBRef($document); } return $this; }
/** * Checks that the current field includes a reference to the supplied document. * * @param object $document * @return Expr */ public function includesReferenceTo($document) { if ($this->currentField) { $mapping = $this->getReferenceMapping(); $dbRef = $this->dm->createDBRef($document, $mapping); $storeAs = array_key_exists('storeAs', $mapping) ? $mapping['storeAs'] : null; if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { $this->query[$mapping['name']] = $dbRef; } else { $keys = array('ref' => true, 'id' => true, 'db' => true); if ($storeAs === ClassMetadataInfo::REFERENCE_STORE_AS_DB_REF) { unset($keys['db']); } if (isset($mapping['targetDocument'])) { unset($keys['ref'], $keys['db']); } foreach ($keys as $key => $value) { $this->query[$this->currentField]['$elemMatch']['$' . $key] = $dbRef['$' . $key]; } } } else { $dbRef = $this->dm->createDBRef($document); $this->query['$elemMatch'] = $dbRef; } return $this; }
/** * Returns the reference representation to be stored in MongoDB. * * If the document does not have an identifier and the mapping calls for a * simple reference, null may be returned. * * @param array $referenceMapping * @param object $document * @return array|null */ public function prepareReferencedDocumentValue(array $referenceMapping, $document) { try { return $this->dm->createDBRef($document, $referenceMapping); } catch (\InvalidArgumentException $e) { throw new \InvalidArgumentException(sprintf('You are trying to reference a non-object in %s field, "%s" given', $referenceMapping['name'], $document)); } }
/** * Checks that the current field includes a reference to the supplied document. */ public function includesReferenceTo($document) { $dbRef = $this->dm->createDBRef($document); if ($this->currentField) { $keys = array('ref' => true, 'id' => true, 'db' => true); if ($this->class) { $mapping = $this->class->getFieldMapping($this->currentField); if (isset($mapping['targetDocument'])) { unset($keys['ref'], $keys['db']); } } foreach ($keys as $key => $value) { $this->query[$this->currentField][$this->cmd . 'elemMatch'][$this->cmd . $key] = $dbRef[$this->cmd . $key]; } } else { $this->query[$this->cmd . 'elemMatch'] = $dbRef; } return $this; }
/** * @param string $fieldName * @param mixed $value * @param array $mapping * @return array */ private function prepareDbRefElement($fieldName, $value, array $mapping) { $dbRef = $this->dm->createDBRef($value, $mapping); $keys = ['$ref' => true, '$id' => true, '$db' => true]; if ($mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { unset($keys['$db']); } if (isset($mapping['targetDocument'])) { unset($keys['$ref'], $keys['$db']); } if ($mapping['storeAs'] === ClassMetadataInfo::REFERENCE_STORE_AS_ID) { return [[$fieldName, $dbRef]]; } elseif ($mapping['type'] === 'many') { return [[$fieldName, ['$elemMatch' => array_intersect_key($dbRef, $keys)]]]; } else { return array_map(function ($key) use($dbRef, $fieldName) { return [$fieldName . '.' . $key, $dbRef[$key]]; }, array_keys($keys)); } }
/** * Checks that the current field includes a reference to the supplied document. * * @param object $document * @return Expr */ public function includesReferenceTo($document) { if ($this->currentField) { $mapping = $this->getReferenceMapping(); $dbRef = $this->dm->createDBRef($document, $mapping); if (isset($mapping['simple']) && $mapping['simple']) { $this->query[$mapping['name']]['$elemMatch'] = $dbRef; } else { $keys = array('ref' => true, 'id' => true, 'db' => true); if (isset($mapping['targetDocument'])) { unset($keys['ref'], $keys['db']); } foreach ($keys as $key => $value) { $this->query[$this->currentField]['$elemMatch']['$' . $key] = $dbRef['$' . $key]; } } } else { $dbRef = $this->dm->createDBRef($document); $this->query['$elemMatch'] = $dbRef; } return $this; }
/** * Returns the reference representation to be stored in MongoDB. * * If the document does not have an identifier and the mapping calls for a * simple reference, null may be returned. * * @param array $referenceMapping * @param object $document * @return array|null */ public function prepareReferencedDocumentValue(array $referenceMapping, $document) { return $this->dm->createDBRef($document, $referenceMapping); }
/** * 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)); } if (!empty($mapping['reference']) && is_object($value) && !$value instanceof \MongoId) { try { return array($fieldName, $this->dm->createDBRef($value, $mapping)); } catch (MappingException $e) { // do nothing in case passed object is not mapped document } } // 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']) || $mapping['storeAs'] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID || 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 ($mapping['type'] == 'many' && 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']) && $mapping['storeAs'] !== ClassMetadataInfo::REFERENCE_STORE_AS_ID ? $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); }