Skip to content
This repository has been archived by the owner on Nov 11, 2020. It is now read-only.

DBRef database/collection method improvements #126

Merged
merged 4 commits into from
Aug 12, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 3 additions & 25 deletions lib/Doctrine/MongoDB/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,22 +190,12 @@ public function count(array $query = array(), $limit = 0, $skip = 0)
* Wrapper method for MongoCollection::createDBRef().
*
* @see http://php.net/manual/en/mongocollection.createdbref.php
* @param array $a
* @param mixed $documentOrId
* @return array
*/
public function createDBRef(array $a)
public function createDBRef($documentOrId)
{
if ($this->eventManager->hasListeners(Events::preCreateDBRef)) {
$this->eventManager->dispatchEvent(Events::preCreateDBRef, new EventArgs($this, $a));
}

$result = $this->doCreateDBRef($a);

if ($this->eventManager->hasListeners(Events::postCreateDBRef)) {
$this->eventManager->dispatchEvent(Events::postCreateDBRef, new EventArgs($this, $result));
}

return $result;
return $this->getMongoCollection()->createDBRef($documentOrId);
}

/**
Expand Down Expand Up @@ -894,18 +884,6 @@ protected function doBatchInsert(array &$a, array $options = array())
return $this->getMongoCollection()->batchInsert($a, $options);
}

/**
* Creates a database reference.
*
* @see Collection::createDBRef()
* @param array $a
* @return array
*/
protected function doCreateDBRef(array $a)
{
return $this->getMongoCollection()->createDBRef($a);
}

/**
* Execute the distinct command.
*
Expand Down
64 changes: 63 additions & 1 deletion lib/Doctrine/MongoDB/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Doctrine\Common\EventManager;
use Doctrine\MongoDB\Event\CreateCollectionEventArgs;
use Doctrine\MongoDB\Event\EventArgs;
use Doctrine\MongoDB\Event\MutableEventArgs;
use Doctrine\MongoDB\Util\ReadPreference;

/**
Expand Down Expand Up @@ -224,13 +225,27 @@ public function forceError()
/**
* Wrapper method for MongoDB::getDBRef().
*
* This method will dispatch preGetDBRef and postGetDBRef events.
*
* @see http://php.net/manual/en/mongodb.getdbref.php
* @param array $reference
* @return array|null
*/
public function getDBRef(array $reference)
{
return $this->getMongoDB()->getDBRef($reference);
if ($this->eventManager->hasListeners(Events::preGetDBRef)) {
$this->eventManager->dispatchEvent(Events::preGetDBRef, new EventArgs($this, $reference));
}

$result = $this->doGetDBRef($reference);

if ($this->eventManager->hasListeners(Events::postGetDBRef)) {
$eventArgs = new MutableEventArgs($this, $result);
$this->eventManager->dispatchEvent(Events::postGetDBRef, $eventArgs);
$result = $eventArgs->getData();
}

return $result;
}

/**
Expand Down Expand Up @@ -489,6 +504,21 @@ public function __toString()
return $this->name;
}

/**
* Resolves a database reference.
*
* @see Database::getDBRef()
* @param array $reference
* @return array|null
*/
protected function doGetDBRef(array $reference)
{
$database = $this;
return $this->retry(function() use ($database, $reference) {
return $database->getMongoDB()->getDBRef($reference);
});
}

/**
* Return a new GridFS instance.
*
Expand All @@ -512,4 +542,36 @@ protected function doSelectCollection($name)
{
return new Collection($this->connection, $name, $this, $this->eventManager, $this->cmd, $this->numRetries);
}

/**
* Conditionally retry a closure if it yields an exception.
*
* If the closure does not return successfully within the configured number
* of retries, its first exception will be thrown.
*
* This method should not be used for write operations.
*
* @param \Closure $retry
* @return mixed
*/
protected function retry(\Closure $retry)
{
if ($this->numRetries) {
$firstException = null;
for ($i = 0; $i <= $this->numRetries; $i++) {
try {
return $retry();
} catch (\MongoException $e) {
if (!$firstException) {
$firstException = $e;
}
if ($i === $this->numRetries) {
throw $firstException;
}
}
}
} else {
return $retry();
}
}
}
3 changes: 0 additions & 3 deletions lib/Doctrine/MongoDB/Events.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ private function __construct() {}
const preCreateCollection = 'preCreateCollection';
const postCreateCollection = 'postCreateCollection';

const preCreateDBRef = 'collectionPreCreateDBRef';
const postCreateDBRef = 'collectionPostCreateDBRef';

const preConnect = 'preConnect';
const postConnect = 'postConnect';

Expand Down
13 changes: 0 additions & 13 deletions lib/Doctrine/MongoDB/LoggableCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,19 +100,6 @@ public function count(array $query = array(), $limit = 0, $skip = 0)
return parent::count($query, $limit, $skip);
}

/**
* @see Collection::createDBRef()
*/
public function createDBRef(array $a)
{
$this->log(array(
'createDBRef' => true,
'reference' => $a,
));

return parent::createDBRef($a);
}

/**
* @see Collection::deleteIndex()
*/
Expand Down
14 changes: 0 additions & 14 deletions lib/Doctrine/MongoDB/LoggableDatabase.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,6 @@ public function createCollection($name, $capped = false, $size = 0, $max = 0)
return parent::createCollection($name, $capped, $size, $max);
}

/**
* @see Database::createDBRef()
*/
public function createDBRef($collection, $a)
{
$this->log(array(
'createDBRef' => true,
'collection' => $collection,
'reference' => $a,
));

return parent::createDBRef($collection, $a);
}

/**
* @see Database::drop()
*/
Expand Down
16 changes: 0 additions & 16 deletions tests/Doctrine/MongoDB/Tests/CollectionEventsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,22 +51,6 @@ public function testBatchInsert()
$this->assertSame($result, $collection->batchInsert($documents, $options));
}

public function testCreateDBRef()
{
$document = array('_id' => 1);
$result = array('$ref' => self::collectionName, '$id' => 1);

$eventManager = $this->getMockEventManager();
$collection = $this->getMockCollection($eventManager, array('doCreateDBRef' => $result));

$this->expectEvents($eventManager, array(
array(Events::preCreateDBRef, new EventArgs($collection, $document)),
array(Events::postCreateDBRef, new EventArgs($collection, $result)),
));

$this->assertSame($result, $collection->createDBRef($document));
}

public function testDistinct()
{
$field = 'x';
Expand Down
83 changes: 83 additions & 0 deletions tests/Doctrine/MongoDB/Tests/DatabaseEventsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Doctrine\MongoDB\Tests;

use Doctrine\Common\EventManager;
use Doctrine\MongoDB\Events;
use Doctrine\MongoDB\Event\EventArgs;
use Doctrine\MongoDB\Event\MutableEventArgs;

class DatabaseEventsTest extends \PHPUnit_Framework_TestCase
{
const databaseName = 'database';

public function testGetDBRef()
{
$reference = array('$ref' => 'collection', '$id' => 1);
$result = array('_id' => 1);

$eventManager = $this->getMockEventManager();
$db = $this->getMockDatabase($eventManager, array('doGetDBRef' => $result));

$this->expectEvents($eventManager, array(
array(Events::preGetDBRef, new EventArgs($db, $reference)),
array(Events::postGetDBRef, new MutableEventArgs($db, $result)),
));

$this->assertSame($result, $db->getDBRef($reference));
}

/**
* Expect events to be dispatched by the event manager in the given order.
*
* @param EventManager $em EventManager mock
* @param array $events Tuple of event name and dispatch argument
*/
private function expectEvents(EventManager $em, array $events)
{
/* Each event should be a tuple consisting of the event name and the
* dispatched argument (e.g. EventArgs).
*
* For each event, expect a call to hasListeners() immediately followed
* by a call to dispatchEvent(). The dispatch argument is passed as-is
* to with(), so constraints may be used (e.g. callback).
*/
foreach ($events as $i => $event) {
$em->expects($this->at($i * 2))
->method('hasListeners')
->with($event[0])
->will($this->returnValue(true));

$em->expects($this->at($i * 2 + 1))
->method('dispatchEvent')
->with($event[0], $event[1]);
}
}

private function getMockDatabase(EventManager $em, array $methods)
{
$c = $this->getMockBuilder('Doctrine\MongoDB\Connection')
->disableOriginalConstructor()
->getMock();

$db = $this->getMockBuilder('Doctrine\MongoDB\Database')
->setConstructorArgs(array($c, self::databaseName, $em, '$'))
->setMethods(array_keys($methods))
->getMock();

foreach ($methods as $method => $returnValue) {
$db->expects($this->once())
->method($method)
->will($this->returnValue($returnValue));
}

return $db;
}

private function getMockEventManager()
{
return $this->getMockBuilder('Doctrine\Common\EventManager')
->disableOriginalConstructor()
->getMock();
}
}