Commit 5a44dc72 authored by Jeremy Mikola's avatar Jeremy Mikola

Merge pull request #99

parents af9bc65d e61ce5d9
...@@ -14,6 +14,12 @@ use MongoDB\Operation\ListDatabases; ...@@ -14,6 +14,12 @@ use MongoDB\Operation\ListDatabases;
class Client class Client
{ {
private static $defaultTypeMap = [
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
];
private $manager; private $manager;
private $uri; private $uri;
private $typeMap; private $typeMap;
...@@ -41,13 +47,7 @@ class Client ...@@ -41,13 +47,7 @@ class Client
*/ */
public function __construct($uri = 'mongodb://localhost:27017', array $uriOptions = [], array $driverOptions = []) public function __construct($uri = 'mongodb://localhost:27017', array $uriOptions = [], array $driverOptions = [])
{ {
$driverOptions += [ $driverOptions += ['typeMap' => self::$defaultTypeMap];
'typeMap' => [
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
],
];
if (isset($driverOptions['typeMap']) && ! is_array($driverOptions['typeMap'])) { if (isset($driverOptions['typeMap']) && ! is_array($driverOptions['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array'); throw InvalidArgumentException::invalidType('"typeMap" driver option', $driverOptions['typeMap'], 'array');
...@@ -103,12 +103,18 @@ class Client ...@@ -103,12 +103,18 @@ class Client
/** /**
* Drop a database. * Drop a database.
* *
* @param string $databaseName * @see DropDatabase::__construct() for supported options
* @return object Command result document * @param string $databaseName Database name
* @param array $options Additional options
* @return array|object Command result document
*/ */
public function dropDatabase($databaseName) public function dropDatabase($databaseName, array $options = [])
{ {
$operation = new DropDatabase($databaseName); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropDatabase($databaseName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
......
...@@ -36,6 +36,11 @@ use Traversable; ...@@ -36,6 +36,11 @@ use Traversable;
class Collection class Collection
{ {
private static $defaultTypeMap = [
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
];
private static $wireVersionForFindAndModifyWriteConcern = 4; private static $wireVersionForFindAndModifyWriteConcern = 4;
private $collectionName; private $collectionName;
...@@ -102,7 +107,7 @@ class Collection ...@@ -102,7 +107,7 @@ class Collection
$this->manager = $manager; $this->manager = $manager;
$this->readConcern = isset($options['readConcern']) ? $options['readConcern'] : $this->manager->getReadConcern(); $this->readConcern = isset($options['readConcern']) ? $options['readConcern'] : $this->manager->getReadConcern();
$this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference(); $this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference();
$this->typeMap = isset($options['typeMap']) ? $options['typeMap'] : null; $this->typeMap = isset($options['typeMap']) ? $options['typeMap'] : self::$defaultTypeMap;
$this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern(); $this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern();
} }
...@@ -340,11 +345,17 @@ class Collection ...@@ -340,11 +345,17 @@ class Collection
/** /**
* Drop this collection. * Drop this collection.
* *
* @return object Command result document * @see DropCollection::__construct() for supported options
* @param array $options Additional options
* @return array|object Command result document
*/ */
public function drop() public function drop(array $options = [])
{ {
$operation = new DropCollection($this->databaseName, $this->collectionName); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropCollection($this->databaseName, $this->collectionName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
...@@ -353,11 +364,13 @@ class Collection ...@@ -353,11 +364,13 @@ class Collection
/** /**
* Drop a single index in the collection. * Drop a single index in the collection.
* *
* @see DropIndexes::__construct() for supported options
* @param string $indexName Index name * @param string $indexName Index name
* @return object Command result document * @param array $options Additional options
* @return array|object Command result document
* @throws InvalidArgumentException if $indexName is an empty string or "*" * @throws InvalidArgumentException if $indexName is an empty string or "*"
*/ */
public function dropIndex($indexName) public function dropIndex($indexName, array $options = [])
{ {
$indexName = (string) $indexName; $indexName = (string) $indexName;
...@@ -365,7 +378,11 @@ class Collection ...@@ -365,7 +378,11 @@ class Collection
throw new InvalidArgumentException('dropIndexes() must be used to drop multiple indexes'); throw new InvalidArgumentException('dropIndexes() must be used to drop multiple indexes');
} }
$operation = new DropIndexes($this->databaseName, $this->collectionName, $indexName); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropIndexes($this->databaseName, $this->collectionName, $indexName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
...@@ -374,11 +391,17 @@ class Collection ...@@ -374,11 +391,17 @@ class Collection
/** /**
* Drop all indexes in the collection. * Drop all indexes in the collection.
* *
* @return object Command result document * @see DropIndexes::__construct() for supported options
* @param array $options Additional options
* @return array|object Command result document
*/ */
public function dropIndexes() public function dropIndexes(array $options = [])
{ {
$operation = new DropIndexes($this->databaseName, $this->collectionName, '*'); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropIndexes($this->databaseName, $this->collectionName, '*', $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
......
...@@ -20,6 +20,12 @@ use MongoDB\Operation\ListCollections; ...@@ -20,6 +20,12 @@ use MongoDB\Operation\ListCollections;
class Database class Database
{ {
private static $defaultTypeMap = [
'array' => 'MongoDB\Model\BSONArray',
'document' => 'MongoDB\Model\BSONDocument',
'root' => 'MongoDB\Model\BSONDocument',
];
private $databaseName; private $databaseName;
private $manager; private $manager;
private $readConcern; private $readConcern;
...@@ -80,7 +86,7 @@ class Database ...@@ -80,7 +86,7 @@ class Database
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->readConcern = isset($options['readConcern']) ? $options['readConcern'] : $this->manager->getReadConcern(); $this->readConcern = isset($options['readConcern']) ? $options['readConcern'] : $this->manager->getReadConcern();
$this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference(); $this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference();
$this->typeMap = isset($options['typeMap']) ? $options['typeMap'] : null; $this->typeMap = isset($options['typeMap']) ? $options['typeMap'] : self::$defaultTypeMap;
$this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern(); $this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern();
} }
...@@ -144,6 +150,10 @@ class Database ...@@ -144,6 +150,10 @@ class Database
$options['readPreference'] = $this->readPreference; $options['readPreference'] = $this->readPreference;
} }
if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DatabaseCommand($this->databaseName, $command, $options); $operation = new DatabaseCommand($this->databaseName, $command, $options);
$server = $this->manager->selectServer($options['readPreference']); $server = $this->manager->selectServer($options['readPreference']);
...@@ -169,11 +179,17 @@ class Database ...@@ -169,11 +179,17 @@ class Database
/** /**
* Drop this database. * Drop this database.
* *
* @return object Command result document * @see DropDatabase::__construct() for supported options
* @param array $options Additional options
* @return array|object Command result document
*/ */
public function drop() public function drop(array $options = [])
{ {
$operation = new DropDatabase($this->databaseName); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropDatabase($this->databaseName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
...@@ -182,12 +198,18 @@ class Database ...@@ -182,12 +198,18 @@ class Database
/** /**
* Drop a collection within this database. * Drop a collection within this database.
* *
* @param string $collectionName * @see DropCollection::__construct() for supported options
* @return object Command result document * @param string $collectionName Collection name
* @param array $options Additional options
* @return array|object Command result document
*/ */
public function dropCollection($collectionName) public function dropCollection($collectionName, array $options = [])
{ {
$operation = new DropCollection($this->databaseName, $collectionName); if ( ! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$operation = new DropCollection($this->databaseName, $collectionName, $options);
$server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY)); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
return $operation->execute($server); return $operation->execute($server);
......
...@@ -5,6 +5,7 @@ namespace MongoDB\Operation; ...@@ -5,6 +5,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Driver\Exception\RuntimeException; use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Exception\InvalidArgumentException;
/** /**
* Operation for the drop command. * Operation for the drop command.
...@@ -17,19 +18,32 @@ use MongoDB\Driver\Exception\RuntimeException; ...@@ -17,19 +18,32 @@ use MongoDB\Driver\Exception\RuntimeException;
class DropCollection implements Executable class DropCollection implements Executable
{ {
private static $errorMessageNamespaceNotFound = 'ns not found'; private static $errorMessageNamespaceNotFound = 'ns not found';
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $options;
/** /**
* Constructs a drop command. * Constructs a drop command.
* *
* Supported options:
*
* * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document.
*
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param array $options Command options
*/ */
public function __construct($databaseName, $collectionName) public function __construct($databaseName, $collectionName, array $options = [])
{ {
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->options = $options;
} }
/** /**
...@@ -37,7 +51,7 @@ class DropCollection implements Executable ...@@ -37,7 +51,7 @@ class DropCollection implements Executable
* *
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return object Command result document * @return array|object Command result document
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -55,6 +69,10 @@ class DropCollection implements Executable ...@@ -55,6 +69,10 @@ class DropCollection implements Executable
throw $e; throw $e;
} }
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
return current($cursor->toArray()); return current($cursor->toArray());
} }
} }
...@@ -4,6 +4,7 @@ namespace MongoDB\Operation; ...@@ -4,6 +4,7 @@ namespace MongoDB\Operation;
use MongoDB\Driver\Command; use MongoDB\Driver\Command;
use MongoDB\Driver\Server; use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
/** /**
* Operation for the dropDatabase command. * Operation for the dropDatabase command.
...@@ -16,15 +17,22 @@ use MongoDB\Driver\Server; ...@@ -16,15 +17,22 @@ use MongoDB\Driver\Server;
class DropDatabase implements Executable class DropDatabase implements Executable
{ {
private $databaseName; private $databaseName;
private $options;
/** /**
* Constructs a dropDatabase command. * Constructs a dropDatabase command.
* *
* @param string $databaseName Database name * @param string $databaseName Database name
* @param array $options Command options
*/ */
public function __construct($databaseName) public function __construct($databaseName, array $options = [])
{ {
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->options = $options;
} }
/** /**
...@@ -32,12 +40,16 @@ class DropDatabase implements Executable ...@@ -32,12 +40,16 @@ class DropDatabase implements Executable
* *
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return object Command result document * @return array|object Command result document
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$cursor = $server->executeCommand($this->databaseName, new Command(['dropDatabase' => 1])); $cursor = $server->executeCommand($this->databaseName, new Command(['dropDatabase' => 1]));
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
return current($cursor->toArray()); return current($cursor->toArray());
} }
} }
...@@ -18,6 +18,7 @@ class DropIndexes implements Executable ...@@ -18,6 +18,7 @@ class DropIndexes implements Executable
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $indexName; private $indexName;
private $options;
/** /**
* Constructs a dropIndexes command. * Constructs a dropIndexes command.
...@@ -25,9 +26,10 @@ class DropIndexes implements Executable ...@@ -25,9 +26,10 @@ class DropIndexes implements Executable
* @param string $databaseName Database name * @param string $databaseName Database name
* @param string $collectionName Collection name * @param string $collectionName Collection name
* @param string $indexName Index name (use "*" to drop all indexes) * @param string $indexName Index name (use "*" to drop all indexes)
* @param array $options Command options
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function __construct($databaseName, $collectionName, $indexName) public function __construct($databaseName, $collectionName, $indexName, array $options = [])
{ {
$indexName = (string) $indexName; $indexName = (string) $indexName;
...@@ -35,9 +37,14 @@ class DropIndexes implements Executable ...@@ -35,9 +37,14 @@ class DropIndexes implements Executable
throw new InvalidArgumentException('$indexName cannot be empty'); throw new InvalidArgumentException('$indexName cannot be empty');
} }
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
$this->databaseName = (string) $databaseName; $this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName; $this->collectionName = (string) $collectionName;
$this->indexName = $indexName; $this->indexName = $indexName;
$this->options = $options;
} }
/** /**
...@@ -45,7 +52,7 @@ class DropIndexes implements Executable ...@@ -45,7 +52,7 @@ class DropIndexes implements Executable
* *
* @see Executable::execute() * @see Executable::execute()
* @param Server $server * @param Server $server
* @return object Command result document * @return array|object Command result document
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
...@@ -56,6 +63,10 @@ class DropIndexes implements Executable ...@@ -56,6 +63,10 @@ class DropIndexes implements Executable
$cursor = $server->executeCommand($this->databaseName, new Command($cmd)); $cursor = $server->executeCommand($this->databaseName, new Command($cmd));
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
return current($cursor->toArray()); return current($cursor->toArray());
} }
} }
...@@ -115,9 +115,9 @@ class CollectionFunctionalTest extends FunctionalTestCase ...@@ -115,9 +115,9 @@ class CollectionFunctionalTest extends FunctionalTestCase
'sort' => ['x' => -1], 'sort' => ['x' => -1],
]; ];
$expected = (object) ['_id' => 3, 'x' => 33]; $expected = ['_id' => 3, 'x' => 33];
$this->assertEquals($expected, $this->collection->findOne($filter, $options)); $this->assertSameDocument($expected, $this->collection->findOne($filter, $options));
} }
public function testWithOptionsInheritsReadPreferenceAndWriteConcern() public function testWithOptionsInheritsReadPreferenceAndWriteConcern()
......
...@@ -32,9 +32,7 @@ abstract class FunctionalTestCase extends TestCase ...@@ -32,9 +32,7 @@ abstract class FunctionalTestCase extends TestCase
protected function assertCommandSucceeded($document) protected function assertCommandSucceeded($document)
{ {
if (is_object($document)) { $document = is_object($document) ? (array) $document : $document;
$document = get_object_vars($document);
}
$this->assertArrayHasKey('ok', $document); $this->assertArrayHasKey('ok', $document);
$this->assertEquals(1, $document['ok']); $this->assertEquals(1, $document['ok']);
...@@ -43,8 +41,8 @@ abstract class FunctionalTestCase extends TestCase ...@@ -43,8 +41,8 @@ abstract class FunctionalTestCase extends TestCase
protected function assertSameDocument($expectedDocument, $actualDocument) protected function assertSameDocument($expectedDocument, $actualDocument)
{ {
$this->assertEquals( $this->assertEquals(
($expectedDocument instanceof stdClass) ? (array) $expectedDocument : $expectedDocument, is_object($expectedDocument) ? (array) $expectedDocument : $expectedDocument,
($actualDocument instanceof stdClass) ? (array) $actualDocument : $actualDocument is_object($actualDocument) ? (array) $actualDocument : $actualDocument
); );
} }
...@@ -59,7 +57,7 @@ abstract class FunctionalTestCase extends TestCase ...@@ -59,7 +57,7 @@ abstract class FunctionalTestCase extends TestCase
} }
$normalizeRootDocuments = function($document) { $normalizeRootDocuments = function($document) {
return ($document instanceof stdClass) ? (array) $document : $document; return is_object($document) ? (array) $document : $document;
}; };
$this->assertEquals( $this->assertEquals(
......
<?php
namespace MongoDB\Tests\Operation;
use MongoDB\Operation\DropCollection;
class DropCollectionTest extends TestCase
{
/**
* @expectedException MongoDB\Exception\InvalidArgumentException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new DropCollection($this->getDatabaseName(), $this->getCollectionName(), $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidArrayValues() as $value) {
$options[][] = ['typeMap' => $value];
}
return $options;
}
}
<?php
namespace MongoDB\Tests\Operation;
use MongoDB\Operation\DropDatabase;
class DropDatabaseTest extends TestCase
{
/**
* @expectedException MongoDB\Exception\InvalidArgumentException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new DropDatabase($this->getDatabaseName(), $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidArrayValues() as $value) {
$options[][] = ['typeMap' => $value];
}
return $options;
}
}
...@@ -13,4 +13,24 @@ class DropIndexesTest extends TestCase ...@@ -13,4 +13,24 @@ class DropIndexesTest extends TestCase
{ {
new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), ''); new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), '');
} }
/**
* @expectedException MongoDB\Exception\InvalidArgumentException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), '*', $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidArrayValues() as $value) {
$options[][] = ['typeMap' => $value];
}
return $options;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment