Commit c1cc2d6f authored by Jeremy Mikola's avatar Jeremy Mikola

Merge pull request #65

parents 4327715e b1bc3c88
...@@ -22,6 +22,7 @@ use Traversable; ...@@ -22,6 +22,7 @@ use Traversable;
class Aggregate implements Executable class Aggregate implements Executable
{ {
private static $wireVersionForCursor = 2; private static $wireVersionForCursor = 2;
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
...@@ -39,6 +40,13 @@ class Aggregate implements Executable ...@@ -39,6 +40,13 @@ class Aggregate implements Executable
* *
* * batchSize (integer): The number of documents to return per batch. * * batchSize (integer): The number of documents to return per batch.
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation. This only applies when the $out
* stage is specified.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
...@@ -92,6 +100,10 @@ class Aggregate implements Executable ...@@ -92,6 +100,10 @@ class Aggregate implements Executable
throw new InvalidArgumentTypeException('"batchSize" option', $options['batchSize'], 'integer'); throw new InvalidArgumentTypeException('"batchSize" option', $options['batchSize'], 'integer');
} }
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
} }
...@@ -163,6 +175,10 @@ class Aggregate implements Executable ...@@ -163,6 +175,10 @@ class Aggregate implements Executable
$cmd['allowDiskUse'] = $this->options['allowDiskUse']; $cmd['allowDiskUse'] = $this->options['allowDiskUse'];
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
if (isset($this->options['maxTimeMS'])) { if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS']; $cmd['maxTimeMS'] = $this->options['maxTimeMS'];
} }
......
...@@ -24,6 +24,8 @@ class BulkWrite implements Executable ...@@ -24,6 +24,8 @@ class BulkWrite implements Executable
const UPDATE_MANY = 'updateMany'; const UPDATE_MANY = 'updateMany';
const UPDATE_ONE = 'updateOne'; const UPDATE_ONE = 'updateOne';
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $operations; private $operations;
...@@ -54,6 +56,9 @@ class BulkWrite implements Executable ...@@ -54,6 +56,9 @@ class BulkWrite implements Executable
* *
* Supported options for the bulk write operation: * Supported options for the bulk write operation:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * ordered (boolean): If true, when an insert fails, return without * * ordered (boolean): If true, when an insert fails, return without
* performing the remaining writes. If false, when a write fails, * performing the remaining writes. If false, when a write fails,
* continue with the remaining writes, if any. The default is true. * continue with the remaining writes, if any. The default is true.
...@@ -182,6 +187,10 @@ class BulkWrite implements Executable ...@@ -182,6 +187,10 @@ class BulkWrite implements Executable
$options += ['ordered' => true]; $options += ['ordered' => true];
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if ( ! is_bool($options['ordered'])) { if ( ! is_bool($options['ordered'])) {
throw new InvalidArgumentTypeException('"ordered" option', $options['ordered'], 'boolean'); throw new InvalidArgumentTypeException('"ordered" option', $options['ordered'], 'boolean');
} }
...@@ -205,7 +214,13 @@ class BulkWrite implements Executable ...@@ -205,7 +214,13 @@ class BulkWrite implements Executable
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$bulk = new Bulk(['ordered' => $this->options['ordered']]); $options = ['ordered' => $this->options['ordered']];
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$insertedIds = []; $insertedIds = [];
foreach ($this->operations as $i => $operation) { foreach ($this->operations as $i => $operation) {
......
...@@ -19,6 +19,8 @@ use MongoDB\Exception\UnexpectedValueException; ...@@ -19,6 +19,8 @@ use MongoDB\Exception\UnexpectedValueException;
*/ */
class FindAndModify implements Executable class FindAndModify implements Executable
{ {
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $options; private $options;
...@@ -28,6 +30,9 @@ class FindAndModify implements Executable ...@@ -28,6 +30,9 @@ class FindAndModify implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * fields (document): Limits the fields to return for the matching * * fields (document): Limits the fields to return for the matching
* document. * document.
* *
...@@ -66,6 +71,10 @@ class FindAndModify implements Executable ...@@ -66,6 +71,10 @@ class FindAndModify implements Executable
'upsert' => false, 'upsert' => false,
]; ];
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if (isset($options['fields']) && ! is_array($options['fields']) && ! is_object($options['fields'])) { if (isset($options['fields']) && ! is_array($options['fields']) && ! is_object($options['fields'])) {
throw new InvalidArgumentTypeException('"fields" option', $options['fields'], 'array or object'); throw new InvalidArgumentTypeException('"fields" option', $options['fields'], 'array or object');
} }
...@@ -116,7 +125,7 @@ class FindAndModify implements Executable ...@@ -116,7 +125,7 @@ class FindAndModify implements Executable
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$cursor = $server->executeCommand($this->databaseName, $this->createCommand()); $cursor = $server->executeCommand($this->databaseName, $this->createCommand($server));
$result = current($cursor->toArray()); $result = current($cursor->toArray());
if ( ! isset($result->value)) { if ( ! isset($result->value)) {
...@@ -144,9 +153,10 @@ class FindAndModify implements Executable ...@@ -144,9 +153,10 @@ class FindAndModify implements Executable
/** /**
* Create the findAndModify command. * Create the findAndModify command.
* *
* @param Server $server
* @return Command * @return Command
*/ */
private function createCommand() private function createCommand(Server $server)
{ {
$cmd = ['findAndModify' => $this->collectionName]; $cmd = ['findAndModify' => $this->collectionName];
...@@ -167,6 +177,10 @@ class FindAndModify implements Executable ...@@ -167,6 +177,10 @@ class FindAndModify implements Executable
$cmd['maxTimeMS'] = $this->options['maxTimeMS']; $cmd['maxTimeMS'] = $this->options['maxTimeMS'];
} }
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
return new Command($cmd); return new Command($cmd);
} }
} }
...@@ -26,6 +26,9 @@ class FindOneAndReplace implements Executable ...@@ -26,6 +26,9 @@ class FindOneAndReplace implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
......
...@@ -26,6 +26,9 @@ class FindOneAndUpdate implements Executable ...@@ -26,6 +26,9 @@ class FindOneAndUpdate implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to * * maxTimeMS (integer): The maximum amount of time to allow the query to
* run. * run.
* *
......
...@@ -18,6 +18,8 @@ use MongoDB\Exception\InvalidArgumentTypeException; ...@@ -18,6 +18,8 @@ use MongoDB\Exception\InvalidArgumentTypeException;
*/ */
class InsertMany implements Executable class InsertMany implements Executable
{ {
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $documents; private $documents;
...@@ -28,6 +30,9 @@ class InsertMany implements Executable ...@@ -28,6 +30,9 @@ class InsertMany implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * ordered (boolean): If true, when an insert fails, return without * * ordered (boolean): If true, when an insert fails, return without
* performing the remaining writes. If false, when a write fails, * performing the remaining writes. If false, when a write fails,
* continue with the remaining writes, if any. The default is true. * continue with the remaining writes, if any. The default is true.
...@@ -62,6 +67,10 @@ class InsertMany implements Executable ...@@ -62,6 +67,10 @@ class InsertMany implements Executable
$options += ['ordered' => true]; $options += ['ordered' => true];
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if ( ! is_bool($options['ordered'])) { if ( ! is_bool($options['ordered'])) {
throw new InvalidArgumentTypeException('"ordered" option', $options['ordered'], 'boolean'); throw new InvalidArgumentTypeException('"ordered" option', $options['ordered'], 'boolean');
} }
...@@ -85,7 +94,13 @@ class InsertMany implements Executable ...@@ -85,7 +94,13 @@ class InsertMany implements Executable
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$bulk = new Bulk(['ordered' => $this->options['ordered']]); $options = ['ordered' => $this->options['ordered']];
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$insertedIds = []; $insertedIds = [];
foreach ($this->documents as $i => $document) { foreach ($this->documents as $i => $document) {
......
...@@ -17,6 +17,8 @@ use MongoDB\Exception\InvalidArgumentTypeException; ...@@ -17,6 +17,8 @@ use MongoDB\Exception\InvalidArgumentTypeException;
*/ */
class InsertOne implements Executable class InsertOne implements Executable
{ {
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $document; private $document;
...@@ -27,6 +29,9 @@ class InsertOne implements Executable ...@@ -27,6 +29,9 @@ class InsertOne implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern. * * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
* *
* @param string $databaseName Database name * @param string $databaseName Database name
...@@ -41,6 +46,10 @@ class InsertOne implements Executable ...@@ -41,6 +46,10 @@ class InsertOne implements Executable
throw new InvalidArgumentTypeException('$document', $document, 'array or object'); throw new InvalidArgumentTypeException('$document', $document, 'array or object');
} }
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw new InvalidArgumentTypeException('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern'); throw new InvalidArgumentTypeException('"writeConcern" option', $options['writeConcern'], 'MongoDB\Driver\WriteConcern');
} }
...@@ -60,7 +69,13 @@ class InsertOne implements Executable ...@@ -60,7 +69,13 @@ class InsertOne implements Executable
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$bulk = new Bulk(); $options = [];
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$insertedId = $bulk->insert($this->document); $insertedId = $bulk->insert($this->document);
if ($insertedId === null) { if ($insertedId === null) {
......
...@@ -23,6 +23,9 @@ class ReplaceOne implements Executable ...@@ -23,6 +23,9 @@ class ReplaceOne implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * upsert (boolean): When true, a new document is created if no document * * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false. * matches the query. The default is false.
* *
......
...@@ -20,6 +20,8 @@ use MongoDB\Exception\InvalidArgumentTypeException; ...@@ -20,6 +20,8 @@ use MongoDB\Exception\InvalidArgumentTypeException;
*/ */
class Update implements Executable class Update implements Executable
{ {
private static $wireVersionForDocumentLevelValidation = 4;
private $databaseName; private $databaseName;
private $collectionName; private $collectionName;
private $filter; private $filter;
...@@ -31,6 +33,9 @@ class Update implements Executable ...@@ -31,6 +33,9 @@ class Update implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * multi (boolean): When true, updates all documents matching the query. * * multi (boolean): When true, updates all documents matching the query.
* This option cannot be true if the $update argument is a replacement * This option cannot be true if the $update argument is a replacement
* document (i.e. contains no update operators). The default is false. * document (i.e. contains no update operators). The default is false.
...@@ -63,6 +68,10 @@ class Update implements Executable ...@@ -63,6 +68,10 @@ class Update implements Executable
'upsert' => false, 'upsert' => false,
]; ];
if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) {
throw new InvalidArgumentTypeException('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean');
}
if ( ! is_bool($options['multi'])) { if ( ! is_bool($options['multi'])) {
throw new InvalidArgumentTypeException('"multi" option', $options['multi'], 'boolean'); throw new InvalidArgumentTypeException('"multi" option', $options['multi'], 'boolean');
} }
...@@ -95,13 +104,19 @@ class Update implements Executable ...@@ -95,13 +104,19 @@ class Update implements Executable
*/ */
public function execute(Server $server) public function execute(Server $server)
{ {
$options = [ $updateOptions = [
'multi' => $this->options['multi'], 'multi' => $this->options['multi'],
'upsert' => $this->options['upsert'], 'upsert' => $this->options['upsert'],
]; ];
$bulk = new Bulk(); $bulkOptions = [];
$bulk->update($this->filter, $this->update, $options);
if (isset($this->options['bypassDocumentValidation']) && \MongoDB\server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)) {
$bulkOptions['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($bulkOptions);
$bulk->update($this->filter, $this->update, $updateOptions);
$writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null; $writeConcern = isset($this->options['writeConcern']) ? $this->options['writeConcern'] : null;
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $writeConcern); $writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $writeConcern);
......
...@@ -23,6 +23,9 @@ class UpdateMany implements Executable ...@@ -23,6 +23,9 @@ class UpdateMany implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * upsert (boolean): When true, a new document is created if no document * * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false. * matches the query. The default is false.
* *
......
...@@ -23,6 +23,9 @@ class UpdateOne implements Executable ...@@ -23,6 +23,9 @@ class UpdateOne implements Executable
* *
* Supported options: * Supported options:
* *
* * bypassDocumentValidation (boolean): If true, allows the write to opt
* out of document level validation.
*
* * upsert (boolean): When true, a new document is created if no document * * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false. * matches the query. The default is false.
* *
......
...@@ -45,6 +45,10 @@ class AggregateTest extends TestCase ...@@ -45,6 +45,10 @@ class AggregateTest extends TestCase
$options[][] = ['batchSize' => $value]; $options[][] = ['batchSize' => $value];
} }
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidIntegerValues() as $value) { foreach ($this->getInvalidIntegerValues() as $value) {
$options[][] = ['maxTimeMS' => $value]; $options[][] = ['maxTimeMS' => $value];
} }
......
...@@ -350,6 +350,10 @@ class BulkWriteTest extends TestCase ...@@ -350,6 +350,10 @@ class BulkWriteTest extends TestCase
{ {
$options = []; $options = [];
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidBooleanValues() as $value) { foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['ordered' => $value]; $options[][] = ['ordered' => $value];
} }
......
...@@ -19,6 +19,10 @@ class FindAndModifyTest extends TestCase ...@@ -19,6 +19,10 @@ class FindAndModifyTest extends TestCase
{ {
$options = []; $options = [];
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidDocumentValues() as $value) { foreach ($this->getInvalidDocumentValues() as $value) {
$options[][] = ['fields' => $value]; $options[][] = ['fields' => $value];
} }
......
...@@ -47,6 +47,10 @@ class InsertManyTest extends TestCase ...@@ -47,6 +47,10 @@ class InsertManyTest extends TestCase
{ {
$options = []; $options = [];
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidBooleanValues() as $value) { foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['ordered' => $value]; $options[][] = ['ordered' => $value];
} }
......
...@@ -28,6 +28,10 @@ class InsertOneTest extends TestCase ...@@ -28,6 +28,10 @@ class InsertOneTest extends TestCase
{ {
$options = []; $options = [];
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidWriteConcernValues() as $value) { foreach ($this->getInvalidWriteConcernValues() as $value) {
$options[][] = ['writeConcern' => $value]; $options[][] = ['writeConcern' => $value];
} }
......
...@@ -39,6 +39,10 @@ class UpdateTest extends TestCase ...@@ -39,6 +39,10 @@ class UpdateTest extends TestCase
{ {
$options = []; $options = [];
foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['bypassDocumentValidation' => $value];
}
foreach ($this->getInvalidBooleanValues() as $value) { foreach ($this->getInvalidBooleanValues() as $value) {
$options[][] = ['multi' => $value]; $options[][] = ['multi' => $value];
} }
......
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