Commit 68acf014 authored by Jeremy Mikola's avatar Jeremy Mikola

PHPLIB-144: Use arrays to take Database and Collection options

If we've learned anything from the legacy driver, it's that options arrays will prove more flexible than nullable, positional arguments in the long run.
parent be188e3e
......@@ -75,40 +75,45 @@ class Client
/**
* Select a collection.
*
* If a write concern or read preference is not specified, the write concern
* or read preference of the Client will be applied, respectively.
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The default read
* preference to use for collection operations. Defaults to the Client's
* read preference.
*
* * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
* to use for collection operations. Defaults to the Client's write
* concern.
*
* @param string $databaseName Name of the database containing the collection
* @param string $collectionName Name of the collection to select
* @param WriteConcern $writeConcern Default write concern to apply
* @param ReadPreference $readPreference Default read preference to apply
* @param array $options Collection constructor options
* @return Collection
*/
public function selectCollection($databaseName, $collectionName, WriteConcern $writeConcern = null, ReadPreference $readPreference = null)
public function selectCollection($databaseName, $collectionName, array $options = [])
{
$namespace = $databaseName . '.' . $collectionName;
$writeConcern = $writeConcern ?: $this->manager->getWriteConcern();
$readPreference = $readPreference ?: $this->manager->getReadPreference();
return new Collection($this->manager, $namespace, $writeConcern, $readPreference);
return new Collection($this->manager, $databaseName . '.' . $collectionName, $options);
}
/**
* Select a database.
*
* If a write concern or read preference is not specified, the write concern
* or read preference of the Client will be applied, respectively.
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The default read
* preference to use for database operations and selected collections.
* Defaults to the Client's read preference.
*
* * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
* to use for database operations and selected collections. Defaults to
* the Client's write concern.
*
* @param string $databaseName Name of the database to select
* @param WriteConcern $writeConcern Default write concern to apply
* @param ReadPreference $readPreference Default read preference to apply
* @param array $options Database constructor options
* @return Database
*/
public function selectDatabase($databaseName, WriteConcern $writeConcern = null, ReadPreference $readPreference = null)
public function selectDatabase($databaseName, array $options = [])
{
$writeConcern = $writeConcern ?: $this->manager->getWriteConcern();
$readPreference = $readPreference ?: $this->manager->getReadPreference();
return new Database($this->manager, $databaseName, $writeConcern, $readPreference);
return new Database($this->manager, $databaseName, $options);
}
}
......@@ -9,6 +9,7 @@ use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
use MongoDB\Exception\UnexpectedTypeException;
use MongoDB\Model\IndexInfoIterator;
use MongoDB\Model\IndexInput;
......@@ -48,13 +49,22 @@ class Collection
* This class provides methods for collection-specific operations, such as
* CRUD (i.e. create, read, update, and delete) and index management.
*
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The default read
* preference to use for collection operations. Defaults to the Manager's
* read preference.
*
* * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
* to use for collection operations. Defaults to the Manager's write
* concern.
*
* @param Manager $manager Manager instance from the driver
* @param string $namespace Collection namespace (e.g. "db.collection")
* @param WriteConcern $writeConcern Default write concern to apply
* @param ReadPreference $readPreference Default read preference to apply
* @throws InvalidArgumentException if $namespace is invalid
* @param array $options Collection options
* @throws InvalidArgumentException
*/
public function __construct(Manager $manager, $namespace, WriteConcern $writeConcern = null, ReadPreference $readPreference = null)
public function __construct(Manager $manager, $namespace, array $options = [])
{
$parts = explode('.', $namespace, 2);
......@@ -65,13 +75,21 @@ class Collection
$this->databaseName = $parts[0];
$this->collectionName = $parts[1];
if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
throw new InvalidArgumentTypeException('"readPreference" option', $options['readPreference'], 'MongoDB\Driver\ReadPreference');
}
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw new InvalidArgumentTypeException('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->manager = $manager;
$this->writeConcern = $writeConcern ?: $this->manager->getWriteConcern();
$this->readPreference = $readPreference ?: $this->manager->getReadPreference();
$this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference();
$this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern();
}
/**
* Return the collection namespace.
* Return the collection namespace (e.g. "db.collection").
*
* @param string
*/
......
......@@ -11,6 +11,7 @@ use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
use MongoDB\Model\CollectionInfoIterator;
use MongoDB\Operation\CreateCollection;
use MongoDB\Operation\DropCollection;
......@@ -30,22 +31,39 @@ class Database
* This class provides methods for database-specific operations and serves
* as a gateway for accessing collections.
*
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The default read
* preference to use for database operations and selected collections.
* Defaults to the Manager's read preference.
*
* * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
* to use for database operations and selected collections. Defaults to
* the Manager's write concern.
*
* @param Manager $manager Manager instance from the driver
* @param string $databaseName Database name
* @param WriteConcern $writeConcern Default write concern to apply
* @param ReadPreference $readPreference Default read preference to apply
* @throws InvalidArgumentException if $databaseName is invalid
* @param array $options Database options
* @throws InvalidArgumentException
*/
public function __construct(Manager $manager, $databaseName, WriteConcern $writeConcern = null, ReadPreference $readPreference = null)
public function __construct(Manager $manager, $databaseName, array $options = [])
{
if (strlen($databaseName) < 1) {
throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName);
}
if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
throw new InvalidArgumentTypeException('"readPreference" option', $options['readPreference'], 'MongoDB\Driver\ReadPreference');
}
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw new InvalidArgumentTypeException('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
}
$this->manager = $manager;
$this->databaseName = (string) $databaseName;
$this->writeConcern = $writeConcern ?: $this->manager->getWriteConcern();
$this->readPreference = $readPreference ?: $this->manager->getReadPreference();
$this->readPreference = isset($options['readPreference']) ? $options['readPreference'] : $this->manager->getReadPreference();
$this->writeConcern = isset($options['writeConcern']) ? $options['writeConcern'] : $this->manager->getWriteConcern();
}
/**
......@@ -129,20 +147,30 @@ class Database
/**
* Select a collection within this database.
*
* If a write concern or read preference is not specified, the write concern
* or read preference of the Database will be applied, respectively.
* Supported options:
*
* * readPreference (MongoDB\Driver\ReadPreference): The default read
* preference to use for collection operations. Defaults to the
* Database's read preference.
*
* * writeConcern (MongoDB\Driver\WriteConcern): The default write concern
* to use for collection operations. Defaults to the Database's write
* concern.
*
* @param string $collectionName Name of the collection to select
* @param WriteConcern $writeConcern Default write concern to apply
* @param ReadPreference $readPreference Default read preference to apply
* @param array $options Collection constructor options
* @return Collection
*/
public function selectCollection($collectionName, WriteConcern $writeConcern = null, ReadPreference $readPreference = null)
public function selectCollection($collectionName, array $options = [])
{
$namespace = $this->databaseName . '.' . $collectionName;
$writeConcern = $writeConcern ?: $this->writeConcern;
$readPreference = $readPreference ?: $this->readPreference;
if ( ! isset($options['readPreference'])) {
$options['readPreference'] = $this->readPreference;
}
if ( ! isset($options['writeConcern'])) {
$options['writeConcern'] = $this->writeConcern;
}
return new Collection($this->manager, $namespace, $writeConcern, $readPreference);
return new Collection($this->manager, $this->databaseName . '.' . $collectionName, $options);
}
}
......@@ -31,6 +31,30 @@ class CollectionFunctionalTest extends FunctionalTestCase
];
}
/**
* @expectedException MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new Collection($this->manager, $this->getNamespace(), $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidReadPreferenceValues() as $value) {
$options[][] = ['readPreference' => $value];
}
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options;
}
public function testToString()
{
$this->assertEquals($this->getNamespace(), (string) $this->collection);
......
......@@ -28,6 +28,30 @@ class DatabaseFunctionalTest extends FunctionalTestCase
];
}
/**
* @expectedException MongoDB\Exception\InvalidArgumentTypeException
* @dataProvider provideInvalidConstructorOptions
*/
public function testConstructorOptionTypeChecks(array $options)
{
new Database($this->manager, $this->getDatabaseName(), $options);
}
public function provideInvalidConstructorOptions()
{
$options = [];
foreach ($this->getInvalidReadPreferenceValues() as $value) {
$options[][] = ['readPreference' => $value];
}
foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value];
}
return $options;
}
public function testToString()
{
$this->assertEquals($this->getDatabaseName(), (string) $this->database);
......
......@@ -45,16 +45,6 @@ abstract class TestCase extends BaseTestCase
return [123, 3.14, true, [], new stdClass];
}
protected function getInvalidReadPreferenceValues()
{
return [123, 3.14, 'foo', true, [], new stdClass];
}
protected function getInvalidWriteConcernValues()
{
return [123, 3.14, 'foo', true, [], new stdClass];
}
protected function wrapValuesForDataProvider(array $values)
{
return array_map(function($value) { return [$value]; }, $values);
......
......@@ -3,6 +3,7 @@
namespace MongoDB\Tests;
use ReflectionClass;
use stdClass;
abstract class TestCase extends \PHPUnit_Framework_TestCase
{
......@@ -28,6 +29,16 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
return getenv('MONGODB_DATABASE') ?: 'phplib_test';
}
protected function getInvalidReadPreferenceValues()
{
return [123, 3.14, 'foo', true, [], new stdClass];
}
protected function getInvalidWriteConcernValues()
{
return [123, 3.14, 'foo', true, [], new stdClass];
}
/**
* Return the test namespace.
*
......
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