Skip to content

Commit 0128d99

Browse files
committed
Merge pull request #1192 from malarzm/collection-vs-lock
Mind versioning when updating collections
2 parents 5632b82 + dcd8aff commit 0128d99

2 files changed

Lines changed: 60 additions & 4 deletions

File tree

lib/Doctrine/ODM/MongoDB/Persisters/CollectionPersister.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace Doctrine\ODM\MongoDB\Persisters;
2121

2222
use Doctrine\ODM\MongoDB\DocumentManager;
23+
use Doctrine\ODM\MongoDB\LockException;
2324
use Doctrine\ODM\MongoDB\PersistentCollection;
2425
use Doctrine\ODM\MongoDB\Persisters\PersistenceBuilder;
2526
use Doctrine\ODM\MongoDB\UnitOfWork;
@@ -260,15 +261,22 @@ private function getPathAndParent(PersistentCollection $coll)
260261
* Executes a query updating the given document.
261262
*
262263
* @param object $document
263-
* @param array $query
264+
* @param array $newObj
264265
* @param array $options
265266
*/
266-
private function executeQuery($document, array $query, array $options)
267+
private function executeQuery($document, array $newObj, array $options)
267268
{
268269
$className = get_class($document);
269270
$class = $this->dm->getClassMetadata($className);
270271
$id = $class->getDatabaseIdentifierValue($this->uow->getDocumentIdentifier($document));
272+
$query = array('_id' => $id);
273+
if ($class->isVersioned) {
274+
$query[$class->versionField] = $class->reflFields[$class->versionField]->getValue($document);
275+
}
271276
$collection = $this->dm->getDocumentCollection($className);
272-
$collection->update(array('_id' => $id), $query, $options);
277+
$result = $collection->update($query, $newObj, $options);
278+
if (($class->isVersioned) && ! $result['n']) {
279+
throw LockException::lockFailed($document);
280+
}
273281
}
274282
}

tests/Doctrine/ODM/MongoDB/Tests/Functional/LockTest.php

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
namespace Doctrine\ODM\MongoDB\Tests\Functional;
44

5+
use Doctrine\Common\Collections\ArrayCollection;
6+
use Doctrine\ODM\MongoDB\LockException;
57
use Doctrine\ODM\MongoDB\LockMode;
68
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
9+
use Documents\Issue;
710

811
class LockTest extends \Doctrine\ODM\MongoDB\Tests\BaseTest
912
{
@@ -365,6 +368,45 @@ public function testInvalidVersionDocument()
365368
$this->setExpectedException('Doctrine\ODM\MongoDB\MongoDBException', 'Invalid version field type string. Version field must be int or date.');
366369
$this->dm->getClassMetadata(__NAMESPACE__.'\InvalidVersionDocument');
367370
}
371+
372+
/**
373+
* @expectedException Doctrine\ODM\MongoDB\LockException
374+
*/
375+
public function testUpdatingCollectionRespectsVersionNumber()
376+
{
377+
$d = new LockInt('test');
378+
$d->issues->add(new Issue('hi', 'ohai'));
379+
$this->dm->persist($d);
380+
$this->dm->flush();
381+
382+
// simulate another request updating document in the meantime
383+
$this->dm->getDocumentCollection(__NAMESPACE__.'\LockInt')->update(
384+
array('_id' => new \MongoId($d->id)),
385+
array('$set' => array('version' => 2))
386+
);
387+
388+
$d->issues->add(new Issue('oops', 'version mismatch'));
389+
$this->uow->getCollectionPersister()->update($d->issues, array());
390+
}
391+
392+
/**
393+
* @expectedException Doctrine\ODM\MongoDB\LockException
394+
*/
395+
public function testDeletingCollectionRespectsVersionNumber()
396+
{
397+
$d = new LockInt('test');
398+
$d->issues->add(new Issue('hi', 'ohai'));
399+
$this->dm->persist($d);
400+
$this->dm->flush();
401+
402+
// simulate another request updating document in the meantime
403+
$this->dm->getDocumentCollection(__NAMESPACE__.'\LockInt')->update(
404+
array('_id' => new \MongoId($d->id)),
405+
array('$set' => array('version' => 2))
406+
);
407+
408+
$this->uow->getCollectionPersister()->delete($d->issues, array());
409+
}
368410
}
369411

370412
/** @ODM\MappedSuperclass */
@@ -379,8 +421,14 @@ abstract class AbstractVersionBase
379421
/** @ODM\Lock @ODM\Int */
380422
public $locked;
381423

424+
/**
425+
* @ODM\EmbedMany(targetDocument="Documents\Issue")
426+
*/
427+
public $issues;
428+
382429
public function __construct($title = null)
383430
{
431+
$this->issues = new ArrayCollection();
384432
$this->title = $title;
385433
}
386434

@@ -391,7 +439,7 @@ public function getId()
391439

392440
public function getTitle()
393441
{
394-
return $title;
442+
return $this->title;
395443
}
396444

397445
public function getVersion()

0 commit comments

Comments
 (0)