/** * Checks that the current field includes a reference to the supplied document. */ public function includesReferenceTo($document) { if ($this->currentField) { $mapping = $this->class->getFieldMapping($this->currentField); $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; }
/** * @param ClassMetadata $classMetadata * @param array $mapping */ private function remapAssociation(ClassMetadata $classMetadata, array $mapping) { $newMapping = $this->resolveTargetDocuments[$mapping['targetDocument']]; $newMapping = array_replace_recursive($mapping, $newMapping); $newMapping['fieldName'] = $mapping['fieldName']; // clear reference case of duplicate exception unset($classMetadata->fieldMappings[$mapping['fieldName']]); unset($classMetadata->associationMappings[$mapping['fieldName']]); switch ($mapping['association']) { case ClassMetadata::REFERENCE_ONE: $classMetadata->mapOneReference($newMapping); break; case ClassMetadata::REFERENCE_MANY: $classMetadata->mapManyReference($newMapping); break; case ClassMetadata::EMBED_ONE: $classMetadata->mapOneEmbedded($newMapping); break; case ClassMetadata::EMBED_MANY: $classMetadata->mapManyEmbedded($newMapping); break; } }
/** * Adds support for magic finders. * * @param string $method * @param array $arguments * @throws RiakException * @throws \BadMethodCallException If the method called is an invalid find* method * or no find* method at all and therefore an invalid * method call. * @return array|object The found document/documents. */ public function __call($method, $arguments) { if (substr($method, 0, 6) == 'findBy') { $by = substr($method, 6, strlen($method)); $method = 'findBy'; } elseif (substr($method, 0, 9) == 'findOneBy') { $by = substr($method, 9, strlen($method)); $method = 'findOneBy'; } else { throw new \BadMethodCallException("Undefined method '{$method}'. The method name must start with " . "either findBy or findOneBy!"); } if (!isset($arguments[0])) { throw RiakException::findByRequiresParameter($method . $by); } $fieldName = lcfirst(\Doctrine\Common\Util\Inflector::classify($by)); if ($this->class->hasField($fieldName)) { return $this->{$method}(array($fieldName => $arguments[0])); } else { throw RiakException::invalidFindByCall($this->documentName, $fieldName, $method . $by); } }
/** * @param ClassMetadata $class * @return array */ private function prepareIndexes(ClassMetadata $class) { $persister = $this->dm->getUnitOfWork()->getDocumentPersister($class->name); $indexes = $class->getIndexes(); $newIndexes = array(); foreach ($indexes as $index) { $newIndex = array('keys' => array(), 'options' => $index['options']); foreach ($index['keys'] as $key => $value) { $key = $persister->prepareFieldName($key); if ($class->hasField($key)) { $mapping = $class->getFieldMapping($key); $newIndex['keys'][$mapping['name']] = $value; } else { $newIndex['keys'][$key] = $value; } } $newIndexes[] = $newIndex; } return $newIndexes; }
/** * Prepares a query expression. * * @param array|object $expression * @param ClassMetadata $class * @return array */ private function prepareQueryExpression($expression, $class) { foreach ($expression as $k => $v) { // Ignore query operators whose arguments need no type conversion if (in_array($k, array('$exists', '$type', '$mod', '$size'))) { continue; } // Process query operators whose argument arrays need type conversion if (in_array($k, array('$in', '$nin', '$all')) && is_array($v)) { foreach ($v as $k2 => $v2) { $expression[$k][$k2] = $class->getDatabaseIdentifierValue($v2); } continue; } // Recursively process expressions within a $not operator if ($k === '$not' && is_array($v)) { $expression[$k] = $this->prepareQueryExpression($v, $class); continue; } $expression[$k] = $class->getDatabaseIdentifierValue($v); } return $expression; }
/** * INTERNAL: * Tries to get a document by its identifier hash. If no document is found * for the given hash, FALSE is returned. * * @ignore * @param mixed $id Document identifier * @param ClassMetadata $class Document class * @return mixed The found document or FALSE. * @throws InvalidArgumentException if the class does not have an identifier */ public function tryGetById($id, ClassMetadata $class) { if (!$class->identifier) { throw new \InvalidArgumentException(sprintf('Class "%s" does not have an identifier', $class->name)); } $serializedId = serialize($class->getDatabaseIdentifierValue($id)); return isset($this->identityMap[$class->name][$serializedId]) ? $this->identityMap[$class->name][$serializedId] : false; }
/** * Adds inherited indexes to the subclass mapping. * * @param ClassMetadata $subClass * @param ClassMetadata $parentClass */ private function addInheritedIndexes(ClassMetadata $subClass, ClassMetadata $parentClass) { foreach ($parentClass->indexes as $index) { $subClass->addIndex($index['keys'], $index['options']); } }
/** * If you are priming references inside an embedded document you'll need to parse the dot syntax. * This method will traverse through embedded documents to find the reference to prime. * However this method will not traverse through multiple layers of references. * I.e. you can prime this: myDocument.embeddedDocument.embeddedDocuments.embeddedDocuments.referencedDocument(s) * ... but you cannot prime this: myDocument.embeddedDocument.referencedDocuments.referencedDocument(s) * This addresses Issue #624. * * @param string $fieldName * @param ClassMetadata $class * @param array|\Traversable $documents * @param array $mapping * @return array */ private function parseDotSyntaxForPrimer($fieldName, $class, $documents, $mapping = null) { // Recursion passthrough: if ($mapping != null) { return array('fieldName' => $fieldName, 'class' => $class, 'documents' => $documents, 'mapping' => $mapping); } // Gather mapping data: $e = explode('.', $fieldName); if (!isset($class->fieldMappings[$e[0]])) { throw new \InvalidArgumentException(sprintf('Field %s cannot be further parsed for priming because it is unmapped.', $fieldName)); } $mapping = $class->fieldMappings[$e[0]]; $e[0] = $mapping['name']; // Case of embedded document(s) to recurse through: if (!isset($mapping['reference'])) { if (empty($mapping['embedded'])) { throw new \InvalidArgumentException(sprintf('Field "%s" of fieldName "%s" is not an embedded document, therefore no children can be primed. Aborting. This feature does not support traversing nested referenced documents at this time.', $e[0], $fieldName)); } if (!isset($mapping['targetDocument'])) { throw new \InvalidArgumentException(sprintf('No target document class has been specified for this embedded document. However, targetDocument mapping must be specified in order for prime to work on fieldName "%s" for mapping of field "%s".', $fieldName, $mapping['fieldName'])); } $childDocuments = array(); foreach ($documents as $document) { $fieldValue = $class->getFieldValue($document, $e[0]); if ($fieldValue instanceof PersistentCollection) { foreach ($fieldValue as $elemDocument) { array_push($childDocuments, $elemDocument); } } else { array_push($childDocuments, $fieldValue); } } array_shift($e); $childClass = $this->dm->getClassMetadata($mapping['targetDocument']); if (!$childClass->hasField($e[0])) { throw new \InvalidArgumentException(sprintf('Field to prime must exist in embedded target document. Reference fieldName "%s" for mapping of target document class "%s".', $fieldName, $mapping['targetDocument'])); } $childFieldName = implode('.', $e); return $this->parseDotSyntaxForPrimer($childFieldName, $childClass, $childDocuments); } // Case of reference(s) to prime: if ($mapping['reference']) { if (count($e) > 1) { throw new \InvalidArgumentException(sprintf('Cannot prime more than one layer deep but field "%s" is a reference and has children in fieldName "%s".', $e[0], $fieldName)); } return array('fieldName' => $fieldName, 'class' => $class, 'documents' => $documents, 'mapping' => $mapping); } }