Commit 02e651cb authored by Jeremy Mikola's avatar Jeremy Mikola

Extract Collection findAndModify methods to operation classes

parent e36a304c
...@@ -19,6 +19,9 @@ use MongoDB\Operation\Aggregate; ...@@ -19,6 +19,9 @@ use MongoDB\Operation\Aggregate;
use MongoDB\Operation\CreateIndexes; use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\Count; use MongoDB\Operation\Count;
use MongoDB\Operation\Distinct; use MongoDB\Operation\Distinct;
use MongoDB\Operation\FindOneAndDelete;
use MongoDB\Operation\FindOneAndReplace;
use MongoDB\Operation\FindOneAndUpdate;
use Traversable; use Traversable;
class Collection class Collection
...@@ -452,103 +455,63 @@ class Collection ...@@ -452,103 +455,63 @@ class Collection
/** /**
* Finds a single document and deletes it, returning the original. * Finds a single document and deletes it, returning the original.
* *
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/ * The document to return may be null.
* @see Collection::getFindOneAndDelete() for supported $options
* *
* @param array $filter The $filter criteria to search for * @see FindOneAndDelete::__construct() for supported options
* @param array $options Additional options * @param array|object $filter Query by which to filter documents
* @return array The original document * @param array $options Command options
* @return array|null
*/ */
public function findOneAndDelete(array $filter, array $options = array()) public function findOneAndDelete($filter, array $options = array())
{ {
$options = array_merge($this->getFindOneAndDeleteOptions(), $options); $operation = new FindOneAndDelete($this->dbname, $this->collname, $filter, $options);
$options = $this->_massageFindAndModifyOptions($options); $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
$cmd = array(
"findandmodify" => $this->collname,
"query" => $filter,
) + $options;
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
if ($doc["ok"]) {
return is_object($doc["value"]) ? (array) $doc["value"] : $doc["value"];
}
throw $this->_generateCommandException($doc); return $operation->execute($server);
} }
/** /**
* Finds a single document and replaces it, returning either the original or the replaced document * Finds a single document and replaces it, returning either the original or
* By default, returns the original document. * the replaced document.
* To return the new document set:
* $options = array("returnDocument" => Collection::FIND_ONE_AND_RETURN_AFTER);
* *
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/ * The document to return may be null. By default, the original document is
* @see Collection::getFindOneAndReplace() for supported $options * returned. Specify FindOneAndReplace::RETURN_DOCUMENT_AFTER for the
* "returnDocument" option to return the updated document.
* *
* @param array $filter The $filter criteria to search for * @see FindOneAndReplace::__construct() for supported options
* @param array $replacement The document to replace with * @param array|object $filter Query by which to filter documents
* @param array $options Additional options * @param array|object $replacement Replacement document
* @return array * @param array $options Command options
* @return array|null
*/ */
public function findOneAndReplace(array $filter, array $replacement, array $options = array()) public function findOneAndReplace($filter, $replacement, array $options = array())
{ {
$firstKey = key($replacement); $operation = new FindOneAndReplace($this->dbname, $this->collname, $filter, $replacement, $options);
if (isset($firstKey[0]) && $firstKey[0] == '$') { $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
throw new InvalidArgumentException("First key in \$replacement must NOT be a \$operator");
}
$options = array_merge($this->getFindOneAndReplaceOptions(), $options);
$options = $this->_massageFindAndModifyOptions($options, $replacement);
$cmd = array(
"findandmodify" => $this->collname,
"query" => $filter,
) + $options;
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
if ($doc["ok"]) {
return $this->_massageFindAndModifyResult($doc, $options);
}
throw $this->_generateCommandException($doc); return $operation->execute($server);
} }
/** /**
* Finds a single document and updates it, returning either the original or the updated document * Finds a single document and updates it, returning either the original or
* By default, returns the original document. * the updated document.
* To return the new document set:
* $options = array("returnDocument" => Collection::FIND_ONE_AND_RETURN_AFTER);
* *
* The document to return may be null. By default, the original document is
* returned. Specify FindOneAndUpdate::RETURN_DOCUMENT_AFTER for the
* "returnDocument" option to return the updated document.
* *
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/ * @see FindOneAndReplace::__construct() for supported options
* @see Collection::getFindOneAndUpdate() for supported $options * @param array|object $filter Query by which to filter documents
* * @param array|object $update Update to apply to the matched document
* @param array $filter The $filter criteria to search for * @param array $options Command options
* @param array $update An array of update operators to apply to the document * @return array|null
* @param array $options Additional options
* @return array
*/ */
public function findOneAndUpdate(array $filter, array $update, array $options = array()) public function findOneAndUpdate($filter, $update, array $options = array())
{ {
$firstKey = key($update); $operation = new FindOneAndUpdate($this->dbname, $this->collname, $filter, $update, $options);
if (!isset($firstKey[0]) || $firstKey[0] != '$') { $server = $this->manager->selectServer(new ReadPreference(ReadPreference::RP_PRIMARY));
throw new InvalidArgumentException("First key in \$update must be a \$operator");
}
$options = array_merge($this->getFindOneAndUpdateOptions(), $options);
$options = $this->_massageFindAndModifyOptions($options, $update);
$cmd = array(
"findandmodify" => $this->collname,
"query" => $filter,
) + $options;
$doc = current($this->_runCommand($this->dbname, $cmd)->toArray());
if ($doc["ok"]) {
return $this->_massageFindAndModifyResult($doc, $options);
}
throw $this->_generateCommandException($doc); return $operation->execute($server);
} }
/** /**
...@@ -583,133 +546,6 @@ class Collection ...@@ -583,133 +546,6 @@ class Collection
return $this->dbname; return $this->dbname;
} }
/**
* Retrieves all findOneDelete options with their default values.
*
* @return array of Collection::findOneAndDelete() options
*/
public function getFindOneAndDeleteOptions()
{
return array(
/**
* The maximum amount of time to allow the query to run.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"maxTimeMS" => 0,
/**
* Limits the fields to return for all matching documents.
*
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
*/
"projection" => array(),
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"sort" => array(),
);
}
/**
* Retrieves all findOneAndReplace options with their default values.
*
* @return array of Collection::findOneAndReplace() options
*/
public function getFindOneAndReplaceOptions()
{
return array(
/**
* The maximum amount of time to allow the query to run.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"maxTimeMS" => 0,
/**
* Limits the fields to return for all matching documents.
*
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
*/
"projection" => array(),
/**
* When ReturnDocument.After, returns the replaced or inserted document rather than the original.
* Defaults to ReturnDocument.Before.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"returnDocument" => self::FIND_ONE_AND_RETURN_BEFORE,
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"sort" => array(),
/**
* When true, findAndModify creates a new document if no document matches the query. The
* default is false.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"upsert" => false,
);
}
/**
* Retrieves all findOneAndUpdate options with their default values.
*
* @return array of Collection::findOneAndUpdate() options
*/
public function getFindOneAndUpdateOptions()
{
return array(
/**
* The maximum amount of time to allow the query to run.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"maxTimeMS" => 0,
/**
* Limits the fields to return for all matching documents.
*
* @see http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results
*/
"projection" => array(),
/**
* When ReturnDocument.After, returns the updated or inserted document rather than the original.
* Defaults to ReturnDocument.Before.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"returnDocument" => self::FIND_ONE_AND_RETURN_BEFORE,
/**
* Determines which document the operation modifies if the query selects multiple documents.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"sort" => array(),
/**
* When true, creates a new document if no document matches the query. The default is false.
*
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
"upsert" => false,
);
}
/** /**
* Retrieves all find options with their default values. * Retrieves all find options with their default values.
* *
...@@ -1025,56 +861,6 @@ class Collection ...@@ -1025,56 +861,6 @@ class Collection
return new RuntimeException("FIXME: Unknown error"); return new RuntimeException("FIXME: Unknown error");
} }
/**
* Internal helper for massaging findandmodify options
* @internal
*/
final protected function _massageFindAndModifyOptions($options, $update = array())
{
$ret = array(
"sort" => $options["sort"],
"new" => isset($options["returnDocument"]) ? $options["returnDocument"] == self::FIND_ONE_AND_RETURN_AFTER : false,
"fields" => $options["projection"],
"upsert" => isset($options["upsert"]) ? $options["upsert"] : false,
);
if ($update) {
$ret["update"] = $update;
} else {
$ret["remove"] = true;
}
return $ret;
}
/**
* Internal helper for massaging the findAndModify result.
*
* @internal
* @param array $result
* @param array $options
* @return array|null
*/
final protected function _massageFindAndModifyResult(array $result, array $options)
{
if ($result['value'] === null) {
return null;
}
/* Prior to 3.0, findAndModify returns an empty document instead of null
* when an upsert is performed and the pre-modified document was
* requested.
*/
if ($options['upsert'] && ! $options['new'] &&
isset($result['lastErrorObject']->updatedExisting) &&
! $result['lastErrorObject']->updatedExisting) {
return null;
}
return is_object($result["value"])
? (array) $result['value']
: $result['value'];
}
/** /**
* Constructs the Query Wire Protocol field 'flags' based on $options * Constructs the Query Wire Protocol field 'flags' based on $options
* provided to other helpers * provided to other helpers
......
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
use MongoDB\Exception\RuntimeException;
use MongoDB\Exception\UnexpectedValueException;
/**
* Operation for the findAndModify command.
*
* This class is used internally by the FindOneAndDelete, FindOneAndReplace, and
* FindOneAndUpdate operation classes.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
class FindAndModify implements Executable
{
private $databaseName;
private $collectionName;
private $options;
/**
* Constructs a findAndModify command.
*
* Supported options:
*
* * fields (document): Limits the fields to return for the matching
* document.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * new (boolean): When true, returns the modified document rather than
* the original. This option is ignored for remove operations. The
* The default is false.
*
* * query (document): Query by which to filter documents.
*
* * remove (boolean): When true, removes the matched document. This option
* cannot be true if the update option is set. The default is false.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
* * update (document): Update or replacement to apply to the matched
* document. This option cannot be set if the remove option is true.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. This option is ignored for remove operations. The
* default is false.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $options Command options
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $collectionName, array $options)
{
$options += array(
'new' => false,
'remove' => false,
'upsert' => false,
);
if (isset($options['fields']) && ! is_array($options['fields']) && ! is_object($options['fields'])) {
throw new InvalidArgumentTypeException('"fields" option', $options['fields'], 'array or object');
}
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if ( ! is_bool($options['new'])) {
throw new InvalidArgumentTypeException('"new" option', $options['new'], 'boolean');
}
if (isset($options['query']) && ! is_array($options['query']) && ! is_object($options['query'])) {
throw new InvalidArgumentTypeException('"query" option', $options['query'], 'array or object');
}
if ( ! is_bool($options['remove'])) {
throw new InvalidArgumentTypeException('"remove" option', $options['remove'], 'boolean');
}
if (isset($options['sort']) && ! is_array($options['sort']) && ! is_object($options['sort'])) {
throw new InvalidArgumentTypeException('"sort" option', $options['sort'], 'array or object');
}
if (isset($options['update']) && ! is_array($options['update']) && ! is_object($options['update'])) {
throw new InvalidArgumentTypeException('"update" option', $options['update'], 'array or object');
}
if ( ! is_bool($options['upsert'])) {
throw new InvalidArgumentTypeException('"upsert" option', $options['upsert'], 'boolean');
}
if ( ! (isset($options['update']) xor $options['remove'])) {
throw new InvalidArgumentException('The "remove" option must be true or an "update" document must be specified, but not both');
}
$this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName;
$this->options = $options;
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|null
*/
public function execute(Server $server)
{
$cursor = $server->executeCommand($this->databaseName, $this->createCommand());
$result = current($cursor->toArray());
if (empty($result['ok'])) {
throw new RuntimeException(isset($result['errmsg']) ? $result['errmsg'] : 'Unknown error');
}
if ( ! isset($result['value'])) {
return null;
}
/* Prior to 3.0, findAndModify returns an empty document instead of null
* when an upsert is performed and the pre-modified document was
* requested.
*/
if ($this->options['upsert'] && ! $this->options['new'] &&
isset($result['lastErrorObject']->updatedExisting) &&
! $result['lastErrorObject']->updatedExisting) {
return null;
}
if ( ! is_object($result['value'])) {
throw new UnexpectedValueException('findAndModify command did not return a "value" document');
}
return (array) $result['value'];
}
/**
* Create the findAndModify command.
*
* @return Command
*/
private function createCommand()
{
$cmd = array(
'findAndModify' => $this->collectionName,
);
if ($this->options['remove']) {
$cmd['remove'] = true;
} else {
$cmd['new'] = $this->options['new'];
$cmd['upsert'] = $this->options['upsert'];
}
foreach (array('fields', 'query', 'sort', 'update') as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = (object) $this->options[$option];
}
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
}
return new Command($cmd);
}
}
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
/**
* Operation for deleting a document with the findAndModify command.
*
* @api
* @see MongoDB\Collection::findOneAndDelete()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
class FindOneAndDelete implements Executable
{
private $findAndModify;
/**
* Constructs a findAndModify command for deleting a document.
*
* Supported options:
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * projection (document): Limits the fields to return for the matching
* document.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array|object $filter Query by which to filter documents
* @param array $options Command options
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $collectionName, $filter, array $options = array())
{
if ( ! is_array($filter) && ! is_object($filter)) {
throw new InvalidArgumentTypeException('$filter', $filter, 'array or object');
}
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['projection']) && ! is_array($options['projection']) && ! is_object($options['projection'])) {
throw new InvalidArgumentTypeException('"projection" option', $options['projection'], 'array or object');
}
if (isset($options['sort']) && ! is_array($options['sort']) && ! is_object($options['sort'])) {
throw new InvalidArgumentTypeException('"sort" option', $options['sort'], 'array or object');
}
$this->findAndModify = new FindAndModify(
$databaseName,
$collectionName,
array(
'fields' => isset($options['projection']) ? $options['projection'] : null,
'maxTimeMS' => isset($options['maxTimeMS']) ? $options['maxTimeMS'] : null,
'query' => $filter,
'remove' => true,
'sort' => isset($options['sort']) ? $options['sort'] : null,
)
);
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|null
*/
public function execute(Server $server)
{
return $this->findAndModify->execute($server);
}
}
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
/**
* Operation for replacing a document with the findAndModify command.
*
* @api
* @see MongoDB\Collection::findOneAndReplace()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
class FindOneAndReplace implements Executable
{
const RETURN_DOCUMENT_BEFORE = 1;
const RETURN_DOCUMENT_AFTER = 2;
private $findAndModify;
/**
* Constructs a findAndModify command for replacing a document.
*
* Supported options:
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * projection (document): Limits the fields to return for the matching
* document.
*
* * returnDocument (enum): Whether to return the document before or after
* the update is applied. Must be either RETURN_DOCUMENT_BEFORE or
* RETURN_DOCUMENT_AFTER. The default is RETURN_DOCUMENT_BEFORE.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array|object $filter Query by which to filter documents
* @param array|object $replacement Replacement document
* @param array $options Command options
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $collectionName, $filter, $replacement, array $options = array())
{
if ( ! is_array($filter) && ! is_object($filter)) {
throw new InvalidArgumentTypeException('$filter', $filter, 'array or object');
}
if ( ! is_array($replacement) && ! is_object($replacement)) {
throw new InvalidArgumentTypeException('$replacement', $replacement, 'array or object');
}
if (\MongoDB\is_first_key_operator($replacement)) {
throw new InvalidArgumentException('First key in $replacement argument is an update operator');
}
$options += array(
'returnDocument' => self::RETURN_DOCUMENT_BEFORE,
'upsert' => false,
);
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['projection']) && ! is_array($options['projection']) && ! is_object($options['projection'])) {
throw new InvalidArgumentTypeException('"projection" option', $options['projection'], 'array or object');
}
if ( ! is_integer($options['returnDocument'])) {
throw new InvalidArgumentTypeException('"returnDocument" option', $options['returnDocument'], 'integer');
}
if ($options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE) {
throw new InvalidArgumentException('Invalid value for "returnDocument" option: ' . $options['returnDocument']);
}
if (isset($options['sort']) && ! is_array($options['sort']) && ! is_object($options['sort'])) {
throw new InvalidArgumentTypeException('"sort" option', $options['sort'], 'array or object');
}
if ( ! is_bool($options['upsert'])) {
throw new InvalidArgumentTypeException('"upsert" option', $options['upsert'], 'boolean');
}
$this->findAndModify = new FindAndModify(
$databaseName,
$collectionName,
array(
'fields' => isset($options['projection']) ? $options['projection'] : null,
'maxTimeMS' => isset($options['maxTimeMS']) ? $options['maxTimeMS'] : null,
'new' => $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER,
'query' => $filter,
'sort' => isset($options['sort']) ? $options['sort'] : null,
'update' => $replacement,
'upsert' => $options['upsert'],
)
);
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|null
*/
public function execute(Server $server)
{
return $this->findAndModify->execute($server);
}
}
<?php
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\InvalidArgumentTypeException;
/**
* Operation for updating a document with the findAndModify command.
*
* @api
* @see MongoDB\Collection::findOneAndUpdate()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
*/
class FindOneAndUpdate implements Executable
{
const RETURN_DOCUMENT_BEFORE = 1;
const RETURN_DOCUMENT_AFTER = 2;
private $findAndModify;
/**
* Constructs a findAndModify command for updating a document.
*
* Supported options:
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * projection (document): Limits the fields to return for the matching
* document.
*
* * returnDocument (enum): Whether to return the document before or after
* the update is applied. Must be either RETURN_DOCUMENT_BEFORE or
* RETURN_DOCUMENT_AFTER. The default is RETURN_DOCUMENT_BEFORE.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array|object $filter Query by which to filter documents
* @param array|object $update Update to apply to the matched document
* @param array $options Command options
* @throws InvalidArgumentException
*/
public function __construct($databaseName, $collectionName, $filter, $update, array $options = array())
{
if ( ! is_array($filter) && ! is_object($filter)) {
throw new InvalidArgumentTypeException('$filter', $filter, 'array or object');
}
if ( ! is_array($update) && ! is_object($update)) {
throw new InvalidArgumentTypeException('$update', $update, 'array or object');
}
if ( ! \MongoDB\is_first_key_operator($update)) {
throw new InvalidArgumentException('First key in $update argument is not an update operator');
}
$options += array(
'returnDocument' => self::RETURN_DOCUMENT_BEFORE,
'upsert' => false,
);
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw new InvalidArgumentTypeException('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['projection']) && ! is_array($options['projection']) && ! is_object($options['projection'])) {
throw new InvalidArgumentTypeException('"projection" option', $options['projection'], 'array or object');
}
if ( ! is_integer($options['returnDocument'])) {
throw new InvalidArgumentTypeException('"returnDocument" option', $options['returnDocument'], 'integer');
}
if ($options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE) {
throw new InvalidArgumentException('Invalid value for "returnDocument" option: ' . $options['returnDocument']);
}
if (isset($options['sort']) && ! is_array($options['sort']) && ! is_object($options['sort'])) {
throw new InvalidArgumentTypeException('"sort" option', $options['sort'], 'array or object');
}
if ( ! is_bool($options['upsert'])) {
throw new InvalidArgumentTypeException('"upsert" option', $options['upsert'], 'boolean');
}
$this->findAndModify = new FindAndModify(
$databaseName,
$collectionName,
array(
'fields' => isset($options['projection']) ? $options['projection'] : null,
'maxTimeMS' => isset($options['maxTimeMS']) ? $options['maxTimeMS'] : null,
'new' => $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER,
'query' => $filter,
'sort' => isset($options['sort']) ? $options['sort'] : null,
'update' => $update,
'upsert' => $options['upsert'],
)
);
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|null
*/
public function execute(Server $server)
{
return $this->findAndModify->execute($server);
}
}
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace MongoDB\Tests\Collection\CrudSpec; namespace MongoDB\Tests\Collection\CrudSpec;
use MongoDB\Collection; use MongoDB\Collection;
use MongoDB\Operation\FindOneAndReplace;
/** /**
* CRUD spec functional tests for findOneAndReplace(). * CRUD spec functional tests for findOneAndReplace().
...@@ -46,7 +47,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase ...@@ -46,7 +47,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndReplace::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndReplace($filter, $replacement, $options); $document = $this->collection->findOneAndReplace($filter, $replacement, $options);
...@@ -89,7 +90,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase ...@@ -89,7 +90,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndReplace::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndReplace($filter, $replacement, $options); $document = $this->collection->findOneAndReplace($filter, $replacement, $options);
...@@ -156,7 +157,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase ...@@ -156,7 +157,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndReplace::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndReplace($filter, $replacement, $options); $document = $this->collection->findOneAndReplace($filter, $replacement, $options);
...@@ -179,7 +180,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase ...@@ -179,7 +180,7 @@ class FindOneAndReplaceFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndReplace::RETURN_DOCUMENT_AFTER,
'upsert' => true, 'upsert' => true,
); );
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
namespace MongoDB\Tests\Collection\CrudSpec; namespace MongoDB\Tests\Collection\CrudSpec;
use MongoDB\Collection; use MongoDB\Collection;
use MongoDB\Operation\FindOneAndUpdate;
/** /**
* CRUD spec functional tests for findOneAndUpdate(). * CRUD spec functional tests for findOneAndUpdate().
...@@ -46,7 +47,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase ...@@ -46,7 +47,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndUpdate($filter, $update, $options); $document = $this->collection->findOneAndUpdate($filter, $update, $options);
...@@ -89,7 +90,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase ...@@ -89,7 +90,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndUpdate($filter, $update, $options); $document = $this->collection->findOneAndUpdate($filter, $update, $options);
...@@ -155,7 +156,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase ...@@ -155,7 +156,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
); );
$document = $this->collection->findOneAndUpdate($filter, $update, $options); $document = $this->collection->findOneAndUpdate($filter, $update, $options);
...@@ -177,7 +178,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase ...@@ -177,7 +178,7 @@ class FindOneAndUpdateFunctionalTest extends FunctionalTestCase
$options = array( $options = array(
'projection' => array('x' => 1, '_id' => 0), 'projection' => array('x' => 1, '_id' => 0),
'sort' => array('x' => 1), 'sort' => array('x' => 1),
'returnDocument' => Collection::FIND_ONE_AND_RETURN_AFTER, 'returnDocument' => FindOneAndUpdate::RETURN_DOCUMENT_AFTER,
'upsert' => true, 'upsert' => true,
); );
......
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