Commit 330e1e30 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-138: Support typeMap option for Database::command()

This refactors the existing Database method to use an Operation class.
parent a3bf7021
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
namespace MongoDB; namespace MongoDB;
use MongoDB\Collection; use MongoDB\Collection;
use MongoDB\Driver\Command;
use MongoDB\Driver\Cursor; use MongoDB\Driver\Cursor;
use MongoDB\Driver\Manager; use MongoDB\Driver\Manager;
use MongoDB\Driver\Query; use MongoDB\Driver\Query;
...@@ -15,6 +14,7 @@ use MongoDB\Exception\InvalidArgumentException; ...@@ -15,6 +14,7 @@ use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException; use MongoDB\Exception\InvalidArgumentTypeException;
use MongoDB\Model\CollectionInfoIterator; use MongoDB\Model\CollectionInfoIterator;
use MongoDB\Operation\CreateCollection; use MongoDB\Operation\CreateCollection;
use MongoDB\Operation\DatabaseCommand;
use MongoDB\Operation\DropCollection; use MongoDB\Operation\DropCollection;
use MongoDB\Operation\DropDatabase; use MongoDB\Operation\DropDatabase;
use MongoDB\Operation\ListCollections; use MongoDB\Operation\ListCollections;
...@@ -116,27 +116,22 @@ class Database ...@@ -116,27 +116,22 @@ class Database
/** /**
* Execute a command on this database. * Execute a command on this database.
* *
* @see DatabaseCommand::__construct() for supported options
* @param array|object $command Command document * @param array|object $command Command document
* @param ReadPreference|null $readPreference Read preference * @param array $options Options for command execution
* @return Cursor * @return Cursor
* @throws InvalidArgumentException
*/ */
public function command($command, ReadPreference $readPreference = null) public function command($command, array $options = [])
{ {
if ( ! is_array($command) && ! is_object($command)) { if ( ! isset($options['readPreference'])) {
throw new InvalidArgumentTypeException('$command', $command, 'array or object'); $options['readPreference'] = $this->readPreference;
}
if ( ! $command instanceof Command) {
$command = new Command($command);
} }
if ( ! isset($readPreference)) { $operation = new DatabaseCommand($this->databaseName, $command, $options);
$readPreference = $this->readPreference; $server = $this->manager->selectServer($options['readPreference']);
}
$server = $this->manager->selectServer($readPreference);
return $server->executeCommand($this->databaseName, $command); return $operation->execute($server);
} }
/** /**
......
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
/**
* Operation for executing a database command.
*
* @api
* @see MongoDB\Database::command()
*/
class DatabaseCommand implements Executable
{
private $databaseName;
private $command;
private $options;
/**
* Constructs a command.
*
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The read preference to
* use when executing the command. This may be used when issuing the
* command to a replica set or mongos node to ensure that the driver sets
* the wire protocol accordingly or adds the read preference to the
* command document, respectively.
*
* * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server).
*
* @param string $databaseName Database name
* @param array|object $command Command document
* @param array $options Options for command execution
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $command, array $options = [])
{
if ( ! is_array($command) && ! is_object($command)) {
throw new InvalidArgumentTypeException('$command', $command, 'array or object');
}
if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
throw new InvalidArgumentTypeException('"readPreference" option', $options['readPreference'], 'MongoDB\Driver\ReadPreference');
}
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw new InvalidArgumentTypeException('"typeMap" option', $options['typeMap'], 'array');
}
$this->databaseName = (string) $databaseName;
$this->command = ($command instanceof Command) ? $command : new Command($command);
$this->options = $options;
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return integer
*/
public function execute(Server $server)
{
$readPreference = isset($this->options['readPreference']) ? $this->options['readPreference'] : null;
$cursor = $server->executeCommand($this->databaseName, $this->command, $readPreference);
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
return $cursor;
}
}
...@@ -68,8 +68,11 @@ class DatabaseFunctionalTest extends FunctionalTestCase ...@@ -68,8 +68,11 @@ class DatabaseFunctionalTest extends FunctionalTestCase
public function testCommand() public function testCommand()
{ {
$command = ['isMaster' => 1]; $command = ['isMaster' => 1];
$readPreference = new ReadPreference(ReadPreference::RP_PRIMARY); $options = [
$cursor = $this->database->command($command, $readPreference); 'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
];
$cursor = $this->database->command($command, $options);
$this->assertInstanceOf('MongoDB\Driver\Cursor', $cursor); $this->assertInstanceOf('MongoDB\Driver\Cursor', $cursor);
$commandResult = current($cursor->toArray()); $commandResult = current($cursor->toArray());
...@@ -79,6 +82,25 @@ class DatabaseFunctionalTest extends FunctionalTestCase ...@@ -79,6 +82,25 @@ class DatabaseFunctionalTest extends FunctionalTestCase
$this->assertTrue($commandResult->ismaster); $this->assertTrue($commandResult->ismaster);
} }
public function testCommandAppliesTypeMapToCursor()
{
$command = ['isMaster' => 1];
$options = [
'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
'typeMap' => ['root' => 'array'],
];
$cursor = $this->database->command($command, $options);
$this->assertInstanceOf('MongoDB\Driver\Cursor', $cursor);
$commandResult = current($cursor->toArray());
$this->assertCommandSucceeded($commandResult);
$this->assertInternalType('array', $commandResult);
$this->assertTrue(isset($commandResult['ismaster']));
$this->assertTrue($commandResult['ismaster']);
}
/** /**
* @expectedException MongoDB\Exception\InvalidArgumentTypeException * @expectedException MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidDocumentValues * @dataProvider provideInvalidDocumentValues
......
<?php
namespace MongoDB\Tests\Operation;
use MongoDB\Operation\DatabaseCommand;
class DatabaseCommandTest extends TestCase
{
/**
* @expectedException MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidDocumentValues
*/
public function testConstructorCommandArgumentTypeCheck($command)
{
new DatabaseCommand($this->getDatabaseName(), $command);
}
/**
* @expectedException MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new DatabaseCommand($this->getDatabaseName(), ['ping' => 1], $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidReadPreferenceValues() as $value) {
$options[][] = ['readPreference' => $value];
}
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