/** * Sets the version field mapping used for versioning. Sets the default * value to use depending on the column type. * * @param array $mapping The version field mapping array * * @throws \CosmoW\ODM\Riak\LockException */ public function setLockMapping(array &$mapping) { if ($mapping['type'] !== 'int') { throw LockException::invalidLockFieldType($mapping['type']); } $this->isLockable = true; $this->lockField = $mapping['fieldName']; }
/** * Finds a document by a set of criteria. * * If a scalar or MongoId is provided for $criteria, it will be used to * match an _id value. * * @param mixed $criteria Query criteria * @param object $document Document to load the data into. If not specified, a new document is created. * @param array $hints Hints for document creation * @param integer $lockMode * @param array $sort Sort array for Cursor::sort() * @throws \CosmoW\ODM\Riak\LockException * @return object|null The loaded and managed document instance or null if no document was found * @todo Check identity map? loadById method? Try to guess whether $criteria is the id? */ public function load($criteria, $document = null, array $hints = array(), $lockMode = 0, array $sort = null) { // TODO: remove this if ($criteria === null || is_scalar($criteria) || $criteria instanceof \MongoId) { $criteria = array('_id' => $criteria); } $criteria = $this->prepareQueryOrNewObj($criteria); $criteria = $this->addDiscriminatorToPreparedQuery($criteria); $criteria = $this->addFilterToPreparedQuery($criteria); $cursor = $this->collection->find($criteria); if (null !== $sort) { $cursor->sort($this->prepareSortOrProjection($sort)); } $result = $cursor->getSingleResult(); if ($this->class->isLockable) { $lockMapping = $this->class->fieldMappings[$this->class->lockField]; if (isset($result[$lockMapping['name']]) && $result[$lockMapping['name']] === LockMode::PESSIMISTIC_WRITE) { throw LockException::lockFailed($result); } } return $this->createDocument($result, $document, $hints); }
/** * Finds a document by its identifier * * @param string|object $id The identifier * @param int $lockMode * @param int $lockVersion * @throws Mapping\MappingException * @throws LockException * @return object The document. */ public function find($id, $lockMode = LockMode::NONE, $lockVersion = null) { if ($id === null) { return; } /* TODO: What if the ID object has a field with the same name as the * class' mapped identifier field name? */ if (is_array($id)) { list($identifierFieldName) = $this->class->getIdentifierFieldNames(); if (isset($id[$identifierFieldName])) { $id = $id[$identifierFieldName]; } } // Check identity map first if ($document = $this->uow->tryGetById($id, $this->class)) { if ($lockMode != LockMode::NONE) { $this->dm->lock($document, $lockMode, $lockVersion); } return $document; // Hit! } $criteria = array('_id' => $id); if ($lockMode == LockMode::NONE) { return $this->getDocumentPersister()->load($criteria); } if ($lockMode == LockMode::OPTIMISTIC) { if (!$this->class->isVersioned) { throw LockException::notVersioned($this->documentName); } if ($document = $this->getDocumentPersister()->load($criteria)) { $this->uow->lock($document, $lockMode, $lockVersion); } return $document; } return $this->getDocumentPersister()->load($criteria, null, array(), $lockMode); }
/** * Executes a query updating the given document. * * @param object $document * @param array $newObj * @param array $options */ private function executeQuery($document, array $newObj, array $options) { $className = get_class($document); $class = $this->dm->getClassMetadata($className); $id = $class->getDatabaseIdentifierValue($this->uow->getDocumentIdentifier($document)); $query = array('_id' => $id); if ($class->isVersioned) { $query[$class->versionField] = $class->reflFields[$class->versionField]->getValue($document); } $collection = $this->dm->getDocumentCollection($className); $result = $collection->update($query, $newObj, $options); if ($class->isVersioned && !$result['n']) { throw LockException::lockFailed($document); } }
/** * Acquire a lock on the given document. * * @param object $document * @param int $lockMode * @param int $lockVersion * @throws LockException * @throws \InvalidArgumentException */ public function lock($document, $lockMode, $lockVersion = null) { if ($this->getDocumentState($document) != self::STATE_MANAGED) { throw new \InvalidArgumentException("Document is not MANAGED."); } $documentName = get_class($document); $class = $this->dm->getClassMetadata($documentName); if ($lockMode == LockMode::OPTIMISTIC) { if (!$class->isVersioned) { throw LockException::notVersioned($documentName); } if ($lockVersion != null) { $documentVersion = $class->reflFields[$class->versionField]->getValue($document); if ($documentVersion != $lockVersion) { throw LockException::lockFailedVersionMissmatch($document, $lockVersion, $documentVersion); } } } elseif (in_array($lockMode, array(LockMode::PESSIMISTIC_READ, LockMode::PESSIMISTIC_WRITE))) { $this->getDocumentPersister($class->name)->lock($document, $lockMode); } }