MDL-75481 lib: Updated MongoDB files to 1.13.1

This commit is contained in:
Kevin Percy
2022-10-13 15:22:01 +08:00
parent e4c5a12a1c
commit 8ab37cea82
84 changed files with 2073 additions and 1333 deletions
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
+19 -12
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2017 MongoDB, Inc.
* Copyright 2017-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,8 @@ use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Driver\Exception\ServerException;
use MongoDB\Exception\ResumeTokenException;
use MongoDB\Model\ChangeStreamIterator;
use ReturnTypeWillChange;
use function call_user_func;
use function in_array;
@@ -32,7 +34,7 @@ use function in_array;
*
* @api
* @see \MongoDB\Collection::watch()
* @see http://docs.mongodb.org/manual/reference/command/changeStream/
* @see https://mongodb.com/docs/manual/reference/method/db.watch/#mongodb-method-db.watch
*/
class ChangeStream implements Iterator
{
@@ -40,7 +42,7 @@ class ChangeStream implements Iterator
* @deprecated 1.4
* @todo Remove this in 2.0 (see: PHPLIB-360)
*/
const CURSOR_NOT_FOUND = 43;
public const CURSOR_NOT_FOUND = 43;
/** @var int */
private static $cursorNotFound = 43;
@@ -54,11 +56,11 @@ class ChangeStream implements Iterator
189, // PrimarySteppedDown
262, // ExceededTimeLimit
9001, // SocketException
10107, // NotMaster
10107, // NotPrimary
11600, // InterruptedAtShutdown
11602, // InterruptedDueToReplStateChange
13435, // NotMasterNoSlaveOk
13436, // NotMasterOrSecondary
13435, // NotPrimaryNoSecondaryOk
13436, // NotPrimaryOrSecondary
63, // StaleShardVersion
150, // StaleEpoch
13388, // StaleConfig
@@ -98,9 +100,10 @@ class ChangeStream implements Iterator
}
/**
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->iterator->current();
@@ -129,9 +132,10 @@ class ChangeStream implements Iterator
}
/**
* @see http://php.net/iterator.key
* @see https://php.net/iterator.key
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
if ($this->valid()) {
@@ -142,10 +146,11 @@ class ChangeStream implements Iterator
}
/**
* @see http://php.net/iterator.next
* @see https://php.net/iterator.next
* @return void
* @throws ResumeTokenException
*/
#[ReturnTypeWillChange]
public function next()
{
try {
@@ -157,10 +162,11 @@ class ChangeStream implements Iterator
}
/**
* @see http://php.net/iterator.rewind
* @see https://php.net/iterator.rewind
* @return void
* @throws ResumeTokenException
*/
#[ReturnTypeWillChange]
public function rewind()
{
try {
@@ -175,9 +181,10 @@ class ChangeStream implements Iterator
}
/**
* @see http://php.net/iterator.valid
* @see https://php.net/iterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->iterator->valid();
+17 -22
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -38,6 +38,7 @@ use MongoDB\Operation\ListDatabaseNames;
use MongoDB\Operation\ListDatabases;
use MongoDB\Operation\Watch;
use Throwable;
use function is_array;
use function is_string;
@@ -50,12 +51,6 @@ class Client
'root' => BSONDocument::class,
];
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForWritableCommandWriteConcern = 5;
/** @var string */
private static $handshakeSeparator = ' / ';
@@ -93,9 +88,9 @@ class Client
*
* Other options are documented in MongoDB\Driver\Manager::__construct().
*
* @see http://docs.mongodb.org/manual/reference/connection-string/
* @see http://php.net/manual/en/mongodb-driver-manager.construct.php
* @see http://php.net/manual/en/mongodb.persistence.php#mongodb.persistence.typemaps
* @see https://mongodb.com/docs/manual/reference/connection-string/
* @see https://php.net/manual/en/mongodb-driver-manager.construct.php
* @see https://php.net/manual/en/mongodb.persistence.php#mongodb.persistence.typemaps
* @param string $uri MongoDB connection string
* @param array $uriOptions Additional connection string options
* @param array $driverOptions Driver-specific options
@@ -135,7 +130,7 @@ class Client
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -155,8 +150,8 @@ class Client
* be selected with complex syntax (e.g. $client->{"that-database"}) or
* {@link selectDatabase()}.
*
* @see http://php.net/oop5.overloading#object.get
* @see http://php.net/types.string#language.types.string.parsing.complex
* @see https://php.net/oop5.overloading#object.get
* @see https://php.net/types.string#language.types.string.parsing.complex
* @param string $databaseName Name of the database to select
* @return Database
*/
@@ -214,7 +209,7 @@ class Client
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -236,7 +231,7 @@ class Client
/**
* Return the read concern for this client.
*
* @see http://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @return ReadConcern
*/
public function getReadConcern()
@@ -267,7 +262,7 @@ class Client
/**
* Return the write concern for this client.
*
* @see http://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @return WriteConcern
*/
public function getWriteConcern()
@@ -283,7 +278,7 @@ class Client
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function listDatabaseNames(array $options = []) : Iterator
public function listDatabaseNames(array $options = []): Iterator
{
$operation = new ListDatabaseNames($options);
$server = select_server($this->manager, $options);
@@ -345,7 +340,7 @@ class Client
/**
* Start a new client session.
*
* @see http://php.net/manual/en/mongodb-driver-manager.startsession.php
* @see https://php.net/manual/en/mongodb-driver-manager.startsession.php
* @param array $options Session options
* @return Session
*/
@@ -371,7 +366,7 @@ class Client
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -384,7 +379,7 @@ class Client
return $operation->execute($server);
}
private static function getVersion() : string
private static function getVersion(): string
{
if (self::$version === null) {
try {
@@ -397,7 +392,7 @@ class Client
return self::$version;
}
private function mergeDriverInfo(array $driver) : array
private function mergeDriverInfo(array $driver): array
{
$mergedDriver = [
'name' => 'PHPLIB',
+97 -61
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -53,11 +53,13 @@ use MongoDB\Operation\InsertMany;
use MongoDB\Operation\InsertOne;
use MongoDB\Operation\ListIndexes;
use MongoDB\Operation\MapReduce;
use MongoDB\Operation\RenameCollection;
use MongoDB\Operation\ReplaceOne;
use MongoDB\Operation\UpdateMany;
use MongoDB\Operation\UpdateOne;
use MongoDB\Operation\Watch;
use Traversable;
use function array_diff_key;
use function array_intersect_key;
use function current;
@@ -73,15 +75,6 @@ class Collection
'root' => BSONDocument::class,
];
/** @var integer */
private static $wireVersionForFindAndModifyWriteConcern = 4;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForWritableCommandWriteConcern = 5;
/** @var integer */
private static $wireVersionForReadConcernWithWriteStage = 8;
@@ -135,11 +128,11 @@ class Collection
*/
public function __construct(Manager $manager, $databaseName, $collectionName, array $options = [])
{
if (strlen($databaseName) < 1) {
if (strlen((string) $databaseName) < 1) {
throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName);
}
if (strlen($collectionName) < 1) {
if (strlen((string) $collectionName) < 1) {
throw new InvalidArgumentException('$collectionName is invalid: ' . $collectionName);
}
@@ -171,7 +164,7 @@ class Collection
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -190,7 +183,7 @@ class Collection
/**
* Return the collection namespace (e.g. "db.collection").
*
* @see https://docs.mongodb.org/manual/faq/developers/#faq-dev-namespace
* @see https://mongodb.com/docs/manual/core/databases-and-collections/
* @return string
*/
public function __toString()
@@ -223,19 +216,17 @@ class Collection
$options['readPreference'] = $this->readPreference;
}
if ($hasWriteStage) {
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
}
$server = select_server($this->manager, $options);
$server = $hasWriteStage
? select_server_for_aggregate_write_stage($this->manager, $options)
: select_server($this->manager, $options);
/* MongoDB 4.2 and later supports a read concern when an $out stage is
* being used, but earlier versions do not.
*
* A read concern is also not compatible with transactions.
*/
if (! isset($options['readConcern']) &&
server_supports_feature($server, self::$wireVersionForReadConcern) &&
if (
! isset($options['readConcern']) &&
! is_in_transaction($options) &&
( ! $hasWriteStage || server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
) {
@@ -246,10 +237,7 @@ class Collection
$options['typeMap'] = $this->typeMap;
}
if ($hasWriteStage &&
! isset($options['writeConcern']) &&
server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) &&
! is_in_transaction($options)) {
if ($hasWriteStage && ! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -303,7 +291,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -332,7 +320,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -380,8 +368,8 @@ class Collection
* If the "name" option is unspecified, a name will be generated from the
* "key" document.
*
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
* @see https://mongodb.com/docs/manual/reference/command/createIndexes/
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createIndex/
* @see CreateIndexes::__construct() for supported command options
* @param array[] $indexes List of index specifications
* @param array $options Command options
@@ -394,7 +382,7 @@ class Collection
{
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -407,7 +395,7 @@ class Collection
* Deletes all documents matching the filter.
*
* @see DeleteMany::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/delete/
* @see https://mongodb.com/docs/manual/reference/command/delete/
* @param array|object $filter Query by which to delete documents
* @param array $options Command options
* @return DeleteResult
@@ -431,7 +419,7 @@ class Collection
* Deletes at most one document matching the filter.
*
* @see DeleteOne::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/delete/
* @see https://mongodb.com/docs/manual/reference/command/delete/
* @param array|object $filter Query by which to delete documents
* @param array $options Command options
* @return DeleteResult
@@ -476,7 +464,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -503,10 +491,25 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
$encryptedFields = $options['encryptedFields']
?? get_encrypted_fields_from_driver($this->databaseName, $this->collectionName, $this->manager)
?? get_encrypted_fields_from_server($this->databaseName, $this->collectionName, $this->manager, $server)
?? null;
if ($encryptedFields !== null) {
// encryptedFields is not passed to the drop command
unset($options['encryptedFields']);
$encryptedFields = (array) $encryptedFields;
(new DropCollection($this->databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $this->collectionName . '.esc'))->execute($server);
(new DropCollection($this->databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $this->collectionName . '.ecc'))->execute($server);
(new DropCollection($this->databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $this->collectionName . '.ecoc'))->execute($server);
}
$operation = new DropCollection($this->databaseName, $this->collectionName, $options);
return $operation->execute($server);
@@ -537,7 +540,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -564,7 +567,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -592,7 +595,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -605,7 +608,7 @@ class Collection
* Explains explainable commands.
*
* @see Explain::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/explain/
* @see https://mongodb.com/docs/manual/reference/command/explain/
* @param Explainable $explainable Command on which to run explain
* @param array $options Additional options
* @return array|object
@@ -634,7 +637,7 @@ class Collection
* Finds documents matching the query.
*
* @see Find::__construct() for supported options
* @see http://docs.mongodb.org/manual/core/read-operations-introduction/
* @see https://mongodb.com/docs/manual/crud/#read-operations
* @param array|object $filter Query by which to filter documents
* @param array $options Additional options
* @return Cursor
@@ -650,7 +653,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -667,7 +670,7 @@ class Collection
* Finds a single document matching the query.
*
* @see FindOne::__construct() for supported options
* @see http://docs.mongodb.org/manual/core/read-operations-introduction/
* @see https://mongodb.com/docs/manual/crud/#read-operations
* @param array|object $filter Query by which to filter documents
* @param array $options Additional options
* @return array|object|null
@@ -683,7 +686,7 @@ class Collection
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -702,7 +705,7 @@ class Collection
* The document to return may be null if no document matched the filter.
*
* @see FindOneAndDelete::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
* @param array|object $filter Query by which to filter documents
* @param array $options Command options
* @return array|object|null
@@ -715,7 +718,7 @@ class Collection
{
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForFindAndModifyWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -738,7 +741,7 @@ class Collection
* to return the updated document.
*
* @see FindOneAndReplace::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
* @param array|object $filter Query by which to filter documents
* @param array|object $replacement Replacement document
* @param array $options Command options
@@ -752,7 +755,7 @@ class Collection
{
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForFindAndModifyWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -775,7 +778,7 @@ class Collection
* to return the updated document.
*
* @see FindOneAndReplace::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
* @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
@@ -789,7 +792,7 @@ class Collection
{
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForFindAndModifyWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -835,7 +838,7 @@ class Collection
/**
* Return the collection namespace.
*
* @see https://docs.mongodb.org/manual/reference/glossary/#term-namespace
* @see https://mongodb.com/docs/manual/reference/glossary/#term-namespace
* @return string
*/
public function getNamespace()
@@ -846,7 +849,7 @@ class Collection
/**
* Return the read concern for this collection.
*
* @see http://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @return ReadConcern
*/
public function getReadConcern()
@@ -877,7 +880,7 @@ class Collection
/**
* Return the write concern for this collection.
*
* @see http://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @return WriteConcern
*/
public function getWriteConcern()
@@ -889,7 +892,7 @@ class Collection
* Inserts multiple documents.
*
* @see InsertMany::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/insert/
* @see https://mongodb.com/docs/manual/reference/command/insert/
* @param array[]|object[] $documents The documents to insert
* @param array $options Command options
* @return InsertManyResult
@@ -912,7 +915,7 @@ class Collection
* Inserts one document.
*
* @see InsertOne::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/insert/
* @see https://mongodb.com/docs/manual/reference/command/insert/
* @param array|object $document The document to insert
* @param array $options Command options
* @return InsertOneResult
@@ -952,7 +955,7 @@ class Collection
* Executes a map-reduce aggregation on the collection.
*
* @see MapReduce::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/mapReduce/
* @see https://mongodb.com/docs/manual/reference/command/mapReduce/
* @param JavascriptInterface $map Map function
* @param JavascriptInterface $reduce Reduce function
* @param string|array|object $out Output specification
@@ -983,7 +986,7 @@ class Collection
*
* A read concern is also not compatible with transactions.
*/
if (! isset($options['readConcern']) && ! ($hasOutputCollection && $this->readConcern->getLevel() === ReadConcern::MAJORITY) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! ($hasOutputCollection && $this->readConcern->getLevel() === ReadConcern::MAJORITY) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
@@ -991,7 +994,7 @@ class Collection
$options['typeMap'] = $this->typeMap;
}
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -1000,11 +1003,44 @@ class Collection
return $operation->execute($server);
}
/**
* Renames the collection.
*
* @see RenameCollection::__construct() for supported options
* @param string $toCollectionName New name of the collection
* @param ?string $toDatabaseName New database name of the collection. Defaults to the original database.
* @param array $options Additional options
* @return array|object Command result document
* @throws UnsupportedException if options are not supported by the selected server
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function rename(string $toCollectionName, ?string $toDatabaseName = null, array $options = [])
{
if (! isset($toDatabaseName)) {
$toDatabaseName = $this->databaseName;
}
if (! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new RenameCollection($this->databaseName, $this->collectionName, $toDatabaseName, $toCollectionName, $options);
return $operation->execute($server);
}
/**
* Replaces at most one document matching the filter.
*
* @see ReplaceOne::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
* @param array|object $filter Query by which to filter documents
* @param array|object $replacement Replacement document
* @param array $options Command options
@@ -1029,7 +1065,7 @@ class Collection
* Updates all documents matching the filter.
*
* @see UpdateMany::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
* @param array|object $filter Query by which to filter documents
* @param array|object $update Update to apply to the matched documents
* @param array $options Command options
@@ -1054,7 +1090,7 @@ class Collection
* Updates at most one document matching the filter.
*
* @see UpdateOne::__construct() for supported options
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
* @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
@@ -1099,7 +1135,7 @@ class Collection
* related to change streams being unsupported instead of an
* UnsupportedException regarding use of the "readConcern" option from
* the Aggregate operation class. */
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
+35 -15
View File
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,7 @@ use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Model\CachingIterator;
use MongoDB\Operation\Executable;
use function is_array;
use function is_bool;
use function is_integer;
@@ -33,7 +34,7 @@ use function is_object;
* Wrapper for the listCollections command.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/listCollections/
* @see https://mongodb.com/docs/manual/reference/command/listCollections/
*/
class ListCollections implements Executable
{
@@ -48,6 +49,15 @@ class ListCollections implements Executable
*
* Supported options:
*
* * authorizedCollections (boolean): Determines which collections are
* returned based on the user privileges.
*
* For servers < 4.0, this option is ignored.
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter collections.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
@@ -59,14 +69,16 @@ class ListCollections implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param string $databaseName Database name
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
*/
public function __construct($databaseName, array $options = [])
{
if (isset($options['authorizedCollections']) && ! is_bool($options['authorizedCollections'])) {
throw InvalidArgumentException::invalidType('"authorizedCollections" option', $options['authorizedCollections'], 'boolean');
}
if (isset($options['filter']) && ! is_array($options['filter']) && ! is_object($options['filter'])) {
throw InvalidArgumentException::invalidType('"filter" option', $options['filter'], 'array or object');
}
@@ -96,6 +108,19 @@ class ListCollections implements Executable
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
$cursor = $server->executeReadCommand($this->databaseName, $this->createCommand(), $this->createOptions());
$cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
return new CachingIterator($cursor);
}
/**
* Create the listCollections command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['listCollections' => 1];
@@ -103,18 +128,13 @@ class ListCollections implements Executable
$cmd['filter'] = (object) $this->options['filter'];
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
foreach (['authorizedCollections', 'comment', 'maxTimeMS', 'nameOnly'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
if (isset($this->options['nameOnly'])) {
$cmd['nameOnly'] = $this->options['nameOnly'];
}
$cursor = $server->executeReadCommand($this->databaseName, new Command($cmd), $this->createOptions());
$cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
return new CachingIterator($cursor);
return new Command($cmd);
}
/**
@@ -123,7 +143,7 @@ class ListCollections implements Executable
* Note: read preference is intentionally omitted, as the spec requires that
* the command be executed on the primary.
*
* @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @return array
*/
private function createOptions()
+31 -26
View File
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,7 @@ use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Operation\Executable;
use function current;
use function is_array;
use function is_bool;
@@ -34,7 +35,7 @@ use function is_object;
* Wrapper for the ListDatabases command.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/listDatabases/
* @see https://mongodb.com/docs/manual/reference/command/listDatabases/
*/
class ListDatabases implements Executable
{
@@ -51,9 +52,11 @@ class ListDatabases implements Executable
*
* For servers < 4.0.5, this option is ignored.
*
* * filter (document): Query by which to filter databases.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* For servers < 3.6, this option is ignored.
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter databases.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
@@ -64,8 +67,6 @@ class ListDatabases implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
*/
@@ -105,25 +106,7 @@ class ListDatabases implements Executable
*/
public function execute(Server $server)
{
$cmd = ['listDatabases' => 1];
if (isset($this->options['authorizedDatabases'])) {
$cmd['authorizedDatabases'] = $this->options['authorizedDatabases'];
}
if (! empty($this->options['filter'])) {
$cmd['filter'] = (object) $this->options['filter'];
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
}
if (isset($this->options['nameOnly'])) {
$cmd['nameOnly'] = $this->options['nameOnly'];
}
$cursor = $server->executeReadCommand('admin', new Command($cmd), $this->createOptions());
$cursor = $server->executeReadCommand('admin', $this->createCommand(), $this->createOptions());
$cursor->setTypeMap(['root' => 'array', 'document' => 'array']);
$result = current($cursor->toArray());
@@ -134,13 +117,35 @@ class ListDatabases implements Executable
return $result['databases'];
}
/**
* Create the listDatabases command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['listDatabases' => 1];
if (! empty($this->options['filter'])) {
$cmd['filter'] = (object) $this->options['filter'];
}
foreach (['authorizedDatabases', 'comment', 'maxTimeMS', 'nameOnly'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* Note: read preference is intentionally omitted, as the spec requires that
* the command be executed on the primary.
*
* @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @return array
*/
private function createOptions()
+94 -32
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -33,14 +33,17 @@ use MongoDB\Model\BSONDocument;
use MongoDB\Model\CollectionInfoIterator;
use MongoDB\Operation\Aggregate;
use MongoDB\Operation\CreateCollection;
use MongoDB\Operation\CreateIndexes;
use MongoDB\Operation\DatabaseCommand;
use MongoDB\Operation\DropCollection;
use MongoDB\Operation\DropDatabase;
use MongoDB\Operation\ListCollectionNames;
use MongoDB\Operation\ListCollections;
use MongoDB\Operation\ModifyCollection;
use MongoDB\Operation\RenameCollection;
use MongoDB\Operation\Watch;
use Traversable;
use function is_array;
use function strlen;
@@ -53,12 +56,6 @@ class Database
'root' => BSONDocument::class,
];
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForWritableCommandWriteConcern = 5;
/** @var integer */
private static $wireVersionForReadConcernWithWriteStage = 8;
@@ -109,7 +106,7 @@ class Database
*/
public function __construct(Manager $manager, $databaseName, array $options = [])
{
if (strlen($databaseName) < 1) {
if (strlen((string) $databaseName) < 1) {
throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName);
}
@@ -140,7 +137,7 @@ class Database
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -162,8 +159,8 @@ class Database
* be selected with complex syntax (e.g. $database->{"system.profile"}) or
* {@link selectCollection()}.
*
* @see http://php.net/oop5.overloading#object.get
* @see http://php.net/types.string#language.types.string.parsing.complex
* @see https://php.net/oop5.overloading#object.get
* @see https://php.net/types.string#language.types.string.parsing.complex
* @param string $collectionName Name of the collection to select
* @return Collection
*/
@@ -204,19 +201,17 @@ class Database
$options['readPreference'] = $this->readPreference;
}
if ($hasWriteStage) {
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
}
$server = select_server($this->manager, $options);
$server = $hasWriteStage
? select_server_for_aggregate_write_stage($this->manager, $options)
: select_server($this->manager, $options);
/* MongoDB 4.2 and later supports a read concern when an $out stage is
* being used, but earlier versions do not.
*
* A read concern is also not compatible with transactions.
*/
if (! isset($options['readConcern']) &&
server_supports_feature($server, self::$wireVersionForReadConcern) &&
if (
! isset($options['readConcern']) &&
! is_in_transaction($options) &&
( ! $hasWriteStage || server_supports_feature($server, self::$wireVersionForReadConcernWithWriteStage))
) {
@@ -227,10 +222,7 @@ class Database
$options['typeMap'] = $this->typeMap;
}
if ($hasWriteStage &&
! isset($options['writeConcern']) &&
server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) &&
! is_in_transaction($options)) {
if ($hasWriteStage && ! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -280,13 +272,34 @@ class Database
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
$encryptedFields = $options['encryptedFields']
?? get_encrypted_fields_from_driver($this->databaseName, $collectionName, $this->manager)
?? null;
if ($encryptedFields !== null) {
// encryptedFields is passed to the create command
$options['encryptedFields'] = $encryptedFields;
$encryptedFields = (array) $encryptedFields;
$enxcolOptions = ['clusteredIndex' => ['key' => ['_id' => 1], 'unique' => true]];
(new CreateCollection($this->databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $collectionName . '.esc', $enxcolOptions))->execute($server);
(new CreateCollection($this->databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $collectionName . '.ecc', $enxcolOptions))->execute($server);
(new CreateCollection($this->databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $collectionName . '.ecoc', $enxcolOptions))->execute($server);
}
$operation = new CreateCollection($this->databaseName, $collectionName, $options);
return $operation->execute($server);
$result = $operation->execute($server);
if ($encryptedFields !== null) {
(new CreateIndexes($this->databaseName, $collectionName, [['key' => ['__safeContent__' => 1]]]))->execute($server);
}
return $result;
}
/**
@@ -307,7 +320,7 @@ class Database
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -335,10 +348,25 @@ class Database
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
$encryptedFields = $options['encryptedFields']
?? get_encrypted_fields_from_driver($this->databaseName, $collectionName, $this->manager)
?? get_encrypted_fields_from_server($this->databaseName, $collectionName, $this->manager, $server)
?? null;
if ($encryptedFields !== null) {
// encryptedFields is not passed to the drop command
unset($options['encryptedFields']);
$encryptedFields = (array) $encryptedFields;
(new DropCollection($this->databaseName, $encryptedFields['escCollection'] ?? 'enxcol_.' . $collectionName . '.esc'))->execute($server);
(new DropCollection($this->databaseName, $encryptedFields['eccCollection'] ?? 'enxcol_.' . $collectionName . '.ecc'))->execute($server);
(new DropCollection($this->databaseName, $encryptedFields['ecocCollection'] ?? 'enxcol_.' . $collectionName . '.ecoc'))->execute($server);
}
$operation = new DropCollection($this->databaseName, $collectionName, $options);
return $operation->execute($server);
@@ -367,7 +395,7 @@ class Database
/**
* Return the read concern for this database.
*
* @see http://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @return ReadConcern
*/
public function getReadConcern()
@@ -398,7 +426,7 @@ class Database
/**
* Return the write concern for this database.
*
* @see http://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @return WriteConcern
*/
public function getWriteConcern()
@@ -413,7 +441,7 @@ class Database
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function listCollectionNames(array $options = []) : Iterator
public function listCollectionNames(array $options = []): Iterator
{
$operation = new ListCollectionNames($this->databaseName, $options);
$server = select_server($this->manager, $options);
@@ -457,7 +485,7 @@ class Database
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && server_supports_feature($server, self::$wireVersionForWritableCommandWriteConcern) && ! is_in_transaction($options)) {
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
@@ -466,6 +494,40 @@ class Database
return $operation->execute($server);
}
/**
* Rename a collection within this database.
*
* @see RenameCollection::__construct() for supported options
* @param string $fromCollectionName Collection name
* @param string $toCollectionName New name of the collection
* @param ?string $toDatabaseName New database name of the collection. Defaults to the original database.
* @param array $options Additional options
* @return array|object Command result document
* @throws UnsupportedException if options are unsupported on the selected server
* @throws InvalidArgumentException for parameter/option parsing errors
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function renameCollection(string $fromCollectionName, string $toCollectionName, ?string $toDatabaseName = null, array $options = [])
{
if (! isset($toDatabaseName)) {
$toDatabaseName = $this->databaseName;
}
if (! isset($options['typeMap'])) {
$options['typeMap'] = $this->typeMap;
}
$server = select_server($this->manager, $options);
if (! isset($options['writeConcern']) && ! is_in_transaction($options)) {
$options['writeConcern'] = $this->writeConcern;
}
$operation = new RenameCollection($this->databaseName, $fromCollectionName, $toDatabaseName, $toCollectionName, $options);
return $operation->execute($server);
}
/**
* Select a collection within this database.
*
@@ -524,7 +586,7 @@ class Database
$server = select_server($this->manager, $options);
if (! isset($options['readConcern']) && server_supports_feature($server, self::$wireVersionForReadConcern) && ! is_in_transaction($options)) {
if (! isset($options['readConcern']) && ! is_in_transaction($options)) {
$options['readConcern'] = $this->readConcern;
}
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Exception;
use BadMethodCallException as BaseBadMethodCallException;
use function sprintf;
class BadMethodCallException extends BaseBadMethodCallException implements Exception
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Exception;
use MongoDB\Driver\Exception\InvalidArgumentException as DriverInvalidArgumentException;
use function array_pop;
use function count;
use function get_debug_type;
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -32,6 +32,9 @@ class UnsupportedException extends RuntimeException
/**
* Thrown when array filters are not supported by a server.
*
* @deprecated 1.12
* @todo Remove this in 2.0 (see: PHPLIB-797)
*
* @return self
*/
public static function arrayFiltersNotSupported()
@@ -42,6 +45,9 @@ class UnsupportedException extends RuntimeException
/**
* Thrown when collations are not supported by a server.
*
* @deprecated 1.12
* @todo Remove this in 2.0 (see: PHPLIB-797)
*
* @return self
*/
public static function collationNotSupported()
+7 -5
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -33,6 +33,7 @@ use MongoDB\Model\BSONArray;
use MongoDB\Model\BSONDocument;
use MongoDB\Operation\Find;
use stdClass;
use function array_intersect_key;
use function fopen;
use function get_resource_type;
@@ -195,7 +196,7 @@ class Bucket
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -433,7 +434,7 @@ class Bucket
/**
* Return the read concern for this GridFS bucket.
*
* @see http://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-readconcern.isdefault.php
* @return ReadConcern
*/
public function getReadConcern()
@@ -464,7 +465,7 @@ class Bucket
/**
* Return the write concern for this GridFS bucket.
*
* @see http://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @see https://php.net/manual/en/mongodb-driver-writeconcern.isdefault.php
* @return WriteConcern
*/
public function getWriteConcern()
@@ -629,6 +630,7 @@ class Bucket
if (@stream_copy_to_stream($source, $destination) === false) {
$destinationUri = $this->createPathForFile($this->getRawFileDocumentForStream($destination));
throw StreamException::uploadFailed($filename, $source, $destinationUri);
}
+6 -5
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,6 +26,7 @@ use MongoDB\Exception\InvalidArgumentException;
use MongoDB\UpdateResult;
use MultipleIterator;
use stdClass;
use function abs;
use function count;
use function is_numeric;
@@ -342,7 +343,7 @@ class CollectionWrapper
$this->ensureChunksIndex();
}
private function indexKeysMatch(array $expectedKeys, array $actualKeys) : bool
private function indexKeysMatch(array $expectedKeys, array $actualKeys): bool
{
if (count($expectedKeys) !== count($actualKeys)) {
return false;
@@ -353,8 +354,8 @@ class CollectionWrapper
$iterator->attachIterator(new ArrayIterator($actualKeys));
foreach ($iterator as $key => $value) {
list($expectedKey, $actualKey) = $key;
list($expectedValue, $actualValue) = $value;
[$expectedKey, $actualKey] = $key;
[$expectedValue, $actualValue] = $value;
if ($expectedKey !== $actualKey) {
return false;
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\GridFS\Exception;
use MongoDB\Exception\RuntimeException;
use function sprintf;
class CorruptFileException extends RuntimeException
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\GridFS\Exception;
use MongoDB\Exception\RuntimeException;
use function MongoDB\BSON\fromPHP;
use function MongoDB\BSON\toJSON;
use function sprintf;
@@ -3,6 +3,7 @@
namespace MongoDB\GridFS\Exception;
use MongoDB\Exception\RuntimeException;
use function MongoDB\BSON\fromPHP;
use function MongoDB\BSON\toJSON;
use function sprintf;
@@ -14,7 +15,7 @@ class StreamException extends RuntimeException
* @param resource $source
* @param resource $destination
*/
public static function downloadFromFilenameFailed(string $filename, $source, $destination) : self
public static function downloadFromFilenameFailed(string $filename, $source, $destination): self
{
$sourceMetadata = stream_get_meta_data($source);
$destinationMetadata = stream_get_meta_data($destination);
@@ -27,7 +28,7 @@ class StreamException extends RuntimeException
* @param resource $source
* @param resource $destination
*/
public static function downloadFromIdFailed($id, $source, $destination) : self
public static function downloadFromIdFailed($id, $source, $destination): self
{
$idString = toJSON(fromPHP(['_id' => $id]));
$sourceMetadata = stream_get_meta_data($source);
@@ -37,7 +38,7 @@ class StreamException extends RuntimeException
}
/** @param resource $source */
public static function uploadFailed(string $filename, $source, string $destinationUri) : self
public static function uploadFailed(string $filename, $source, string $destinationUri): self
{
$sourceMetadata = stream_get_meta_data($source);
+8 -9
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,10 +17,11 @@
namespace MongoDB\GridFS;
use IteratorIterator;
use MongoDB\Driver\CursorInterface;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\GridFS\Exception\CorruptFileException;
use stdClass;
use function ceil;
use function floor;
use function is_integer;
@@ -48,7 +49,7 @@ class ReadableStream
/** @var integer */
private $chunkOffset = 0;
/** @var IteratorIterator|null */
/** @var CursorInterface|null */
private $chunksIterator;
/** @var CollectionWrapper */
@@ -95,14 +96,14 @@ class ReadableStream
if ($this->length > 0) {
$this->numChunks = (integer) ceil($this->length / $this->chunkSize);
$this->expectedLastChunkSize = ($this->length - (($this->numChunks - 1) * $this->chunkSize));
$this->expectedLastChunkSize = $this->length - (($this->numChunks - 1) * $this->chunkSize);
}
}
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -315,9 +316,7 @@ class ReadableStream
*/
private function initChunksIterator()
{
$cursor = $this->collectionWrapper->findChunksByFileId($this->file->_id, $this->chunkOffset);
$this->chunksIterator = new IteratorIterator($cursor);
$this->chunksIterator = $this->collectionWrapper->findChunksByFileId($this->file->_id, $this->chunkOffset);
$this->chunksIterator->rewind();
}
}
+14 -29
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,18 +19,15 @@ namespace MongoDB\GridFS;
use MongoDB\BSON\UTCDateTime;
use stdClass;
use Throwable;
use function explode;
use function get_class;
use function in_array;
use function is_integer;
use function sprintf;
use function stream_context_get_options;
use function stream_get_wrappers;
use function stream_wrapper_register;
use function stream_wrapper_unregister;
use function trigger_error;
use const E_USER_WARNING;
use const SEEK_CUR;
use const SEEK_END;
use const SEEK_SET;
@@ -92,7 +89,7 @@ class StreamWrapper
/**
* Closes the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-close.php
* @see https://php.net/manual/en/streamwrapper.stream-close.php
*/
public function stream_close()
{
@@ -106,7 +103,7 @@ class StreamWrapper
/**
* Returns whether the file pointer is at the end of the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-eof.php
* @see https://php.net/manual/en/streamwrapper.stream-eof.php
* @return boolean
*/
public function stream_eof()
@@ -121,7 +118,7 @@ class StreamWrapper
/**
* Opens the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-open.php
* @see https://php.net/manual/en/streamwrapper.stream-open.php
* @param string $path Path to the file resource
* @param string $mode Mode used to open the file (only "r" and "w" are supported)
* @param integer $options Additional flags set by the streams API
@@ -150,7 +147,7 @@ class StreamWrapper
* Note: this method may return a string smaller than the requested length
* if data is not available to be read.
*
* @see http://php.net/manual/en/streamwrapper.stream-read.php
* @see https://php.net/manual/en/streamwrapper.stream-read.php
* @param integer $length Number of bytes to read
* @return string
*/
@@ -160,19 +157,13 @@ class StreamWrapper
return '';
}
try {
return $this->stream->readBytes($length);
} catch (Throwable $e) {
trigger_error(sprintf('%s: %s', get_class($e), $e->getMessage()), E_USER_WARNING);
return false;
}
return $this->stream->readBytes($length);
}
/**
* Return the current position of the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-seek.php
* @see https://php.net/manual/en/streamwrapper.stream-seek.php
* @param integer $offset Stream offset to seek to
* @param integer $whence One of SEEK_SET, SEEK_CUR, or SEEK_END
* @return boolean True if the position was updated and false otherwise
@@ -206,7 +197,7 @@ class StreamWrapper
/**
* Return information about the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-stat.php
* @see https://php.net/manual/en/streamwrapper.stream-stat.php
* @return array
*/
public function stream_stat()
@@ -236,7 +227,7 @@ class StreamWrapper
/**
* Return the current position of the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-tell.php
* @see https://php.net/manual/en/streamwrapper.stream-tell.php
* @return integer The current position of the stream
*/
public function stream_tell()
@@ -247,7 +238,7 @@ class StreamWrapper
/**
* Write bytes to the stream.
*
* @see http://php.net/manual/en/streamwrapper.stream-write.php
* @see https://php.net/manual/en/streamwrapper.stream-write.php
* @param string $data Data to write
* @return integer The number of bytes written
*/
@@ -257,13 +248,7 @@ class StreamWrapper
return 0;
}
try {
return $this->stream->writeBytes($data);
} catch (Throwable $e) {
trigger_error(sprintf('%s: %s', get_class($e), $e->getMessage()), E_USER_WARNING);
return false;
}
return $this->stream->writeBytes($data);
}
/**
+7 -3
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2016-2017 MongoDB, Inc.
* Copyright 2016-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,6 +23,7 @@ use MongoDB\BSON\UTCDateTime;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Exception\InvalidArgumentException;
use stdClass;
use function array_intersect_key;
use function hash_final;
use function hash_init;
@@ -152,7 +153,7 @@ class WritableStream
/**
* Return internal properties for debugging purposes.
*
* @see http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @see https://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -261,6 +262,9 @@ class WritableStream
$this->isClosed = true;
}
/**
* @return mixed
*/
private function fileCollectionInsert()
{
$this->file['length'] = $this->length;
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
+7 -4
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2017 MongoDB, Inc.
* Copyright 2017-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,8 +18,10 @@
namespace MongoDB;
use IteratorAggregate;
use ReturnTypeWillChange;
use stdClass;
use Traversable;
use function call_user_func;
/**
@@ -31,7 +33,7 @@ use function call_user_func;
*
* @api
* @see \MongoDB\Collection::mapReduce()
* @see https://docs.mongodb.com/manual/reference/command/mapReduce/
* @see https://mongodb.com/docs/manual/reference/command/mapReduce/
*/
class MapReduceResult implements IteratorAggregate
{
@@ -83,9 +85,10 @@ class MapReduceResult implements IteratorAggregate
/**
* Return the mapReduce results as a Traversable.
*
* @see http://php.net/iteratoraggregate.getiterator
* @see https://php.net/iteratoraggregate.getiterator
* @return Traversable
*/
#[ReturnTypeWillChange]
public function getIterator()
{
return call_user_func($this->getIterator);
+9 -6
View File
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,8 @@ use ArrayObject;
use JsonSerializable;
use MongoDB\BSON\Serializable;
use MongoDB\BSON\Unserializable;
use ReturnTypeWillChange;
use function array_values;
use function MongoDB\recursive_copy;
@@ -47,8 +49,8 @@ class BSONArray extends ArrayObject implements JsonSerializable, Serializable, U
/**
* Factory method for var_export().
*
* @see http://php.net/oop5.magic#object.set-state
* @see http://php.net/var-export
* @see https://php.net/oop5.magic#object.set-state
* @see https://php.net/var-export
* @param array $properties
* @return self
*/
@@ -66,7 +68,7 @@ class BSONArray extends ArrayObject implements JsonSerializable, Serializable, U
* The array data will be numerically reindexed to ensure that it is stored
* as a BSON array.
*
* @see http://php.net/mongodb-bson-serializable.bsonserialize
* @see https://php.net/mongodb-bson-serializable.bsonserialize
* @return array
*/
public function bsonSerialize()
@@ -77,7 +79,7 @@ class BSONArray extends ArrayObject implements JsonSerializable, Serializable, U
/**
* Unserialize the document to BSON.
*
* @see http://php.net/mongodb-bson-unserializable.bsonunserialize
* @see https://php.net/mongodb-bson-unserializable.bsonunserialize
* @param array $data Array data
*/
public function bsonUnserialize(array $data)
@@ -91,9 +93,10 @@ class BSONArray extends ArrayObject implements JsonSerializable, Serializable, U
* The array data will be numerically reindexed to ensure that it is stored
* as a JSON array.
*
* @see http://php.net/jsonserializable.jsonserialize
* @see https://php.net/jsonserializable.jsonserialize
* @return array
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return array_values($this->getArrayCopy());
+13 -10
View File
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,8 @@ use ArrayObject;
use JsonSerializable;
use MongoDB\BSON\Serializable;
use MongoDB\BSON\Unserializable;
use ReturnTypeWillChange;
use function MongoDB\recursive_copy;
/**
@@ -47,21 +49,21 @@ class BSONDocument extends ArrayObject implements JsonSerializable, Serializable
* This overrides the parent constructor to allow property access of entries
* by default.
*
* @see http://php.net/arrayobject.construct
* @see https://php.net/arrayobject.construct
* @param array $input
* @param integer $flags
* @param string $iterator_class
* @param string $iteratorClass
*/
public function __construct($input = [], $flags = ArrayObject::ARRAY_AS_PROPS, $iterator_class = 'ArrayIterator')
public function __construct($input = [], $flags = ArrayObject::ARRAY_AS_PROPS, $iteratorClass = 'ArrayIterator')
{
parent::__construct($input, $flags, $iterator_class);
parent::__construct($input, $flags, $iteratorClass);
}
/**
* Factory method for var_export().
*
* @see http://php.net/oop5.magic#object.set-state
* @see http://php.net/var-export
* @see https://php.net/oop5.magic#object.set-state
* @see https://php.net/var-export
* @param array $properties
* @return self
*/
@@ -76,7 +78,7 @@ class BSONDocument extends ArrayObject implements JsonSerializable, Serializable
/**
* Serialize the document to BSON.
*
* @see http://php.net/mongodb-bson-serializable.bsonserialize
* @see https://php.net/mongodb-bson-serializable.bsonserialize
* @return object
*/
public function bsonSerialize()
@@ -87,7 +89,7 @@ class BSONDocument extends ArrayObject implements JsonSerializable, Serializable
/**
* Unserialize the document to BSON.
*
* @see http://php.net/mongodb-bson-unserializable.bsonunserialize
* @see https://php.net/mongodb-bson-unserializable.bsonunserialize
* @param array $data Array data
*/
public function bsonUnserialize(array $data)
@@ -98,9 +100,10 @@ class BSONDocument extends ArrayObject implements JsonSerializable, Serializable
/**
* Serialize the array to JSON.
*
* @see http://php.net/jsonserializable.jsonserialize
* @see https://php.net/jsonserializable.jsonserialize
* @return object
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return (object) $this->getArrayCopy();
+18 -11
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2018 MongoDB, Inc.
* Copyright 2018-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,6 +20,8 @@ namespace MongoDB\Model;
use Iterator;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use ReturnTypeWillChange;
use function is_array;
use function MongoDB\BSON\toPHP;
use function sprintf;
@@ -61,7 +63,7 @@ class BSONIterator implements Iterator
* * typeMap (array): Type map for BSON deserialization.
*
* @internal
* @see http://php.net/manual/en/function.mongodb.bson-tophp.php
* @see https://php.net/manual/en/function.mongodb.bson-tophp.php
* @param string $data Concatenated, valid, BSON-encoded documents
* @param array $options Iterator options
* @throws InvalidArgumentException for parameter/option parsing errors
@@ -82,27 +84,30 @@ class BSONIterator implements Iterator
}
/**
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->current;
}
/**
* @see http://php.net/iterator.key
* @see https://php.net/iterator.key
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->key;
}
/**
* @see http://php.net/iterator.next
* @see https://php.net/iterator.next
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
$this->key++;
@@ -111,9 +116,10 @@ class BSONIterator implements Iterator
}
/**
* @see http://php.net/iterator.rewind
* @see https://php.net/iterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->key = 0;
@@ -123,9 +129,10 @@ class BSONIterator implements Iterator
}
/**
* @see http://php.net/iterator.valid
* @see https://php.net/iterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->current !== null;
@@ -137,13 +144,13 @@ class BSONIterator implements Iterator
return;
}
if (($this->bufferLength - $this->position) < self::$bsonSize) {
if ($this->bufferLength - $this->position < self::$bsonSize) {
throw new UnexpectedValueException(sprintf('Expected at least %d bytes; %d remaining', self::$bsonSize, $this->bufferLength - $this->position));
}
list(,$documentLength) = unpack('V', substr($this->buffer, $this->position, self::$bsonSize));
[, $documentLength] = unpack('V', substr($this->buffer, $this->position, self::$bsonSize));
if (($this->bufferLength - $this->position) < $documentLength) {
if ($this->bufferLength - $this->position < $documentLength) {
throw new UnexpectedValueException(sprintf('Expected %d bytes; %d remaining', $documentLength, $this->bufferLength - $this->position));
}
+35 -19
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2017 MongoDB, Inc.
* Copyright 2017-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,10 +20,11 @@ namespace MongoDB\Model;
use Countable;
use Iterator;
use IteratorIterator;
use ReturnTypeWillChange;
use Traversable;
use function count;
use function current;
use function key;
use function next;
use function reset;
@@ -38,10 +39,13 @@ use function reset;
*/
class CachingIterator implements Countable, Iterator
{
private const FIELD_KEY = 0;
private const FIELD_VALUE = 1;
/** @var array */
private $items = [];
/** @var IteratorIterator */
/** @var Iterator */
private $iterator;
/** @var boolean */
@@ -53,23 +57,24 @@ class CachingIterator implements Countable, Iterator
/**
* Initialize the iterator and stores the first item in the cache. This
* effectively rewinds the Traversable and the wrapping IteratorIterator.
* Additionally, this mimics behavior of the SPL iterators and allows users
* to omit an explicit call * to rewind() before using the other methods.
* Additionally, this mimics behavior of the SPL iterators and allows users
* to omit an explicit call to rewind() before using the other methods.
*
* @param Traversable $traversable
*/
public function __construct(Traversable $traversable)
{
$this->iterator = new IteratorIterator($traversable);
$this->iterator = $traversable instanceof Iterator ? $traversable : new IteratorIterator($traversable);
$this->iterator->rewind();
$this->storeCurrentItem();
}
/**
* @see http://php.net/countable.count
* @see https://php.net/countable.count
* @return integer
*/
#[ReturnTypeWillChange]
public function count()
{
$this->exhaustIterator();
@@ -78,27 +83,34 @@ class CachingIterator implements Countable, Iterator
}
/**
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return current($this->items);
$currentItem = current($this->items);
return $currentItem !== false ? $currentItem[self::FIELD_VALUE] : false;
}
/**
* @see http://php.net/iterator.key
* @see https://php.net/iterator.key
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
return key($this->items);
$currentItem = current($this->items);
return $currentItem !== false ? $currentItem[self::FIELD_KEY] : null;
}
/**
* @see http://php.net/iterator.next
* @see https://php.net/iterator.next
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
if (! $this->iteratorExhausted) {
@@ -114,9 +126,10 @@ class CachingIterator implements Countable, Iterator
}
/**
* @see http://php.net/iterator.rewind
* @see https://php.net/iterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
/* If the iterator has advanced, exhaust it now so that future iteration
@@ -130,9 +143,10 @@ class CachingIterator implements Countable, Iterator
}
/**
* @see http://php.net/iterator.valid
* @see https://php.net/iterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->key() !== null;
@@ -153,12 +167,14 @@ class CachingIterator implements Countable, Iterator
*/
private function storeCurrentItem()
{
$key = $this->iterator->key();
if ($key === null) {
if (! $this->iterator->valid()) {
return;
}
$this->items[$key] = $this->iterator->current();
// Storing a new item in the internal cache
$this->items[] = [
self::FIELD_KEY => $this->iterator->key(),
self::FIELD_VALUE => $this->iterator->current(),
];
}
}
+15 -9
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2017 MongoDB, Inc.
* Copyright 2017-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,6 +20,7 @@ namespace MongoDB\Model;
use Closure;
use Iterator;
use IteratorIterator;
use ReturnTypeWillChange;
use Traversable;
/**
@@ -32,55 +33,60 @@ class CallbackIterator implements Iterator
/** @var Closure */
private $callback;
/** @var IteratorIterator */
/** @var Iterator */
private $iterator;
public function __construct(Traversable $traversable, Closure $callback)
{
$this->iterator = new IteratorIterator($traversable);
$this->iterator = $traversable instanceof Iterator ? $traversable : new IteratorIterator($traversable);
$this->callback = $callback;
}
/**
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return ($this->callback)($this->iterator->current());
}
/**
* @see http://php.net/iterator.key
* @see https://php.net/iterator.key
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->iterator->key();
}
/**
* @see http://php.net/iterator.next
* @see https://php.net/iterator.next
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
$this->iterator->next();
}
/**
* @see http://php.net/iterator.rewind
* @see https://php.net/iterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
$this->iterator->rewind();
}
/**
* @see http://php.net/iterator.valid
* @see https://php.net/iterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->iterator->valid();
+12 -3
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2019 MongoDB, Inc.
* Copyright 2019-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,6 +28,8 @@ use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\ResumeTokenException;
use MongoDB\Exception\UnexpectedValueException;
use ReturnTypeWillChange;
use function count;
use function is_array;
use function is_integer;
@@ -138,6 +140,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
* @see https://php.net/iteratoriterator.current
* @return mixed
*/
#[ReturnTypeWillChange]
public function current()
{
return $this->isValid ? parent::current() : null;
@@ -160,7 +163,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
/**
* Returns the server the cursor is running on.
*/
public function getServer() : Server
public function getServer(): Server
{
return $this->server;
}
@@ -169,6 +172,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
* @see https://php.net/iteratoriterator.key
* @return mixed
*/
#[ReturnTypeWillChange]
public function key()
{
return $this->isValid ? parent::key() : null;
@@ -178,6 +182,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
* @see https://php.net/iteratoriterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
/* Determine if advancing the iterator will execute a getMore command
@@ -205,6 +210,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
* @see https://php.net/iteratoriterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
if ($this->isRewindNop) {
@@ -219,6 +225,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
* @see https://php.net/iteratoriterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return $this->isValid;
@@ -248,11 +255,13 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber
if (! isset($resumeToken)) {
$this->isValid = false;
throw ResumeTokenException::notFound();
}
if (! is_array($resumeToken) && ! is_object($resumeToken)) {
$this->isValid = false;
throw ResumeTokenException::invalidType($resumeToken);
}
+56 -8
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,8 @@ namespace MongoDB\Model;
use ArrayAccess;
use MongoDB\Exception\BadMethodCallException;
use ReturnTypeWillChange;
use function array_key_exists;
/**
@@ -48,7 +50,7 @@ class CollectionInfo implements ArrayAccess
/**
* Return the collection info as an array.
*
* @see http://php.net/oop5.magic#language.oop5.magic.debuginfo
* @see https://php.net/oop5.magic#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -59,6 +61,8 @@ class CollectionInfo implements ArrayAccess
/**
* Return the maximum number of documents to keep in the capped collection.
*
* @deprecated 1.0 Deprecated in favor of using getOptions
*
* @return integer|null
*/
public function getCappedMax()
@@ -70,6 +74,8 @@ class CollectionInfo implements ArrayAccess
/**
* Return the maximum size (in bytes) of the capped collection.
*
* @deprecated 1.0 Deprecated in favor of using getOptions
*
* @return integer|null
*/
public function getCappedSize()
@@ -78,9 +84,31 @@ class CollectionInfo implements ArrayAccess
return isset($this->info['options']['size']) ? (integer) $this->info['options']['size'] : null;
}
/**
* Return information about the _id index for the collection.
*
* @return array
*/
public function getIdIndex(): array
{
return (array) ($this->info['idIndex'] ?? []);
}
/**
* Return the "info" property of the server response.
*
* @see https://mongodb.com/docs/manual/reference/command/listCollections/#output
* @return array
*/
public function getInfo(): array
{
return (array) ($this->info['info'] ?? []);
}
/**
* Return the collection name.
*
* @see https://mongodb.com/docs/manual/reference/command/listCollections/#output
* @return string
*/
public function getName()
@@ -91,16 +119,30 @@ class CollectionInfo implements ArrayAccess
/**
* Return the collection options.
*
* @see https://mongodb.com/docs/manual/reference/command/listCollections/#output
* @return array
*/
public function getOptions()
{
return isset($this->info['options']) ? (array) $this->info['options'] : [];
return (array) ($this->info['options'] ?? []);
}
/**
* Return the collection type.
*
* @see https://mongodb.com/docs/manual/reference/command/listCollections/#output
* @return string
*/
public function getType(): string
{
return (string) $this->info['type'];
}
/**
* Return whether the collection is a capped collection.
*
* @deprecated 1.0 Deprecated in favor of using getOptions
*
* @return boolean
*/
public function isCapped()
@@ -111,10 +153,11 @@ class CollectionInfo implements ArrayAccess
/**
* Check whether a field exists in the collection information.
*
* @see http://php.net/arrayaccess.offsetexists
* @see https://php.net/arrayaccess.offsetexists
* @param mixed $key
* @return boolean
*/
#[ReturnTypeWillChange]
public function offsetExists($key)
{
return array_key_exists($key, $this->info);
@@ -123,10 +166,11 @@ class CollectionInfo implements ArrayAccess
/**
* Return the field's value from the collection information.
*
* @see http://php.net/arrayaccess.offsetget
* @see https://php.net/arrayaccess.offsetget
* @param mixed $key
* @return mixed
*/
#[ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->info[$key];
@@ -135,11 +179,13 @@ class CollectionInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetset
* @see https://php.net/arrayaccess.offsetset
* @param mixed $key
* @param mixed $value
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet($key, $value)
{
throw BadMethodCallException::classIsImmutable(self::class);
@@ -148,10 +194,12 @@ class CollectionInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetunset
* @see https://php.net/arrayaccess.offsetunset
* @param mixed $key
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset($key)
{
throw BadMethodCallException::classIsImmutable(self::class);
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Model;
use IteratorIterator;
use ReturnTypeWillChange;
use Traversable;
/**
@@ -29,7 +30,7 @@ use Traversable;
* @internal
* @see \MongoDB\Database::listCollections()
* @see https://github.com/mongodb/specifications/blob/master/source/enumerate-collections.rst
* @see http://docs.mongodb.org/manual/reference/command/listCollections/
* @see https://mongodb.com/docs/manual/reference/command/listCollections/
*/
class CollectionInfoCommandIterator extends IteratorIterator implements CollectionInfoIterator
{
@@ -50,9 +51,10 @@ class CollectionInfoCommandIterator extends IteratorIterator implements Collecti
* Return the current element as a CollectionInfo instance.
*
* @see CollectionInfoIterator::current()
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return CollectionInfo
*/
#[ReturnTypeWillChange]
public function current()
{
$info = parent::current();
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Model;
use Iterator;
use ReturnTypeWillChange;
/**
* CollectionInfoIterator interface.
@@ -34,5 +35,6 @@ interface CollectionInfoIterator extends Iterator
*
* @return CollectionInfo
*/
#[ReturnTypeWillChange]
public function current();
}
+16 -8
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,8 @@ namespace MongoDB\Model;
use ArrayAccess;
use MongoDB\Exception\BadMethodCallException;
use ReturnTypeWillChange;
use function array_key_exists;
/**
@@ -29,7 +31,7 @@ use function array_key_exists;
*
* @api
* @see \MongoDB\Client::listDatabases()
* @see http://docs.mongodb.org/manual/reference/command/listDatabases/
* @see https://mongodb.com/docs/manual/reference/command/listDatabases/
*/
class DatabaseInfo implements ArrayAccess
{
@@ -47,7 +49,7 @@ class DatabaseInfo implements ArrayAccess
/**
* Return the database info as an array.
*
* @see http://php.net/oop5.magic#language.oop5.magic.debuginfo
* @see https://php.net/oop5.magic#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -89,10 +91,11 @@ class DatabaseInfo implements ArrayAccess
/**
* Check whether a field exists in the database information.
*
* @see http://php.net/arrayaccess.offsetexists
* @see https://php.net/arrayaccess.offsetexists
* @param mixed $key
* @return boolean
*/
#[ReturnTypeWillChange]
public function offsetExists($key)
{
return array_key_exists($key, $this->info);
@@ -101,10 +104,11 @@ class DatabaseInfo implements ArrayAccess
/**
* Return the field's value from the database information.
*
* @see http://php.net/arrayaccess.offsetget
* @see https://php.net/arrayaccess.offsetget
* @param mixed $key
* @return mixed
*/
#[ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->info[$key];
@@ -113,11 +117,13 @@ class DatabaseInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetset
* @see https://php.net/arrayaccess.offsetset
* @param mixed $key
* @param mixed $value
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet($key, $value)
{
throw BadMethodCallException::classIsImmutable(self::class);
@@ -126,10 +132,12 @@ class DatabaseInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetunset
* @see https://php.net/arrayaccess.offsetunset
* @param mixed $key
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset($key)
{
throw BadMethodCallException::classIsImmutable(self::class);
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Model;
use Iterator;
use ReturnTypeWillChange;
/**
* DatabaseInfoIterator interface.
@@ -34,5 +35,6 @@ interface DatabaseInfoIterator extends Iterator
*
* @return DatabaseInfo
*/
#[ReturnTypeWillChange]
public function current();
}
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,6 +17,8 @@
namespace MongoDB\Model;
use ReturnTypeWillChange;
use function current;
use function key;
use function next;
@@ -30,7 +32,7 @@ use function reset;
*
* @internal
* @see \MongoDB\Client::listDatabases()
* @see http://docs.mongodb.org/manual/reference/command/listDatabases/
* @see https://mongodb.com/docs/manual/reference/command/listDatabases/
*/
class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
{
@@ -49,7 +51,7 @@ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
* Return the current element as a DatabaseInfo instance.
*
* @see DatabaseInfoIterator::current()
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return DatabaseInfo
*/
public function current()
@@ -60,9 +62,10 @@ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
/**
* Return the key of the current element.
*
* @see http://php.net/iterator.key
* @see https://php.net/iterator.key
* @return integer
*/
#[ReturnTypeWillChange]
public function key()
{
return key($this->databases);
@@ -71,8 +74,10 @@ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
/**
* Move forward to next element.
*
* @see http://php.net/iterator.next
* @see https://php.net/iterator.next
* @return void
*/
#[ReturnTypeWillChange]
public function next()
{
next($this->databases);
@@ -81,8 +86,10 @@ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
/**
* Rewind the Iterator to the first element.
*
* @see http://php.net/iterator.rewind
* @see https://php.net/iterator.rewind
* @return void
*/
#[ReturnTypeWillChange]
public function rewind()
{
reset($this->databases);
@@ -91,9 +98,10 @@ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator
/**
* Checks if current position is valid.
*
* @see http://php.net/iterator.valid
* @see https://php.net/iterator.valid
* @return boolean
*/
#[ReturnTypeWillChange]
public function valid()
{
return key($this->databases) !== null;
+19 -11
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,8 @@ namespace MongoDB\Model;
use ArrayAccess;
use MongoDB\Exception\BadMethodCallException;
use ReturnTypeWillChange;
use function array_key_exists;
use function array_search;
@@ -35,7 +37,7 @@ use function array_search;
* @api
* @see \MongoDB\Collection::listIndexes()
* @see https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createIndex/
*/
class IndexInfo implements ArrayAccess
{
@@ -53,7 +55,7 @@ class IndexInfo implements ArrayAccess
/**
* Return the collection info as an array.
*
* @see http://php.net/oop5.magic#language.oop5.magic.debuginfo
* @see https://php.net/oop5.magic#language.oop5.magic.debuginfo
* @return array
*/
public function __debugInfo()
@@ -134,7 +136,7 @@ class IndexInfo implements ArrayAccess
/**
* Return whether this is a sparse index.
*
* @see http://docs.mongodb.org/manual/core/index-sparse/
* @see https://mongodb.com/docs/manual/core/index-sparse/
* @return boolean
*/
public function isSparse()
@@ -155,7 +157,7 @@ class IndexInfo implements ArrayAccess
/**
* Return whether this is a TTL index.
*
* @see http://docs.mongodb.org/manual/core/index-ttl/
* @see https://mongodb.com/docs/manual/core/index-ttl/
* @return boolean
*/
public function isTtl()
@@ -166,7 +168,7 @@ class IndexInfo implements ArrayAccess
/**
* Return whether this is a unique index.
*
* @see http://docs.mongodb.org/manual/core/index-unique/
* @see https://mongodb.com/docs/manual/core/index-unique/
* @return boolean
*/
public function isUnique()
@@ -177,10 +179,11 @@ class IndexInfo implements ArrayAccess
/**
* Check whether a field exists in the index information.
*
* @see http://php.net/arrayaccess.offsetexists
* @see https://php.net/arrayaccess.offsetexists
* @param mixed $key
* @return boolean
*/
#[ReturnTypeWillChange]
public function offsetExists($key)
{
return array_key_exists($key, $this->info);
@@ -193,11 +196,12 @@ class IndexInfo implements ArrayAccess
* that index fields be made accessible under their original names. It may
* also be used to access fields that do not have a helper method.
*
* @see http://php.net/arrayaccess.offsetget
* @see https://php.net/arrayaccess.offsetget
* @see https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst#getting-full-index-information
* @param mixed $key
* @return mixed
*/
#[ReturnTypeWillChange]
public function offsetGet($key)
{
return $this->info[$key];
@@ -206,11 +210,13 @@ class IndexInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetset
* @see https://php.net/arrayaccess.offsetset
* @param mixed $key
* @param mixed $value
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetSet($key, $value)
{
throw BadMethodCallException::classIsImmutable(self::class);
@@ -219,10 +225,12 @@ class IndexInfo implements ArrayAccess
/**
* Not supported.
*
* @see http://php.net/arrayaccess.offsetunset
* @see https://php.net/arrayaccess.offsetunset
* @param mixed $key
* @throws BadMethodCallException
* @return void
*/
#[ReturnTypeWillChange]
public function offsetUnset($key)
{
throw BadMethodCallException::classIsImmutable(self::class);
+4 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,6 +18,7 @@
namespace MongoDB\Model;
use Iterator;
use ReturnTypeWillChange;
/**
* IndexInfoIterator interface.
@@ -34,5 +35,6 @@ interface IndexInfoIterator extends Iterator
*
* @return IndexInfo
*/
#[ReturnTypeWillChange]
public function current();
}
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,7 +18,9 @@
namespace MongoDB\Model;
use IteratorIterator;
use ReturnTypeWillChange;
use Traversable;
use function array_key_exists;
/**
@@ -31,8 +33,8 @@ use function array_key_exists;
* @internal
* @see \MongoDB\Collection::listIndexes()
* @see https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst
* @see http://docs.mongodb.org/manual/reference/command/listIndexes/
* @see http://docs.mongodb.org/manual/reference/system-collections/
* @see https://mongodb.com/docs/manual/reference/command/listIndexes/
* @see https://mongodb.com/docs/manual/reference/system-collections/
*/
class IndexInfoIteratorIterator extends IteratorIterator implements IndexInfoIterator
{
@@ -53,9 +55,10 @@ class IndexInfoIteratorIterator extends IteratorIterator implements IndexInfoIte
* Return the current element as an IndexInfo instance.
*
* @see IndexInfoIterator::current()
* @see http://php.net/iterator.current
* @see https://php.net/iterator.current
* @return IndexInfo
*/
#[ReturnTypeWillChange]
public function current()
{
$info = parent::current();
+5 -4
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,7 @@ namespace MongoDB\Model;
use MongoDB\BSON\Serializable;
use MongoDB\Exception\InvalidArgumentException;
use function is_array;
use function is_float;
use function is_int;
@@ -35,7 +36,7 @@ use function sprintf;
* @internal
* @see \MongoDB\Collection::createIndexes()
* @see https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst
* @see http://docs.mongodb.org/manual/reference/method/db.collection.createIndex/
* @see https://mongodb.com/docs/manual/reference/method/db.collection.createIndex/
*/
class IndexInput implements Serializable
{
@@ -87,7 +88,7 @@ class IndexInput implements Serializable
* Serialize the index information to BSON for index creation.
*
* @see \MongoDB\Collection::createIndexes()
* @see http://php.net/mongodb-bson-serializable.bsonserialize
* @see https://php.net/mongodb-bson-serializable.bsonserialize
* @return array
*/
public function bsonSerialize()
+92 -105
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,7 @@ namespace MongoDB\Operation;
use ArrayIterator;
use MongoDB\Driver\Command;
use MongoDB\Driver\Cursor;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference;
@@ -30,6 +31,7 @@ use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use stdClass;
use Traversable;
use function current;
use function is_array;
use function is_bool;
@@ -38,7 +40,6 @@ use function is_object;
use function is_string;
use function MongoDB\create_field_path_type_map;
use function MongoDB\is_last_pipeline_operator_write;
use function MongoDB\server_supports_feature;
use function sprintf;
/**
@@ -46,22 +47,10 @@ use function sprintf;
*
* @api
* @see \MongoDB\Collection::aggregate()
* @see http://docs.mongodb.org/manual/reference/command/aggregate/
* @see https://mongodb.com/docs/manual/reference/command/aggregate/
*/
class Aggregate implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForWriteConcern = 5;
/** @var string */
private $databaseName;
@@ -74,6 +63,12 @@ class Aggregate implements Executable, Explainable
/** @var array */
private $options;
/** @var bool */
private $isExplain;
/** @var bool */
private $isWrite;
/**
* Constructs an aggregate command.
*
@@ -81,7 +76,7 @@ class Aggregate implements Executable, Explainable
*
* * allowDiskUse (boolean): Enables writing to temporary files. When set
* to true, aggregation stages can write data to the _tmp sub-directory
* in the dbPath directory. The default is false.
* in the dbPath directory.
*
* * batchSize (integer): The number of documents to return per batch.
*
@@ -89,16 +84,11 @@ class Aggregate implements Executable, Explainable
* circumvent document level validation. This only applies when an $out
* or $merge stage is specified.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* * comment (string): An arbitrary string to help trace the operation
* through the database profiler, currentOp, and logs.
* Only string values are supported for server versions < 4.4.
*
* * explain (boolean): Specifies whether or not to return the information
* on the processing of the pipeline.
@@ -107,22 +97,25 @@ class Aggregate implements Executable, Explainable
* name as a string or the index key pattern as a document. If specified,
* then the query system will only consider plans using the hinted index.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* This is not supported for server versions < 5.0 and will result in an
* exception at execution time if used.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* This option is ignored if an $out or $merge stage is specified.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server).
*
@@ -135,9 +128,6 @@ class Aggregate implements Executable, Explainable
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern. This only
* applies when an $out or $merge stage is specified.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* Note: Collection-agnostic commands (e.g. $currentOp) may be executed by
* specifying null for the collection name.
*
@@ -163,12 +153,9 @@ class Aggregate implements Executable, Explainable
$expectedIndex += 1;
}
$options += [
'allowDiskUse' => false,
'useCursor' => true,
];
$options += ['useCursor' => true];
if (! is_bool($options['allowDiskUse'])) {
if (isset($options['allowDiskUse']) && ! is_bool($options['allowDiskUse'])) {
throw InvalidArgumentException::invalidType('"allowDiskUse" option', $options['allowDiskUse'], 'boolean');
}
@@ -184,10 +171,6 @@ class Aggregate implements Executable, Explainable
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
}
if (isset($options['comment']) && ! is_string($options['comment'])) {
throw InvalidArgumentException::invalidType('"comment" option', $options['comment'], 'string');
}
if (isset($options['explain']) && ! is_bool($options['explain'])) {
throw InvalidArgumentException::invalidType('"explain" option', $options['explain'], 'boolean');
}
@@ -196,6 +179,10 @@ class Aggregate implements Executable, Explainable
throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object');
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], ['array', 'object']);
}
if (isset($options['maxAwaitTimeMS']) && ! is_integer($options['maxAwaitTimeMS'])) {
throw InvalidArgumentException::invalidType('"maxAwaitTimeMS" option', $options['maxAwaitTimeMS'], 'integer');
}
@@ -232,6 +219,10 @@ class Aggregate implements Executable, Explainable
throw new InvalidArgumentException('"batchSize" option should not be used if "useCursor" is false');
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['readConcern']) && $options['readConcern']->isDefault()) {
unset($options['readConcern']);
}
@@ -240,8 +231,19 @@ class Aggregate implements Executable, Explainable
unset($options['writeConcern']);
}
if (! empty($options['explain'])) {
$this->isExplain = ! empty($options['explain']);
$this->isWrite = is_last_pipeline_operator_write($pipeline) && ! $this->isExplain;
// Explain does not use a cursor
if ($this->isExplain) {
$options['useCursor'] = false;
unset($options['batchSize']);
}
/* Ignore batchSize for writes, since no documents are returned and a
* batchSize of zero could prevent the pipeline from executing. */
if ($this->isWrite) {
unset($options['batchSize']);
}
$this->databaseName = (string) $databaseName;
@@ -257,47 +259,30 @@ class Aggregate implements Executable, Explainable
* @param Server $server
* @return Traversable
* @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation, read concern, or write concern is used and unsupported
* @throws UnsupportedException if read concern or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['readConcern']) && ! server_supports_feature($server, self::$wireVersionForReadConcern)) {
throw UnsupportedException::readConcernNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction) {
if (isset($this->options['readConcern'])) {
throw UnsupportedException::readConcernNotSupportedInTransaction();
}
if (isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
}
$hasExplain = ! empty($this->options['explain']);
$hasWriteStage = $this->hasWriteStage();
$command = new Command(
$this->createCommandDocument($server, $hasWriteStage),
$this->createCommandDocument(),
$this->createCommandOptions()
);
$options = $this->createOptions($hasWriteStage, $hasExplain);
$cursor = $hasWriteStage && ! $hasExplain
? $server->executeReadWriteCommand($this->databaseName, $command, $options)
: $server->executeReadCommand($this->databaseName, $command, $options);
$cursor = $this->executeCommand($server, $command);
if ($this->options['useCursor'] || $hasExplain) {
if ($this->options['useCursor'] || $this->isExplain) {
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
@@ -318,34 +303,40 @@ class Aggregate implements Executable, Explainable
return new ArrayIterator($result->result);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->createCommandDocument($server, $this->hasWriteStage());
return $this->createCommandDocument();
}
private function createCommandDocument(Server $server, bool $hasWriteStage) : array
/**
* Create the aggregate command document.
*
* @return array
*/
private function createCommandDocument()
{
$cmd = [
'aggregate' => $this->collectionName ?? 1,
'pipeline' => $this->pipeline,
];
$cmd['allowDiskUse'] = $this->options['allowDiskUse'];
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
foreach (['comment', 'explain', 'maxTimeMS'] as $option) {
foreach (['allowDiskUse', 'bypassDocumentValidation', 'comment', 'explain', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
if (isset($this->options['collation'])) {
$cmd['collation'] = (object) $this->options['collation'];
foreach (['collation', 'let'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = (object) $this->options[$option];
}
}
if (isset($this->options['hint'])) {
@@ -353,10 +344,7 @@ class Aggregate implements Executable, Explainable
}
if ($this->options['useCursor']) {
/* Ignore batchSize if pipeline includes an $out or $merge stage, as
* no documents will be returned and sending a batchSize of zero
* could prevent the pipeline from executing at all. */
$cmd['cursor'] = isset($this->options["batchSize"]) && ! $hasWriteStage
$cmd['cursor'] = isset($this->options["batchSize"])
? ['batchSize' => $this->options["batchSize"]]
: new stdClass();
}
@@ -364,7 +352,7 @@ class Aggregate implements Executable, Explainable
return $cmd;
}
private function createCommandOptions() : array
private function createCommandOptions(): array
{
$cmdOptions = [];
@@ -376,39 +364,38 @@ class Aggregate implements Executable, Explainable
}
/**
* Create options for executing the command.
* Execute the aggregate command using the appropriate Server method.
*
* @see http://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see http://php.net/manual/en/mongodb-driver-server.executereadwritecommand.php
* @param boolean $hasWriteStage
* @param boolean $hasExplain
* @return array
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadwritecommand.php
*/
private function createOptions($hasWriteStage, $hasExplain)
private function executeCommand(Server $server, Command $command): Cursor
{
$options = [];
if (isset($this->options['readConcern'])) {
$options['readConcern'] = $this->options['readConcern'];
foreach (['readConcern', 'readPreference', 'session'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = $this->options[$option];
}
}
if (! $hasWriteStage && isset($this->options['readPreference'])) {
$options['readPreference'] = $this->options['readPreference'];
}
if (isset($this->options['session'])) {
$options['session'] = $this->options['session'];
}
if ($hasWriteStage && ! $hasExplain && isset($this->options['writeConcern'])) {
if ($this->isWrite && isset($this->options['writeConcern'])) {
$options['writeConcern'] = $this->options['writeConcern'];
}
return $options;
}
if (! $this->isWrite) {
return $server->executeReadCommand($this->databaseName, $command, $options);
}
private function hasWriteStage() : bool
{
return is_last_pipeline_operator_write($this->pipeline);
/* Server::executeReadWriteCommand() does not support a "readPreference"
* option, so fall back to executeCommand(). This means that libmongoc
* will not apply any client-level options (e.g. writeConcern), but that
* should not be an issue as PHPLIB handles inheritance on its own. */
if (isset($options['readPreference'])) {
return $server->executeCommand($this->databaseName, $command, $options);
}
return $server->executeReadWriteCommand($this->databaseName, $command, $options);
}
}
+63 -83
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,6 +25,7 @@ use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function array_key_exists;
use function count;
use function current;
@@ -34,7 +35,6 @@ use function is_object;
use function key;
use function MongoDB\is_first_key_operator;
use function MongoDB\is_pipeline;
use function MongoDB\server_supports_feature;
use function sprintf;
/**
@@ -45,21 +45,12 @@ use function sprintf;
*/
class BulkWrite implements Executable
{
const DELETE_MANY = 'deleteMany';
const DELETE_ONE = 'deleteOne';
const INSERT_ONE = 'insertOne';
const REPLACE_ONE = 'replaceOne';
const UPDATE_MANY = 'updateMany';
const UPDATE_ONE = 'updateOne';
/** @var integer */
private static $wireVersionForArrayFilters = 6;
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
public const DELETE_MANY = 'deleteMany';
public const DELETE_ONE = 'deleteOne';
public const INSERT_ONE = 'insertOne';
public const REPLACE_ONE = 'replaceOne';
public const UPDATE_MANY = 'updateMany';
public const UPDATE_ONE = 'updateOne';
/** @var string */
private $databaseName;
@@ -73,12 +64,6 @@ class BulkWrite implements Executable
/** @var array */
private $options;
/** @var boolean */
private $isArrayFiltersUsed = false;
/** @var boolean */
private $isCollationUsed = false;
/**
* Constructs a bulk write operation.
*
@@ -101,16 +86,10 @@ class BulkWrite implements Executable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* Supported options for replaceOne, updateMany, and updateOne operations:
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
@@ -119,24 +98,26 @@ class BulkWrite implements Executable
* * arrayFilters (document array): A set of filters specifying to which
* array elements an update should apply.
*
* This is not supported for server versions < 3.6 and will result in an
* exception at execution time if used.
*
* Supported options for the bulk write operation:
*
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation. The default is false.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
* * comment (mixed): BSON value to attach as a comment to this command(s)
* associated with this bulk write.
*
* This is not supported for servers versions < 4.4.
*
* * ordered (boolean): If true, when an insert fails, return without
* performing the remaining writes. If false, when a write fails,
* continue with the remaining writes, if any. The default is true.
*
* * session (MongoDB\Driver\Session): Client session.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* Sessions are not supported for server versions < 3.6.
* * session (MongoDB\Driver\Session): Client session.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
@@ -194,12 +175,8 @@ class BulkWrite implements Executable
$args[1]['limit'] = ($type === self::DELETE_ONE ? 1 : 0);
if (isset($args[1]['collation'])) {
$this->isCollationUsed = true;
if (! is_array($args[1]['collation']) && ! is_object($args[1]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]["collation"]', $i, $type), $args[1]['collation'], 'array or object');
}
if (isset($args[1]['collation']) && ! is_array($args[1]['collation']) && ! is_object($args[1]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][1]["collation"]', $i, $type), $args[1]['collation'], 'array or object');
}
$operations[$i][$type][1] = $args[1];
@@ -230,12 +207,8 @@ class BulkWrite implements Executable
$args[2]['multi'] = false;
$args[2] += ['upsert' => false];
if (isset($args[2]['collation'])) {
$this->isCollationUsed = true;
if (! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
}
if (isset($args[2]['collation']) && ! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
}
if (! is_bool($args[2]['upsert'])) {
@@ -271,20 +244,12 @@ class BulkWrite implements Executable
$args[2]['multi'] = ($type === self::UPDATE_MANY);
$args[2] += ['upsert' => false];
if (isset($args[2]['arrayFilters'])) {
$this->isArrayFiltersUsed = true;
if (! is_array($args[2]['arrayFilters'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["arrayFilters"]', $i, $type), $args[2]['arrayFilters'], 'array');
}
if (isset($args[2]['arrayFilters']) && ! is_array($args[2]['arrayFilters'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["arrayFilters"]', $i, $type), $args[2]['arrayFilters'], 'array');
}
if (isset($args[2]['collation'])) {
$this->isCollationUsed = true;
if (! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
}
if (isset($args[2]['collation']) && ! is_array($args[2]['collation']) && ! is_object($args[2]['collation'])) {
throw InvalidArgumentException::invalidType(sprintf('$operations[%d]["%s"][2]["collation"]', $i, $type), $args[2]['collation'], 'array or object');
}
if (! is_bool($args[2]['upsert'])) {
@@ -320,6 +285,14 @@ class BulkWrite implements Executable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], 'array or object');
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
@@ -336,33 +309,17 @@ class BulkWrite implements Executable
* @see Executable::execute()
* @param Server $server
* @return BulkWriteResult
* @throws UnsupportedException if array filters or collation is used and unsupported
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if ($this->isArrayFiltersUsed && ! server_supports_feature($server, self::$wireVersionForArrayFilters)) {
throw UnsupportedException::arrayFiltersNotSupported();
}
if ($this->isCollationUsed && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$options = ['ordered' => $this->options['ordered']];
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$bulk = new Bulk($this->createBulkWriteOptions());
$insertedIds = [];
foreach ($this->operations as $i => $operation) {
@@ -386,18 +343,41 @@ class BulkWrite implements Executable
}
}
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createOptions());
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
return new BulkWriteResult($writeResult, $insertedIds);
}
/**
* Create options for executing the bulk write.
* Create options for constructing the bulk write.
*
* @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @see https://php.net/manual/en/mongodb-driver-bulkwrite.construct.php
* @return array
*/
private function createOptions()
private function createBulkWriteOptions()
{
$options = ['ordered' => $this->options['ordered']];
foreach (['bypassDocumentValidation', 'comment'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = $this->options[$option];
}
}
if (isset($this->options['let'])) {
$options['let'] = (object) $this->options['let'];
}
return $options;
}
/**
* Create options for executing the bulk write.
*
* @see https://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @return array
*/
private function createExecuteOptions()
{
$options = [];
+17 -28
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,29 +26,23 @@ use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_float;
use function is_integer;
use function is_object;
use function is_string;
use function MongoDB\server_supports_feature;
/**
* Operation for the count command.
*
* @api
* @see \MongoDB\Collection::count()
* @see http://docs.mongodb.org/manual/reference/command/count/
* @see https://mongodb.com/docs/manual/reference/command/count/
*/
class Count implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var string */
private $databaseName;
@@ -68,8 +62,9 @@ class Count implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -82,15 +77,10 @@ class Count implements Executable, Explainable
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * skip (integer): The number of documents to skip before returning the
* documents.
*
@@ -155,19 +145,11 @@ class Count implements Executable, Explainable
* @param Server $server
* @return integer
* @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation or read concern is used and unsupported
* @throws UnsupportedException if read concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['readConcern']) && ! server_supports_feature($server, self::$wireVersionForReadConcern)) {
throw UnsupportedException::readConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['readConcern'])) {
throw UnsupportedException::readConcernNotSupportedInTransaction();
@@ -184,6 +166,13 @@ class Count implements Executable, Explainable
return (integer) $result->n;
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->createCommandDocument();
@@ -210,7 +199,7 @@ class Count implements Executable, Explainable
$cmd['hint'] = is_array($this->options['hint']) ? (object) $this->options['hint'] : $this->options['hint'];
}
foreach (['limit', 'maxTimeMS', 'skip'] as $option) {
foreach (['comment', 'limit', 'maxTimeMS', 'skip'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
@@ -222,7 +211,7 @@ class Count implements Executable, Explainable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @return array
*/
private function createOptions()
+7 -10
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@ use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use function array_intersect_key;
use function count;
use function current;
@@ -64,8 +65,9 @@ class CountDocuments implements Executable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* Only string values are supported for server versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -78,15 +80,10 @@ class CountDocuments implements Executable
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * skip (integer): The number of documents to skip before returning the
* documents.
*
@@ -114,7 +111,7 @@ class CountDocuments implements Executable
$this->collectionName = (string) $collectionName;
$this->filter = $filter;
$this->aggregateOptions = array_intersect_key($options, ['collation' => 1, 'hint' => 1, 'maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1]);
$this->aggregateOptions = array_intersect_key($options, ['collation' => 1, 'comment' => 1, 'hint' => 1, 'maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1]);
$this->countOptions = array_intersect_key($options, ['limit' => 1, 'skip' => 1]);
$this->aggregate = $this->createAggregate();
+86 -34
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,15 +23,16 @@ use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_bool;
use function is_integer;
use function is_object;
use function is_string;
use function MongoDB\server_supports_feature;
use function sprintf;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
@@ -39,18 +40,12 @@ use const E_USER_DEPRECATED;
*
* @api
* @see \MongoDB\Database::createCollection()
* @see http://docs.mongodb.org/manual/reference/command/create/
* @see https://mongodb.com/docs/manual/reference/command/create/
*/
class CreateCollection implements Executable
{
const USE_POWER_OF_2_SIZES = 1;
const NO_PADDING = 2;
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForWriteConcern = 5;
public const USE_POWER_OF_2_SIZES = 1;
public const NO_PADDING = 2;
/** @var string */
private $databaseName;
@@ -77,10 +72,26 @@ class CreateCollection implements Executable
* * capped (boolean): Specify true to create a capped collection. If set,
* the size option must also be specified. The default is false.
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * changeStreamPreAndPostImages (document): Used to configure support for
* pre- and post-images in change streams.
*
* This is not supported for server versions < 6.0.
*
* * clusteredIndex (document): A clustered index specification.
*
* This is not supported for server versions < 5.3.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * encryptedFields (document): CSFLE specification.
*
* * expireAfterSeconds: The TTL for documents in time series collections.
*
* This is not supported for servers versions < 5.0.
*
* * flags (integer): Options for the MMAPv1 storage engine only. Must be a
* bitwise combination CreateCollection::USE_POWER_OF_2_SIZES and
@@ -96,14 +107,20 @@ class CreateCollection implements Executable
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * session (MongoDB\Driver\Session): Client session.
* * pipeline (array): An array that consists of the aggregation pipeline
* stage(s), which will be applied to the collection or view specified by
* viewOn.
*
* Sessions are not supported for server versions < 3.6.
* * session (MongoDB\Driver\Session): Client session.
*
* * size (integer): The maximum number of bytes for a capped collection.
*
* * storageEngine (document): Storage engine options.
*
* * timeseries (document): Options for time series collections.
*
* This is not supported for servers versions < 5.0.
*
* * typeMap (array): Type map for BSON deserialization. This will only be
* used for the returned command result document.
*
@@ -113,13 +130,13 @@ class CreateCollection implements Executable
*
* * validator (document): Validation rules or expressions.
*
* * viewOn (string): The name of the source collection or view from which
* to create the view.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @see http://source.wiredtiger.com/2.4.1/struct_w_t___s_e_s_s_i_o_n.html#a358ca4141d59c345f401c58501276bbb
* @see https://docs.mongodb.org/manual/core/document-validation/
* @see https://source.wiredtiger.com/2.4.1/struct_w_t___s_e_s_s_i_o_n.html#a358ca4141d59c345f401c58501276bbb
* @see https://mongodb.com/docs/manual/core/schema-validation/
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $options Command options
@@ -135,10 +152,26 @@ class CreateCollection implements Executable
throw InvalidArgumentException::invalidType('"capped" option', $options['capped'], 'boolean');
}
if (isset($options['changeStreamPreAndPostImages']) && ! is_array($options['changeStreamPreAndPostImages']) && ! is_object($options['changeStreamPreAndPostImages'])) {
throw InvalidArgumentException::invalidType('"changeStreamPreAndPostImages" option', $options['changeStreamPreAndPostImages'], 'array or object');
}
if (isset($options['clusteredIndex']) && ! is_array($options['clusteredIndex']) && ! is_object($options['clusteredIndex'])) {
throw InvalidArgumentException::invalidType('"clusteredIndex" option', $options['clusteredIndex'], 'array or object');
}
if (isset($options['collation']) && ! is_array($options['collation']) && ! is_object($options['collation'])) {
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
}
if (isset($options['encryptedFields']) && ! is_array($options['encryptedFields']) && ! is_object($options['encryptedFields'])) {
throw InvalidArgumentException::invalidType('"encryptedFields" option', $options['encryptedFields'], 'array or object');
}
if (isset($options['expireAfterSeconds']) && ! is_integer($options['expireAfterSeconds'])) {
throw InvalidArgumentException::invalidType('"expireAfterSeconds" option', $options['expireAfterSeconds'], 'integer');
}
if (isset($options['flags']) && ! is_integer($options['flags'])) {
throw InvalidArgumentException::invalidType('"flags" option', $options['flags'], 'integer');
}
@@ -155,6 +188,10 @@ class CreateCollection implements Executable
throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['pipeline']) && ! is_array($options['pipeline'])) {
throw InvalidArgumentException::invalidType('"pipeline" option', $options['pipeline'], 'array');
}
if (isset($options['session']) && ! $options['session'] instanceof Session) {
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
}
@@ -167,6 +204,10 @@ class CreateCollection implements Executable
throw InvalidArgumentException::invalidType('"storageEngine" option', $options['storageEngine'], 'array or object');
}
if (isset($options['timeseries']) && ! is_array($options['timeseries']) && ! is_object($options['timeseries'])) {
throw InvalidArgumentException::invalidType('"timeseries" option', $options['timeseries'], ['array', 'object']);
}
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
@@ -183,6 +224,10 @@ class CreateCollection implements Executable
throw InvalidArgumentException::invalidType('"validator" option', $options['validator'], 'array or object');
}
if (isset($options['viewOn']) && ! is_string($options['viewOn'])) {
throw InvalidArgumentException::invalidType('"viewOn" option', $options['viewOn'], 'string');
}
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
@@ -195,6 +240,22 @@ class CreateCollection implements Executable
trigger_error('The "autoIndexId" option is deprecated and will be removed in a future release', E_USER_DEPRECATED);
}
if (isset($options['pipeline'])) {
$expectedIndex = 0;
foreach ($options['pipeline'] as $i => $operation) {
if ($i !== $expectedIndex) {
throw new InvalidArgumentException(sprintf('The "pipeline" option is not a list (unexpected index: "%s")', $i));
}
if (! is_array($operation) && ! is_object($operation)) {
throw InvalidArgumentException::invalidType(sprintf('$options["pipeline"][%d]', $i), $operation, 'array or object');
}
$expectedIndex += 1;
}
}
$this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName;
$this->options = $options;
@@ -206,19 +267,10 @@ class CreateCollection implements Executable
* @see Executable::execute()
* @param Server $server
* @return array|object Command result document
* @throws UnsupportedException if collation or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions());
if (isset($this->options['typeMap'])) {
@@ -237,13 +289,13 @@ class CreateCollection implements Executable
{
$cmd = ['create' => $this->collectionName];
foreach (['autoIndexId', 'capped', 'flags', 'max', 'maxTimeMS', 'size', 'validationAction', 'validationLevel'] as $option) {
foreach (['autoIndexId', 'capped', 'comment', 'expireAfterSeconds', 'flags', 'max', 'maxTimeMS', 'pipeline', 'size', 'validationAction', 'validationLevel', 'viewOn'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
foreach (['collation', 'indexOptionDefaults', 'storageEngine', 'validator'] as $option) {
foreach (['changeStreamPreAndPostImages', 'clusteredIndex', 'collation', 'encryptedFields', 'indexOptionDefaults', 'storageEngine', 'timeseries', 'validator'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = (object) $this->options[$option];
}
@@ -255,7 +307,7 @@ class CreateCollection implements Executable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
+14 -33
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,6 +25,7 @@ use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\Model\IndexInput;
use function array_map;
use function is_array;
use function is_integer;
@@ -38,16 +39,10 @@ use function sprintf;
* @api
* @see \MongoDB\Collection::createIndex()
* @see \MongoDB\Collection::createIndexes()
* @see http://docs.mongodb.org/manual/reference/command/createIndexes/
* @see https://mongodb.com/docs/manual/reference/command/createIndexes/
*/
class CreateIndexes implements Executable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForWriteConcern = 5;
/** @var integer */
private static $wireVersionForCommitQuorum = 9;
@@ -60,9 +55,6 @@ class CreateIndexes implements Executable
/** @var array */
private $indexes = [];
/** @var boolean */
private $isCollationUsed = false;
/** @var array */
private $options = [];
@@ -71,6 +63,10 @@ class CreateIndexes implements Executable
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * commitQuorum (integer|string): Specifies how many data-bearing members
* of a replica set, including the primary, must complete the index
* builds successfully before the primary marks the indexes as ready.
@@ -80,13 +76,8 @@ class CreateIndexes implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array[] $indexes List of index specifications
@@ -110,10 +101,6 @@ class CreateIndexes implements Executable
throw InvalidArgumentException::invalidType(sprintf('$index[%d]', $i), $index, 'array');
}
if (isset($index['collation'])) {
$this->isCollationUsed = true;
}
$this->indexes[] = new IndexInput($index);
$expectedIndex += 1;
@@ -150,19 +137,11 @@ class CreateIndexes implements Executable
* @see Executable::execute()
* @param Server $server
* @return string[] The names of the created indexes
* @throws UnsupportedException if collation or write concern is used and unsupported
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if ($this->isCollationUsed && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
@@ -178,7 +157,7 @@ class CreateIndexes implements Executable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
@@ -220,8 +199,10 @@ class CreateIndexes implements Executable
$cmd['commitQuorum'] = $this->options['commitQuorum'];
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
foreach (['comment', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
$server->executeWriteCommand($this->databaseName, new Command($cmd), $this->createOptions());
+4 -5
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,6 +23,7 @@ use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use function is_array;
use function is_object;
@@ -56,8 +57,6 @@ class DatabaseCommand implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server).
*
@@ -110,7 +109,7 @@ class DatabaseCommand implements Executable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @return array
*/
private function createOptions()
+54 -21
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,9 +25,11 @@ use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function is_array;
use function is_object;
use function is_string;
use function MongoDB\is_write_concern_acknowledged;
use function MongoDB\server_supports_feature;
/**
@@ -37,15 +39,12 @@ use function MongoDB\server_supports_feature;
* classes.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/delete/
* @see https://mongodb.com/docs/manual/reference/command/delete/
*/
class Delete implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var int */
private static $wireVersionForHintServerSideError = 5;
private static $wireVersionForHint = 9;
/** @var string */
private $databaseName;
@@ -69,8 +68,9 @@ class Delete implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -79,9 +79,12 @@ class Delete implements Executable, Explainable
* This is not supported for server versions < 4.4 and will result in an
* exception at execution time if used.
*
* * session (MongoDB\Driver\Session): Client session.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* Sessions are not supported for server versions < 3.6.
* * session (MongoDB\Driver\Session): Client session.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
@@ -120,6 +123,10 @@ class Delete implements Executable, Explainable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], 'array or object');
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
@@ -137,18 +144,17 @@ class Delete implements Executable, Explainable
* @see Executable::execute()
* @param Server $server
* @return DeleteResult
* @throws UnsupportedException if hint or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
/* Server versions >= 3.4.0 raise errors for unknown update
* options. For previous versions, the CRUD spec requires a client-side
* error. */
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
/* CRUD spec requires a client-side error when using "hint" with an
* unacknowledged write concern on an unsupported server. */
if (
isset($this->options['writeConcern']) && ! is_write_concern_acknowledged($this->options['writeConcern']) &&
isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHint)
) {
throw UnsupportedException::hintNotSupported();
}
@@ -157,7 +163,7 @@ class Delete implements Executable, Explainable
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$bulk = new Bulk();
$bulk = new Bulk($this->createBulkWriteOptions());
$bulk->delete($this->filter, $this->createDeleteOptions());
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
@@ -165,6 +171,13 @@ class Delete implements Executable, Explainable
return new DeleteResult($writeResult);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
$cmd = ['delete' => $this->collectionName, 'deletes' => [['q' => $this->filter] + $this->createDeleteOptions()]];
@@ -176,6 +189,26 @@ class Delete implements Executable, Explainable
return $cmd;
}
/**
* Create options for constructing the bulk write.
*
* @see https://php.net/manual/en/mongodb-driver-bulkwrite.construct.php
*/
private function createBulkWriteOptions(): array
{
$options = [];
if (isset($this->options['comment'])) {
$options['comment'] = $this->options['comment'];
}
if (isset($this->options['let'])) {
$options['let'] = (object) $this->options['let'];
}
return $options;
}
/**
* Create options for the delete command.
*
@@ -202,7 +235,7 @@ class Delete implements Executable, Explainable
/**
* Create options for executing the bulk write.
*
* @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @see https://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @return array
*/
private function createExecuteOptions()
+18 -7
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,7 +28,7 @@ use MongoDB\Exception\UnsupportedException;
*
* @api
* @see \MongoDB\Collection::deleteOne()
* @see http://docs.mongodb.org/manual/reference/command/delete/
* @see https://mongodb.com/docs/manual/reference/command/delete/
*/
class DeleteMany implements Executable, Explainable
{
@@ -42,8 +42,9 @@ class DeleteMany implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -52,9 +53,12 @@ class DeleteMany implements Executable, Explainable
* This is not supported for server versions < 4.4 and will result in an
* exception at execution time if used.
*
* * session (MongoDB\Driver\Session): Client session.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* Sessions are not supported for server versions < 3.6.
* * session (MongoDB\Driver\Session): Client session.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
@@ -83,6 +87,13 @@ class DeleteMany implements Executable, Explainable
return $this->delete->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->delete->getCommandDocument($server);
+18 -7
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -28,7 +28,7 @@ use MongoDB\Exception\UnsupportedException;
*
* @api
* @see \MongoDB\Collection::deleteOne()
* @see http://docs.mongodb.org/manual/reference/command/delete/
* @see https://mongodb.com/docs/manual/reference/command/delete/
*/
class DeleteOne implements Executable, Explainable
{
@@ -42,8 +42,9 @@ class DeleteOne implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -52,9 +53,12 @@ class DeleteOne implements Executable, Explainable
* This is not supported for server versions < 4.4 and will result in an
* exception at execution time if used.
*
* * session (MongoDB\Driver\Session): Client session.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* Sessions are not supported for server versions < 3.6.
* * session (MongoDB\Driver\Session): Client session.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
@@ -83,6 +87,13 @@ class DeleteOne implements Executable, Explainable
return $this->delete->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->delete->getCommandDocument($server);
+20 -29
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,28 +26,22 @@ use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_integer;
use function is_object;
use function MongoDB\create_field_path_type_map;
use function MongoDB\server_supports_feature;
/**
* Operation for the distinct command.
*
* @api
* @see \MongoDB\Collection::distinct()
* @see http://docs.mongodb.org/manual/reference/command/distinct/
* @see https://mongodb.com/docs/manual/reference/command/distinct/
*/
class Distinct implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var string */
private $databaseName;
@@ -70,23 +64,19 @@ class Distinct implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * typeMap (array): Type map for BSON deserialization.
*
* @param string $databaseName Database name
@@ -144,19 +134,11 @@ class Distinct implements Executable, Explainable
* @param Server $server
* @return mixed[]
* @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation or read concern is used and unsupported
* @throws UnsupportedException if read concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['readConcern']) && ! server_supports_feature($server, self::$wireVersionForReadConcern)) {
throw UnsupportedException::readConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['readConcern'])) {
throw UnsupportedException::readConcernNotSupportedInTransaction();
@@ -177,6 +159,13 @@ class Distinct implements Executable, Explainable
return $result->values;
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->createCommandDocument();
@@ -202,8 +191,10 @@ class Distinct implements Executable, Explainable
$cmd['collation'] = (object) $this->options['collation'];
}
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
foreach (['comment', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return $cmd;
@@ -212,7 +203,7 @@ class Distinct implements Executable, Explainable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @return array
*/
private function createOptions()
+30 -28
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,9 +24,9 @@ use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function MongoDB\server_supports_feature;
/**
* Operation for the drop command.
@@ -34,19 +34,13 @@ use function MongoDB\server_supports_feature;
* @api
* @see \MongoDB\Collection::drop()
* @see \MongoDB\Database::dropCollection()
* @see http://docs.mongodb.org/manual/reference/command/drop/
* @see https://mongodb.com/docs/manual/reference/command/drop/
*/
class DropCollection implements Executable
{
/** @var integer */
private static $errorCodeNamespaceNotFound = 26;
/** @var string */
private static $errorMessageNamespaceNotFound = 'ns not found';
/** @var integer */
private static $wireVersionForWriteConcern = 5;
/** @var string */
private $databaseName;
@@ -61,18 +55,17 @@ class DropCollection implements Executable
*
* Supported options:
*
* * session (MongoDB\Driver\Session): Client session.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* Sessions are not supported for server versions < 3.6.
* This is not supported for servers versions < 4.4.
*
* * session (MongoDB\Driver\Session): Client session.
*
* * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $options Command options
@@ -107,30 +100,23 @@ class DropCollection implements Executable
* @see Executable::execute()
* @param Server $server
* @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$command = new Command(['drop' => $this->collectionName]);
try {
$cursor = $server->executeWriteCommand($this->databaseName, $command, $this->createOptions());
$cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions());
} catch (CommandException $e) {
/* The server may return an error if the collection does not exist.
* Check for an error code (or message for pre-3.2 servers) and
* return the command reply instead of throwing. */
if ($e->getCode() === self::$errorCodeNamespaceNotFound ||
$e->getMessage() === self::$errorMessageNamespaceNotFound) {
* Check for an error code and return the command reply instead of
* throwing. */
if ($e->getCode() === self::$errorCodeNamespaceNotFound) {
return $e->getResultDocument();
}
@@ -144,10 +130,26 @@ class DropCollection implements Executable
return current($cursor->toArray());
}
/**
* Create the drop command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['drop' => $this->collectionName];
if (isset($this->options['comment'])) {
$cmd['comment'] = $this->options['comment'];
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
+26 -21
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,10 +23,9 @@ use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function MongoDB\server_supports_feature;
/**
* Operation for the dropDatabase command.
@@ -34,13 +33,10 @@ use function MongoDB\server_supports_feature;
* @api
* @see \MongoDB\Client::dropDatabase()
* @see \MongoDB\Database::drop()
* @see http://docs.mongodb.org/manual/reference/command/dropDatabase/
* @see https://mongodb.com/docs/manual/reference/command/dropDatabase/
*/
class DropDatabase implements Executable
{
/** @var integer */
private static $wireVersionForWriteConcern = 5;
/** @var string */
private $databaseName;
@@ -52,18 +48,17 @@ class DropDatabase implements Executable
*
* Supported options:
*
* * session (MongoDB\Driver\Session): Client session.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* Sessions are not supported for server versions < 3.6.
* This is not supported for servers versions < 4.4.
*
* * session (MongoDB\Driver\Session): Client session.
*
* * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
@@ -96,17 +91,11 @@ class DropDatabase implements Executable
* @see Executable::execute()
* @param Server $server
* @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$command = new Command(['dropDatabase' => 1]);
$cursor = $server->executeWriteCommand($this->databaseName, $command, $this->createOptions());
$cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
@@ -115,10 +104,26 @@ class DropDatabase implements Executable
return current($cursor->toArray());
}
/**
* Create the dropDatabase command.
*
* @return Command
*/
private function createCommand()
{
$cmd = ['dropDatabase' => 1];
if (isset($this->options['comment'])) {
$cmd['comment'] = $this->options['comment'];
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
+14 -20
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,23 +24,20 @@ use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_integer;
use function MongoDB\server_supports_feature;
/**
* Operation for the dropIndexes command.
*
* @api
* @see \MongoDB\Collection::dropIndexes()
* @see http://docs.mongodb.org/manual/reference/command/dropIndexes/
* @see https://mongodb.com/docs/manual/reference/command/dropIndexes/
*/
class DropIndexes implements Executable
{
/** @var integer */
private static $wireVersionForWriteConcern = 5;
/** @var string */
private $databaseName;
@@ -58,21 +55,20 @@ class DropIndexes implements Executable
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param string $indexName Index name (use "*" to drop all indexes)
@@ -119,15 +115,11 @@ class DropIndexes implements Executable
* @see Executable::execute()
* @param Server $server
* @return array|object Command result document
* @throws UnsupportedException if writeConcern is used and unsupported
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
@@ -154,8 +146,10 @@ class DropIndexes implements Executable
'index' => $this->indexName,
];
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
foreach (['comment', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return new Command($cmd);
@@ -164,7 +158,7 @@ class DropIndexes implements Executable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,18 +18,23 @@
namespace MongoDB\Operation;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\ReadConcern;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use function array_intersect_key;
use function is_integer;
/**
* Operation for obtaining an estimated count of documents in a collection
*
* @api
* @see \MongoDB\Collection::estimatedDocumentCount()
* @see http://docs.mongodb.org/manual/reference/command/count/
* @see https://mongodb.com/docs/manual/reference/command/count/
*/
class EstimatedDocumentCount implements Executable, Explainable
{
@@ -42,28 +47,31 @@ class EstimatedDocumentCount implements Executable, Explainable
/** @var array */
private $options;
/** @var Count */
private $count;
/** @var int */
private static $errorCodeCollectionNotFound = 26;
/** @var int */
private static $wireVersionForCollStats = 12;
/**
* Constructs a count command.
* Constructs a command to get the estimated number of documents in a
* collection.
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $options Command options
@@ -73,9 +81,24 @@ class EstimatedDocumentCount implements Executable, Explainable
{
$this->databaseName = (string) $databaseName;
$this->collectionName = (string) $collectionName;
$this->options = array_intersect_key($options, ['maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1]);
$this->count = $this->createCount();
if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) {
throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) {
throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class);
}
if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) {
throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class);
}
if (isset($options['session']) && ! $options['session'] instanceof Session) {
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
}
$this->options = array_intersect_key($options, ['comment' => 1, 'maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1]);
}
/**
@@ -90,18 +113,22 @@ class EstimatedDocumentCount implements Executable, Explainable
*/
public function execute(Server $server)
{
return $this->count->execute($server);
}
public function getCommandDocument(Server $server)
{
return $this->count->getCommandDocument($server);
return $this->createCount()->execute($server);
}
/**
* @return Count
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
private function createCount()
public function getCommandDocument(Server $server)
{
return $this->createCount()->getCommandDocument($server);
}
private function createCount(): Count
{
return new Count($this->databaseName, $this->collectionName, [], $this->options);
}
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
+43 -29
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2018 MongoDB, Inc.
* Copyright 2018-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,11 +18,13 @@
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_string;
@@ -33,23 +35,17 @@ use function MongoDB\server_supports_feature;
*
* @api
* @see \MongoDB\Collection::explain()
* @see http://docs.mongodb.org/manual/reference/command/explain/
* @see https://mongodb.com/docs/manual/reference/command/explain/
*/
class Explain implements Executable
{
const VERBOSITY_ALL_PLANS = 'allPlansExecution';
const VERBOSITY_EXEC_STATS = 'executionStats';
const VERBOSITY_QUERY = 'queryPlanner';
public const VERBOSITY_ALL_PLANS = 'allPlansExecution';
public const VERBOSITY_EXEC_STATS = 'executionStats';
public const VERBOSITY_QUERY = 'queryPlanner';
/** @var integer */
private static $wireVersionForAggregate = 7;
/** @var integer */
private static $wireVersionForDistinct = 4;
/** @var integer */
private static $wireVersionForFindAndModify = 4;
/** @var string */
private $databaseName;
@@ -64,6 +60,10 @@ class Explain implements Executable
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * session (MongoDB\Driver\Session): Client session.
@@ -101,27 +101,22 @@ class Explain implements Executable
$this->options = $options;
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|object
* @throws UnsupportedException if the server does not support explaining the operation
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if ($this->explainable instanceof Distinct && ! server_supports_feature($server, self::$wireVersionForDistinct)) {
throw UnsupportedException::explainNotSupported();
}
if ($this->isFindAndModify($this->explainable) && ! server_supports_feature($server, self::$wireVersionForFindAndModify)) {
throw UnsupportedException::explainNotSupported();
}
if ($this->explainable instanceof Aggregate && ! server_supports_feature($server, self::$wireVersionForAggregate)) {
throw UnsupportedException::explainNotSupported();
}
$cmd = ['explain' => $this->explainable->getCommandDocument($server)];
if (isset($this->options['verbosity'])) {
$cmd['verbosity'] = $this->options['verbosity'];
}
$cursor = $server->executeCommand($this->databaseName, new Command($cmd), $this->createOptions());
$cursor = $server->executeCommand($this->databaseName, $this->createCommand($server), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
@@ -130,10 +125,29 @@ class Explain implements Executable
return current($cursor->toArray());
}
/**
* Create the explain command.
*
* @param Server $server
* @return Command
*/
private function createCommand(Server $server)
{
$cmd = ['explain' => $this->explainable->getCommandDocument($server)];
foreach (['comment', 'verbosity'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @return array
*/
private function createOptions()
@@ -151,7 +165,7 @@ class Explain implements Executable
return $options;
}
private function isFindAndModify($explainable)
private function isFindAndModify(Explainable $explainable): bool
{
if ($explainable instanceof FindAndModify || $explainable instanceof FindOneAndDelete || $explainable instanceof FindOneAndReplace || $explainable instanceof FindOneAndUpdate) {
return true;
+8 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2018 MongoDB, Inc.
* Copyright 2018-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -27,5 +27,11 @@ use MongoDB\Driver\Server;
*/
interface Explainable extends Executable
{
/**
* Returns the command document for this operation.
*
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server);
}
+38 -49
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,13 +26,14 @@ use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function is_array;
use function is_bool;
use function is_integer;
use function is_object;
use function is_string;
use function MongoDB\server_supports_feature;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
@@ -40,23 +41,14 @@ use const E_USER_DEPRECATED;
*
* @api
* @see \MongoDB\Collection::find()
* @see http://docs.mongodb.org/manual/tutorial/query-documents/
* @see http://docs.mongodb.org/manual/reference/operator/query-modifier/
* @see https://mongodb.com/docs/manual/tutorial/query-documents/
* @see https://mongodb.com/docs/manual/reference/operator/query-modifier/
*/
class Find implements Executable, Explainable
{
const NON_TAILABLE = 1;
const TAILABLE = 2;
const TAILABLE_AWAIT = 3;
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForAllowDiskUseServerSideError = 4;
public const NON_TAILABLE = 1;
public const TAILABLE = 2;
public const TAILABLE_AWAIT = 3;
/** @var string */
private $databaseName;
@@ -77,7 +69,7 @@ class Find implements Executable, Explainable
*
* * allowDiskUse (boolean): Enables writing to temporary files. When set
* to true, queries can write data to the _tmp sub-directory in the
* dbPath directory. The default is false.
* dbPath directory.
*
* * allowPartialResults (boolean): Get partial results from a mongos if
* some shards are inaccessible (instead of throwing an error).
@@ -86,11 +78,9 @@ class Find implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* * comment (string): Attaches a comment to the query. If "$comment" also
* exists in the modifiers document, this option will take precedence.
* Only string values are supported for server versions < 4.4.
*
* * cursorType (enum): Indicates the type of cursor to use. Must be either
* NON_TAILABLE, TAILABLE, or TAILABLE_AWAIT. The default is
@@ -134,9 +124,6 @@ class Find implements Executable, Explainable
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * returnKey (boolean): If true, returns only the index keys in the
@@ -144,8 +131,6 @@ class Find implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * showRecordId (boolean): Determines whether to return the record
* identifier for each document. If true, adds a field $recordId to the
* returned documents.
@@ -161,6 +146,11 @@ class Find implements Executable, Explainable
* "$orderby" also exists in the modifiers document, this option will
* take precedence.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * typeMap (array): Type map for BSON deserialization. This will be
* applied to the returned Cursor (it is not sent to the server).
*
@@ -192,18 +182,16 @@ class Find implements Executable, Explainable
throw InvalidArgumentException::invalidType('"collation" option', $options['collation'], 'array or object');
}
if (isset($options['comment']) && ! is_string($options['comment'])) {
throw InvalidArgumentException::invalidType('"comment" option', $options['comment'], 'comment');
}
if (isset($options['cursorType'])) {
if (! is_integer($options['cursorType'])) {
throw InvalidArgumentException::invalidType('"cursorType" option', $options['cursorType'], 'integer');
}
if ($options['cursorType'] !== self::NON_TAILABLE &&
if (
$options['cursorType'] !== self::NON_TAILABLE &&
$options['cursorType'] !== self::TAILABLE &&
$options['cursorType'] !== self::TAILABLE_AWAIT) {
$options['cursorType'] !== self::TAILABLE_AWAIT
) {
throw new InvalidArgumentException('Invalid value for "cursorType" option: ' . $options['cursorType']);
}
}
@@ -288,6 +276,10 @@ class Find implements Executable, Explainable
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], 'array or object');
}
if (isset($options['readConcern']) && $options['readConcern']->isDefault()) {
unset($options['readConcern']);
}
@@ -312,23 +304,11 @@ class Find implements Executable, Explainable
* @see Executable::execute()
* @param Server $server
* @return Cursor
* @throws UnsupportedException if collation or read concern is used and unsupported
* @throws UnsupportedException if read concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['readConcern']) && ! server_supports_feature($server, self::$wireVersionForReadConcern)) {
throw UnsupportedException::readConcernNotSupported();
}
if (isset($this->options['allowDiskUse']) && ! server_supports_feature($server, self::$wireVersionForAllowDiskUseServerSideError)) {
throw UnsupportedException::allowDiskUseNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['readConcern'])) {
throw UnsupportedException::readConcernNotSupportedInTransaction();
@@ -343,6 +323,13 @@ class Find implements Executable, Explainable
return $cursor;
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->createCommandDocument();
@@ -351,7 +338,7 @@ class Find implements Executable, Explainable
/**
* Construct a command document for Find
*/
private function createCommandDocument()
private function createCommandDocument(): array
{
$cmd = ['find' => $this->collectionName, 'filter' => (object) $this->filter];
@@ -383,6 +370,7 @@ class Find implements Executable, Explainable
$options[$modifier[0]] = $options['modifiers'][$modifier[1]];
}
}
unset($options['modifiers']);
return $cmd + $options;
@@ -391,7 +379,7 @@ class Find implements Executable, Explainable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executequery.php
* @see https://php.net/manual/en/mongodb-driver-server.executequery.php
* @return array
*/
private function createExecuteOptions()
@@ -425,6 +413,7 @@ class Find implements Executable, Explainable
if ($this->options['cursorType'] === self::TAILABLE) {
$options['tailable'] = true;
}
if ($this->options['cursorType'] === self::TAILABLE_AWAIT) {
$options['tailable'] = true;
$options['awaitData'] = true;
@@ -437,7 +426,7 @@ class Find implements Executable, Explainable
}
}
foreach (['collation', 'max', 'min'] as $option) {
foreach (['collation', 'let', 'max', 'min'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = (object) $this->options[$option];
}
+57 -83
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,6 +25,8 @@ use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use function array_key_exists;
use function current;
use function is_array;
use function is_bool;
@@ -33,6 +35,7 @@ use function is_object;
use function is_string;
use function MongoDB\create_field_path_type_map;
use function MongoDB\is_pipeline;
use function MongoDB\is_write_concern_acknowledged;
use function MongoDB\server_supports_feature;
/**
@@ -42,27 +45,15 @@ use function MongoDB\server_supports_feature;
* FindOneAndUpdate operation classes.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
*/
class FindAndModify implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForArrayFilters = 6;
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var integer */
private static $wireVersionForHint = 9;
/** @var integer */
private static $wireVersionForHintServerSideError = 8;
/** @var integer */
private static $wireVersionForWriteConcern = 4;
private static $wireVersionForUnsupportedOptionServerSideError = 8;
/** @var string */
private $databaseName;
@@ -81,20 +72,15 @@ class FindAndModify implements Executable, Explainable
* * arrayFilters (document array): A set of filters specifying to which
* array elements an update should apply.
*
* This is not supported for server versions < 3.6 and will result in an
* exception at execution time if used.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * fields (document): Limits the fields to return for the matching
* document.
*
@@ -119,8 +105,6 @@ class FindAndModify implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
@@ -133,10 +117,12 @@ class FindAndModify implements Executable, Explainable
* matches the query. This option is ignored for remove operations. The
* default is false.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
@@ -145,11 +131,7 @@ class FindAndModify implements Executable, Explainable
*/
public function __construct($databaseName, $collectionName, array $options)
{
$options += [
'new' => false,
'remove' => false,
'upsert' => false,
];
$options += ['remove' => false];
if (isset($options['arrayFilters']) && ! is_array($options['arrayFilters'])) {
throw InvalidArgumentException::invalidType('"arrayFilters" option', $options['arrayFilters'], 'array');
@@ -175,7 +157,7 @@ class FindAndModify implements Executable, Explainable
throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer');
}
if (! is_bool($options['new'])) {
if (array_key_exists('new', $options) && ! is_bool($options['new'])) {
throw InvalidArgumentException::invalidType('"new" option', $options['new'], 'boolean');
}
@@ -207,10 +189,18 @@ class FindAndModify implements Executable, Explainable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (! is_bool($options['upsert'])) {
if (array_key_exists('upsert', $options) && ! is_bool($options['upsert'])) {
throw InvalidArgumentException::invalidType('"upsert" option', $options['upsert'], 'boolean');
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], 'array or object');
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
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');
}
@@ -231,29 +221,24 @@ class FindAndModify implements Executable, Explainable
* @param Server $server
* @return array|object|null
* @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if array filters, collation, or write concern is used and unsupported
* @throws UnsupportedException if hint or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['arrayFilters']) && ! server_supports_feature($server, self::$wireVersionForArrayFilters)) {
throw UnsupportedException::arrayFiltersNotSupported();
}
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
/* Server versions >= 4.1.10 raise errors for unknown findAndModify
* options (SERVER-40005), but the CRUD spec requires client-side errors
* for server versions < 4.2. For later versions, we'll rely on the
* server to either utilize the option or report its own error. */
if (isset($this->options['hint']) && ! $this->isHintSupported($server)) {
/* Server versions >= 4.2.0 raise errors for unsupported update options.
* For previous versions, the CRUD spec requires a client-side error. */
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForUnsupportedOptionServerSideError)) {
throw UnsupportedException::hintNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
/* CRUD spec requires a client-side error when using "hint" with an
* unacknowledged write concern on an unsupported server. */
if (
isset($this->options['writeConcern']) && ! is_write_concern_acknowledged($this->options['writeConcern']) &&
isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHint)
) {
throw UnsupportedException::hintNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
@@ -261,7 +246,7 @@ class FindAndModify implements Executable, Explainable
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$cursor = $server->executeWriteCommand($this->databaseName, new Command($this->createCommandDocument($server)), $this->createOptions());
$cursor = $server->executeWriteCommand($this->databaseName, new Command($this->createCommandDocument()), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap(create_field_path_type_map($this->options['typeMap'], 'value'));
@@ -272,29 +257,40 @@ class FindAndModify implements Executable, Explainable
return $result->value ?? null;
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->createCommandDocument($server);
return $this->createCommandDocument();
}
/**
* Create the findAndModify command document.
*
* @param Server $server
* @return array
*/
private function createCommandDocument(Server $server)
private function createCommandDocument()
{
$cmd = ['findAndModify' => $this->collectionName];
if ($this->options['remove']) {
$cmd['remove'] = true;
} else {
$cmd['new'] = $this->options['new'];
$cmd['upsert'] = $this->options['upsert'];
if (isset($this->options['new'])) {
$cmd['new'] = $this->options['new'];
}
if (isset($this->options['upsert'])) {
$cmd['upsert'] = $this->options['upsert'];
}
}
foreach (['collation', 'fields', 'query', 'sort'] as $option) {
foreach (['collation', 'fields', 'let', 'query', 'sort'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = (object) $this->options[$option];
}
@@ -306,25 +302,19 @@ class FindAndModify implements Executable, Explainable
: (object) $this->options['update'];
}
foreach (['arrayFilters', 'hint', 'maxTimeMS'] as $option) {
foreach (['arrayFilters', 'bypassDocumentValidation', 'comment', 'hint', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
return $cmd;
}
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
@@ -341,20 +331,4 @@ class FindAndModify implements Executable, Explainable
return $options;
}
private function isAcknowledgedWriteConcern() : bool
{
if (! isset($this->options['writeConcern'])) {
return true;
}
return $this->options['writeConcern']->getW() > 1 || $this->options['writeConcern']->getJournal();
}
private function isHintSupported(Server $server) : bool
{
$requiredWireVersion = $this->isAcknowledgedWriteConcern() ? self::$wireVersionForHintServerSideError : self::$wireVersionForHint;
return server_supports_feature($server, $requiredWireVersion);
}
}
+19 -13
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,7 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
/**
@@ -28,8 +29,8 @@ use function current;
*
* @api
* @see \MongoDB\Collection::findOne()
* @see http://docs.mongodb.org/manual/tutorial/query-documents/
* @see http://docs.mongodb.org/manual/reference/operator/query-modifier/
* @see https://mongodb.com/docs/manual/tutorial/query-documents/
* @see https://mongodb.com/docs/manual/reference/operator/query-modifier/
*/
class FindOne implements Executable, Explainable
{
@@ -43,11 +44,9 @@ class FindOne implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* * comment (string): Attaches a comment to the query. If "$comment" also
* exists in the modifiers document, this option will take precedence.
* Only string values are supported for server versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -74,9 +73,6 @@ class FindOne implements Executable, Explainable
*
* * readConcern (MongoDB\Driver\ReadConcern): Read concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* * returnKey (boolean): If true, returns only the index keys in the
@@ -84,8 +80,6 @@ class FindOne implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * showRecordId (boolean): Determines whether to return the record
* identifier for each document. If true, adds a field $recordId to the
* returned documents.
@@ -96,6 +90,11 @@ class FindOne implements Executable, Explainable
* "$orderby" also exists in the modifiers document, this option will
* take precedence.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * typeMap (array): Type map for BSON deserialization.
*
* @param string $databaseName Database name
@@ -131,6 +130,13 @@ class FindOne implements Executable, Explainable
return $document === false ? null : $document;
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->find->getCommandDocument($server);
+19 -10
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,7 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function is_array;
use function is_object;
@@ -29,7 +30,7 @@ use function is_object;
*
* @api
* @see \MongoDB\Collection::findOneAndDelete()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
*/
class FindOneAndDelete implements Executable, Explainable
{
@@ -43,8 +44,9 @@ class FindOneAndDelete implements Executable, Explainable
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -61,18 +63,18 @@ class FindOneAndDelete implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * typeMap (array): Type map for BSON deserialization.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array|object $filter Query by which to filter documents
@@ -116,6 +118,13 @@ class FindOneAndDelete implements Executable, Explainable
return $this->findAndModify->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->findAndModify->getCommandDocument($server);
+31 -24
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,8 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function array_key_exists;
use function is_array;
use function is_integer;
use function is_object;
@@ -31,12 +33,12 @@ use function MongoDB\is_first_key_operator;
*
* @api
* @see \MongoDB\Collection::findOneAndReplace()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
*/
class FindOneAndReplace implements Executable, Explainable
{
const RETURN_DOCUMENT_BEFORE = 1;
const RETURN_DOCUMENT_AFTER = 2;
public const RETURN_DOCUMENT_BEFORE = 1;
public const RETURN_DOCUMENT_AFTER = 2;
/** @var FindAndModify */
private $findAndModify;
@@ -49,13 +51,11 @@ class FindOneAndReplace implements Executable, Explainable
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -78,8 +78,6 @@ class FindOneAndReplace implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
@@ -88,10 +86,12 @@ class FindOneAndReplace implements Executable, Explainable
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
@@ -114,21 +114,19 @@ class FindOneAndReplace implements Executable, Explainable
throw new InvalidArgumentException('First key in $replacement argument is an update operator');
}
$options += [
'returnDocument' => self::RETURN_DOCUMENT_BEFORE,
'upsert' => false,
];
if (isset($options['projection']) && ! is_array($options['projection']) && ! is_object($options['projection'])) {
throw InvalidArgumentException::invalidType('"projection" option', $options['projection'], 'array or object');
}
if (! is_integer($options['returnDocument'])) {
if (array_key_exists('returnDocument', $options) && ! is_integer($options['returnDocument'])) {
throw InvalidArgumentException::invalidType('"returnDocument" option', $options['returnDocument'], 'integer');
}
if ($options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE) {
if (
isset($options['returnDocument']) &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE
) {
throw new InvalidArgumentException('Invalid value for "returnDocument" option: ' . $options['returnDocument']);
}
@@ -136,7 +134,9 @@ class FindOneAndReplace implements Executable, Explainable
$options['fields'] = $options['projection'];
}
$options['new'] = $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER;
if (isset($options['returnDocument'])) {
$options['new'] = $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER;
}
unset($options['projection'], $options['returnDocument']);
@@ -161,6 +161,13 @@ class FindOneAndReplace implements Executable, Explainable
return $this->findAndModify->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->findAndModify->getCommandDocument($server);
+31 -24
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -21,6 +21,8 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function array_key_exists;
use function is_array;
use function is_integer;
use function is_object;
@@ -32,12 +34,12 @@ use function MongoDB\is_pipeline;
*
* @api
* @see \MongoDB\Collection::findOneAndUpdate()
* @see http://docs.mongodb.org/manual/reference/command/findAndModify/
* @see https://mongodb.com/docs/manual/reference/command/findAndModify/
*/
class FindOneAndUpdate implements Executable, Explainable
{
const RETURN_DOCUMENT_BEFORE = 1;
const RETURN_DOCUMENT_AFTER = 2;
public const RETURN_DOCUMENT_BEFORE = 1;
public const RETURN_DOCUMENT_AFTER = 2;
/** @var FindAndModify */
private $findAndModify;
@@ -53,13 +55,11 @@ class FindOneAndUpdate implements Executable, Explainable
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -82,8 +82,6 @@ class FindOneAndUpdate implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * sort (document): Determines which document the operation modifies if
* the query selects multiple documents.
*
@@ -92,10 +90,12 @@ class FindOneAndUpdate implements Executable, Explainable
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
@@ -118,21 +118,19 @@ class FindOneAndUpdate implements Executable, Explainable
throw new InvalidArgumentException('Expected an update document with operator as first key or a pipeline');
}
$options += [
'returnDocument' => self::RETURN_DOCUMENT_BEFORE,
'upsert' => false,
];
if (isset($options['projection']) && ! is_array($options['projection']) && ! is_object($options['projection'])) {
throw InvalidArgumentException::invalidType('"projection" option', $options['projection'], 'array or object');
}
if (! is_integer($options['returnDocument'])) {
if (array_key_exists('returnDocument', $options) && ! is_integer($options['returnDocument'])) {
throw InvalidArgumentException::invalidType('"returnDocument" option', $options['returnDocument'], 'integer');
}
if ($options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE) {
if (
isset($options['returnDocument']) &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_AFTER &&
$options['returnDocument'] !== self::RETURN_DOCUMENT_BEFORE
) {
throw new InvalidArgumentException('Invalid value for "returnDocument" option: ' . $options['returnDocument']);
}
@@ -140,7 +138,9 @@ class FindOneAndUpdate implements Executable, Explainable
$options['fields'] = $options['projection'];
}
$options['new'] = $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER;
if (isset($options['returnDocument'])) {
$options['new'] = $options['returnDocument'] === self::RETURN_DOCUMENT_AFTER;
}
unset($options['projection'], $options['returnDocument']);
@@ -165,6 +165,13 @@ class FindOneAndUpdate implements Executable, Explainable
return $this->findAndModify->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->findAndModify->getCommandDocument($server);
+37 -24
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,10 +25,10 @@ use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\InsertManyResult;
use function is_array;
use function is_bool;
use function is_object;
use function MongoDB\server_supports_feature;
use function sprintf;
/**
@@ -36,13 +36,10 @@ use function sprintf;
*
* @api
* @see \MongoDB\Collection::insertMany()
* @see http://docs.mongodb.org/manual/reference/command/insert/
* @see https://mongodb.com/docs/manual/reference/command/insert/
*/
class InsertMany implements Executable
{
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var string */
private $databaseName;
@@ -63,8 +60,10 @@ class InsertMany implements Executable
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
* * comment (mixed): BSON value to attach as a comment to the command(s)
* associated with this insert.
*
* This is not supported for servers versions < 4.4.
*
* * ordered (boolean): If true, when an insert fails, return without
* performing the remaining writes. If false, when a write fails,
@@ -72,8 +71,6 @@ class InsertMany implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
@@ -120,6 +117,10 @@ class InsertMany implements Executable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
@@ -136,6 +137,7 @@ class InsertMany implements Executable
* @see Executable::execute()
* @param Server $server
* @return InsertManyResult
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
@@ -145,33 +147,44 @@ class InsertMany implements Executable
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$options = ['ordered' => $this->options['ordered']];
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$bulk = new Bulk($this->createBulkWriteOptions());
$insertedIds = [];
foreach ($this->documents as $i => $document) {
$insertedIds[$i] = $bulk->insert($document);
}
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createOptions());
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
return new InsertManyResult($writeResult, $insertedIds);
}
/**
* Create options for executing the bulk write.
* Create options for constructing the bulk write.
*
* @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @see https://php.net/manual/en/mongodb-driver-bulkwrite.construct.php
* @return array
*/
private function createOptions()
private function createBulkWriteOptions()
{
$options = ['ordered' => $this->options['ordered']];
foreach (['bypassDocumentValidation', 'comment'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = $this->options[$option];
}
}
return $options;
}
/**
* Create options for executing the bulk write.
*
* @see https://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @return array
*/
private function createExecuteOptions()
{
$options = [];
+36 -24
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,23 +25,20 @@ use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\InsertOneResult;
use function is_array;
use function is_bool;
use function is_object;
use function MongoDB\server_supports_feature;
/**
* Operation for inserting a single document with the insert command.
*
* @api
* @see \MongoDB\Collection::insertOne()
* @see http://docs.mongodb.org/manual/reference/command/insert/
* @see https://mongodb.com/docs/manual/reference/command/insert/
*/
class InsertOne implements Executable
{
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var string */
private $databaseName;
@@ -62,13 +59,12 @@ class InsertOne implements Executable
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
@@ -95,6 +91,10 @@ class InsertOne implements Executable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
@@ -111,38 +111,50 @@ class InsertOne implements Executable
* @see Executable::execute()
* @param Server $server
* @return InsertOneResult
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
$options = [];
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if (isset($this->options['writeConcern']) && $inTransaction) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$options['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($options);
$bulk = new Bulk($this->createBulkWriteOptions());
$insertedId = $bulk->insert($this->document);
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createOptions());
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
return new InsertOneResult($writeResult, $insertedId);
}
/**
* Create options for executing the bulk write.
* Create options for constructing the bulk write.
*
* @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @see https://php.net/manual/en/mongodb-driver-bulkwrite.construct.php
* @return array
*/
private function createOptions()
private function createBulkWriteOptions()
{
$options = [];
foreach (['bypassDocumentValidation', 'comment'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = $this->options[$option];
}
}
return $options;
}
/**
* Create options for executing the bulk write.
*
* @see https://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @return array
*/
private function createExecuteOptions()
{
$options = [];
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,7 +29,7 @@ use MongoDB\Model\CallbackIterator;
*
* @api
* @see \MongoDB\Database::listCollectionNames()
* @see http://docs.mongodb.org/manual/reference/command/listCollections/
* @see https://mongodb.com/docs/manual/reference/command/listCollections/
*/
class ListCollectionNames implements Executable
{
@@ -41,6 +41,15 @@ class ListCollectionNames implements Executable
*
* Supported options:
*
* * authorizedCollections (boolean): Determines which collections are
* returned based on the user privileges.
*
* For servers < 4.0, this option is ignored.
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter collections.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
@@ -48,8 +57,6 @@ class ListCollectionNames implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param string $databaseName Database name
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
@@ -67,7 +74,7 @@ class ListCollectionNames implements Executable
* @return Iterator
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server) : Iterator
public function execute(Server $server): Iterator
{
return new CallbackIterator(
$this->listCollections->execute($server),
+12 -5
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -29,7 +29,7 @@ use MongoDB\Model\CollectionInfoIterator;
*
* @api
* @see \MongoDB\Database::listCollections()
* @see http://docs.mongodb.org/manual/reference/command/listCollections/
* @see https://mongodb.com/docs/manual/reference/command/listCollections/
*/
class ListCollections implements Executable
{
@@ -44,6 +44,15 @@ class ListCollections implements Executable
*
* Supported options:
*
* * authorizedCollections (boolean): Determines which collections are
* returned based on the user privileges.
*
* For servers < 4.0, this option is ignored.
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter collections.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
@@ -51,8 +60,6 @@ class ListCollections implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param string $databaseName Database name
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
@@ -6,7 +6,7 @@
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -24,6 +24,7 @@ use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use function array_column;
/**
@@ -31,7 +32,7 @@ use function array_column;
*
* @api
* @see \MongoDB\Client::listDatabaseNames()
* @see http://docs.mongodb.org/manual/reference/command/ListDatabases/
* @see https://mongodb.com/docs/manual/reference/command/listDatabases/#mongodb-dbcommand-dbcmd.listDatabases
*/
class ListDatabaseNames implements Executable
{
@@ -48,17 +49,17 @@ class ListDatabaseNames implements Executable
*
* For servers < 4.0.5, this option is ignored.
*
* * filter (document): Query by which to filter databases.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* For servers < 3.6, this option is ignored.
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter databases.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
*/
@@ -76,7 +77,7 @@ class ListDatabaseNames implements Executable
* @throws UnexpectedValueException if the command response was malformed
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server) : Iterator
public function execute(Server $server): Iterator
{
$result = $this->listDatabases->execute($server);
+7 -7
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -30,7 +30,7 @@ use MongoDB\Model\DatabaseInfoLegacyIterator;
*
* @api
* @see \MongoDB\Client::listDatabases()
* @see http://docs.mongodb.org/manual/reference/command/ListDatabases/
* @see https://mongodb.com/docs/manual/reference/command/listDatabases/#mongodb-dbcommand-dbcmd.listDatabases`
*/
class ListDatabases implements Executable
{
@@ -47,17 +47,17 @@ class ListDatabases implements Executable
*
* For servers < 4.0.5, this option is ignored.
*
* * filter (document): Query by which to filter databases.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* For servers < 3.6, this option is ignored.
* This is not supported for servers versions < 4.4.
*
* * filter (document): Query by which to filter databases.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
*/
+15 -9
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,7 @@ namespace MongoDB\Operation;
use EmptyIterator;
use MongoDB\Driver\Command;
use MongoDB\Driver\Exception\CommandException;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
@@ -26,6 +27,7 @@ use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Model\CachingIterator;
use MongoDB\Model\IndexInfoIterator;
use MongoDB\Model\IndexInfoIteratorIterator;
use function is_integer;
/**
@@ -33,7 +35,7 @@ use function is_integer;
*
* @api
* @see \MongoDB\Collection::listIndexes()
* @see http://docs.mongodb.org/manual/reference/command/listIndexes/
* @see https://mongodb.com/docs/manual/reference/command/listIndexes/
*/
class ListIndexes implements Executable
{
@@ -57,13 +59,15 @@ class ListIndexes implements Executable
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * maxTimeMS (integer): The maximum amount of time to allow the query to
* run.
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param array $options Command options
@@ -103,7 +107,7 @@ class ListIndexes implements Executable
* Note: read preference is intentionally omitted, as the spec requires that
* the command be executed on the primary.
*
* @see http://php.net/manual/en/mongodb-driver-server.executecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executecommand.php
* @return array
*/
private function createOptions()
@@ -129,13 +133,15 @@ class ListIndexes implements Executable
{
$cmd = ['listIndexes' => $this->collectionName];
if (isset($this->options['maxTimeMS'])) {
$cmd['maxTimeMS'] = $this->options['maxTimeMS'];
foreach (['comment', 'maxTimeMS'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
try {
$cursor = $server->executeReadCommand($this->databaseName, new Command($cmd), $this->createOptions());
} catch (DriverRuntimeException $e) {
} catch (CommandException $e) {
/* The server may return an error if the collection does not exist.
* Check for possible error codes (see: SERVER-20463) and return an
* empty iterator instead of throwing.
+19 -54
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -31,6 +31,7 @@ use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\MapReduceResult;
use stdClass;
use function current;
use function is_array;
use function is_bool;
@@ -39,8 +40,8 @@ use function is_object;
use function is_string;
use function MongoDB\create_field_path_type_map;
use function MongoDB\is_mapreduce_output_inline;
use function MongoDB\server_supports_feature;
use function trigger_error;
use const E_USER_DEPRECATED;
/**
@@ -48,22 +49,10 @@ use const E_USER_DEPRECATED;
*
* @api
* @see \MongoDB\Collection::mapReduce()
* @see https://docs.mongodb.com/manual/reference/command/mapReduce/
* @see https://mongodb.com/docs/manual/reference/command/mapReduce/
*/
class MapReduce implements Executable
{
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var integer */
private static $wireVersionForReadConcern = 4;
/** @var integer */
private static $wireVersionForWriteConcern = 4;
/** @var string */
private $databaseName;
@@ -111,13 +100,11 @@ class MapReduce implements Executable
* circumvent document level validation. This only applies when results
* are output to a collection.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * finalize (MongoDB\BSON\JavascriptInterface): Follows the reduce method
* and modifies the output.
@@ -140,9 +127,6 @@ class MapReduce implements Executable
* * readConcern (MongoDB\Driver\ReadConcern): Read concern. This is not
* supported when results are returned inline.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* * readPreference (MongoDB\Driver\ReadPreference): Read preference.
*
* This option is ignored if results are output to a collection.
@@ -152,8 +136,6 @@ class MapReduce implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * sort (document): Sorts the input documents. This option is useful for
* optimization. For example, specify the sort key to be the same as the
* emit key so that there are fewer reduce operations. The sort key must
@@ -168,9 +150,6 @@ class MapReduce implements Executable
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern. This only
* applies when results are output to a collection.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection name
* @param JavascriptInterface $map Map function
@@ -245,6 +224,10 @@ class MapReduce implements Executable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['readConcern']) && $options['readConcern']->isDefault()) {
unset($options['readConcern']);
}
@@ -283,28 +266,17 @@ class MapReduce implements Executable
* @param Server $server
* @return MapReduceResult
* @throws UnexpectedValueException if the command response was malformed
* @throws UnsupportedException if collation, read concern, or write concern is used and unsupported
* @throws UnsupportedException if read concern or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
if (isset($this->options['readConcern']) && ! server_supports_feature($server, self::$wireVersionForReadConcern)) {
throw UnsupportedException::readConcernNotSupported();
}
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction) {
if (isset($this->options['readConcern'])) {
throw UnsupportedException::readConcernNotSupportedInTransaction();
}
if (isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
@@ -312,7 +284,7 @@ class MapReduce implements Executable
$hasOutputCollection = ! is_mapreduce_output_inline($this->out);
$command = $this->createCommand($server);
$command = $this->createCommand();
$options = $this->createOptions($hasOutputCollection);
/* If the mapReduce operation results in a write, use
@@ -360,10 +332,9 @@ class MapReduce implements Executable
/**
* Create the mapReduce command.
*
* @param Server $server
* @return Command
*/
private function createCommand(Server $server)
private function createCommand()
{
$cmd = [
'mapReduce' => $this->collectionName,
@@ -372,7 +343,7 @@ class MapReduce implements Executable
'out' => $this->out,
];
foreach (['finalize', 'jsMode', 'limit', 'maxTimeMS', 'verbose'] as $option) {
foreach (['bypassDocumentValidation', 'comment', 'finalize', 'jsMode', 'limit', 'maxTimeMS', 'verbose'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
@@ -384,12 +355,6 @@ class MapReduce implements Executable
}
}
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
return new Command($cmd);
}
@@ -430,8 +395,8 @@ class MapReduce implements Executable
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see http://php.net/manual/en/mongodb-driver-server.executereadwritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadcommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executereadwritecommand.php
* @param boolean $hasOutputCollection
* @return array
*/
+21 -16
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2018 MongoDB, Inc.
* Copyright 2018-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -23,17 +23,16 @@ use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function MongoDB\server_supports_feature;
/**
* Operation for the collMod command.
*
* @api
* @see \MongoDB\Database::modifyCollection()
* @see http://docs.mongodb.org/manual/reference/command/collMod/
* @see https://mongodb.com/docs/manual/reference/command/collMod/
*/
class ModifyCollection implements Executable
{
@@ -54,18 +53,17 @@ class ModifyCollection implements Executable
*
* Supported options:
*
* * session (MongoDB\Driver\Session): Client session.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* Sessions are not supported for server versions < 3.6.
* This is not supported for servers versions < 4.4.
*
* * session (MongoDB\Driver\Session): Client session.
*
* * typeMap (array): Type map for BSON deserialization. This will only be
* used for the returned command result document.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* This is not supported for server versions < 3.2 and will result in an
* exception at execution time if used.
*
* @param string $databaseName Database name
* @param string $collectionName Collection or view to modify
* @param array $collectionOptions Collection or view options to assign
@@ -110,11 +108,7 @@ class ModifyCollection implements Executable
*/
public function execute(Server $server)
{
if (isset($this->options['writeConcern']) && ! server_supports_feature($server, self::$wireVersionForWriteConcern)) {
throw UnsupportedException::writeConcernNotSupported();
}
$cursor = $server->executeWriteCommand($this->databaseName, new Command(['collMod' => $this->collectionName] + $this->collectionOptions), $this->createOptions());
$cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
@@ -123,10 +117,21 @@ class ModifyCollection implements Executable
return current($cursor->toArray());
}
private function createCommand(): Command
{
$cmd = ['collMod' => $this->collectionName] + $this->collectionOptions;
if (isset($this->options['comment'])) {
$cmd['comment'] = $this->options['comment'];
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* @see http://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
@@ -0,0 +1,169 @@
<?php
/*
* Copyright 2021-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
namespace MongoDB\Operation;
use MongoDB\Driver\Command;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use function current;
use function is_array;
use function is_bool;
/**
* Operation for the renameCollection command.
*
* @api
* @see \MongoDB\Collection::rename()
* @see \MongoDB\Database::renameCollection()
* @see https://mongodb.com/docs/manual/reference/command/renameCollection/
*/
class RenameCollection implements Executable
{
/** @var string */
private $fromNamespace;
/** @var string */
private $toNamespace;
/** @var array */
private $options;
/**
* Constructs a renameCollection command.
*
* Supported options:
*
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * session (MongoDB\Driver\Session): Client session.
*
* * typeMap (array): Type map for BSON deserialization. This will be used
* for the returned command result document.
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* * dropTarget (boolean): If true, MongoDB will drop the target before
* renaming the collection.
*
* @param string $fromDatabaseName Database name
* @param string $fromCollectionName Collection name
* @param string $toDatabaseName New database name
* @param string $toCollectionName New collection name
* @param array $options Command options
* @throws InvalidArgumentException for parameter/option parsing errors
*/
public function __construct(string $fromDatabaseName, string $fromCollectionName, string $toDatabaseName, string $toCollectionName, array $options = [])
{
if (isset($options['session']) && ! $options['session'] instanceof Session) {
throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class);
}
if (isset($options['typeMap']) && ! is_array($options['typeMap'])) {
throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array');
}
if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) {
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
if (isset($options['dropTarget']) && ! is_bool($options['dropTarget'])) {
throw InvalidArgumentException::invalidType('"dropTarget" option', $options['dropTarget'], 'boolean');
}
$this->fromNamespace = $fromDatabaseName . '.' . $fromCollectionName;
$this->toNamespace = $toDatabaseName . '.' . $toCollectionName;
$this->options = $options;
}
/**
* Execute the operation.
*
* @see Executable::execute()
* @param Server $server
* @return array|object Command result document
* @throws UnsupportedException if write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
$inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction();
if ($inTransaction && isset($this->options['writeConcern'])) {
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$cursor = $server->executeWriteCommand('admin', $this->createCommand(), $this->createOptions());
if (isset($this->options['typeMap'])) {
$cursor->setTypeMap($this->options['typeMap']);
}
return current($cursor->toArray());
}
/**
* Create the renameCollection command.
*
* @return Command
*/
private function createCommand()
{
$cmd = [
'renameCollection' => $this->fromNamespace,
'to' => $this->toNamespace,
];
foreach (['comment', 'dropTarget'] as $option) {
if (isset($this->options[$option])) {
$cmd[$option] = $this->options[$option];
}
}
return new Command($cmd);
}
/**
* Create options for executing the command.
*
* @see https://php.net/manual/en/mongodb-driver-server.executewritecommand.php
* @return array
*/
private function createOptions()
{
$options = [];
if (isset($this->options['session'])) {
$options['session'] = $this->options['session'];
}
if (isset($this->options['writeConcern'])) {
$options['writeConcern'] = $this->options['writeConcern'];
}
return $options;
}
}
+12 -10
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@ use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\UpdateResult;
use function is_array;
use function is_object;
use function MongoDB\is_first_key_operator;
@@ -32,7 +33,7 @@ use function MongoDB\is_pipeline;
*
* @api
* @see \MongoDB\Collection::replaceOne()
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
*/
class ReplaceOne implements Executable
{
@@ -47,13 +48,11 @@ class ReplaceOne implements Executable
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -64,11 +63,14 @@ class ReplaceOne implements Executable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
+65 -52
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -25,12 +25,14 @@ use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\UpdateResult;
use function is_array;
use function is_bool;
use function is_object;
use function is_string;
use function MongoDB\is_first_key_operator;
use function MongoDB\is_pipeline;
use function MongoDB\is_write_concern_acknowledged;
use function MongoDB\server_supports_feature;
/**
@@ -40,21 +42,12 @@ use function MongoDB\server_supports_feature;
* operation classes.
*
* @internal
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
*/
class Update implements Executable, Explainable
{
/** @var integer */
private static $wireVersionForArrayFilters = 6;
/** @var integer */
private static $wireVersionForCollation = 5;
/** @var integer */
private static $wireVersionForDocumentLevelValidation = 4;
/** @var integer */
private static $wireVersionForHintServerSideError = 5;
private static $wireVersionForHint = 8;
/** @var string */
private $databaseName;
@@ -79,19 +72,14 @@ class Update implements Executable, Explainable
* * arrayFilters (document array): A set of filters specifying to which
* array elements an update should apply.
*
* This is not supported for server versions < 3.6 and will result in an
* exception at execution time if used.
*
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -106,11 +94,14 @@ class Update implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
@@ -172,6 +163,14 @@ class Update implements Executable, Explainable
throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class);
}
if (isset($options['let']) && ! is_array($options['let']) && ! is_object($options['let'])) {
throw InvalidArgumentException::invalidType('"let" option', $options['let'], 'array or object');
}
if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) {
unset($options['bypassDocumentValidation']);
}
if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) {
unset($options['writeConcern']);
}
@@ -189,23 +188,17 @@ class Update implements Executable, Explainable
* @see Executable::execute()
* @param Server $server
* @return UpdateResult
* @throws UnsupportedException if array filters or collation is used and unsupported
* @throws UnsupportedException if hint or write concern is used and unsupported
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
*/
public function execute(Server $server)
{
if (isset($this->options['arrayFilters']) && ! server_supports_feature($server, self::$wireVersionForArrayFilters)) {
throw UnsupportedException::arrayFiltersNotSupported();
}
if (isset($this->options['collation']) && ! server_supports_feature($server, self::$wireVersionForCollation)) {
throw UnsupportedException::collationNotSupported();
}
/* Server versions >= 3.4.0 raise errors for unknown update
* options. For previous versions, the CRUD spec requires a client-side
* error. */
if (isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHintServerSideError)) {
/* CRUD spec requires a client-side error when using "hint" with an
* unacknowledged write concern on an unsupported server. */
if (
isset($this->options['writeConcern']) && ! is_write_concern_acknowledged($this->options['writeConcern']) &&
isset($this->options['hint']) && ! server_supports_feature($server, self::$wireVersionForHint)
) {
throw UnsupportedException::hintNotSupported();
}
@@ -214,15 +207,7 @@ class Update implements Executable, Explainable
throw UnsupportedException::writeConcernNotSupportedInTransaction();
}
$bulkOptions = [];
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$bulkOptions['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
$bulk = new Bulk($bulkOptions);
$bulk = new Bulk($this->createBulkWriteOptions());
$bulk->update($this->filter, $this->update, $this->createUpdateOptions());
$writeResult = $server->executeBulkWrite($this->databaseName . '.' . $this->collectionName, $bulk, $this->createExecuteOptions());
@@ -230,27 +215,55 @@ class Update implements Executable, Explainable
return new UpdateResult($writeResult);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
$cmd = ['update' => $this->collectionName, 'updates' => [['q' => $this->filter, 'u' => $this->update] + $this->createUpdateOptions()]];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = $this->options['writeConcern'];
if (isset($this->options['bypassDocumentValidation'])) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
}
if (! empty($this->options['bypassDocumentValidation']) &&
server_supports_feature($server, self::$wireVersionForDocumentLevelValidation)
) {
$cmd['bypassDocumentValidation'] = $this->options['bypassDocumentValidation'];
if (isset($this->options['writeConcern'])) {
$cmd['writeConcern'] = $this->options['writeConcern'];
}
return $cmd;
}
/**
* Create options for constructing the bulk write.
*
* @see https://php.net/manual/en/mongodb-driver-bulkwrite.construct.php
* @return array
*/
private function createBulkWriteOptions()
{
$options = [];
foreach (['bypassDocumentValidation', 'comment'] as $option) {
if (isset($this->options[$option])) {
$options[$option] = $this->options[$option];
}
}
if (isset($this->options['let'])) {
$options['let'] = (object) $this->options['let'];
}
return $options;
}
/**
* Create options for executing the bulk write.
*
* @see http://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @see https://php.net/manual/en/mongodb-driver-server.executebulkwrite.php
* @return array
*/
private function createExecuteOptions()
+19 -13
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@ use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\UpdateResult;
use function is_array;
use function is_object;
use function MongoDB\is_first_key_operator;
@@ -32,7 +33,7 @@ use function MongoDB\is_pipeline;
*
* @api
* @see \MongoDB\Collection::updateMany()
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
*/
class UpdateMany implements Executable, Explainable
{
@@ -47,19 +48,14 @@ class UpdateMany implements Executable, Explainable
* * arrayFilters (document array): A set of filters specifying to which
* array elements an update should apply.
*
* This is not supported for server versions < 3.6 and will result in an$
* exception at execution time if used.
*
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -70,11 +66,14 @@ class UpdateMany implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
@@ -117,6 +116,13 @@ class UpdateMany implements Executable, Explainable
return $this->update->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->update->getCommandDocument($server);
+19 -13
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -22,6 +22,7 @@ use MongoDB\Driver\Server;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\UpdateResult;
use function is_array;
use function is_object;
use function MongoDB\is_first_key_operator;
@@ -32,7 +33,7 @@ use function MongoDB\is_pipeline;
*
* @api
* @see \MongoDB\Collection::updateOne()
* @see http://docs.mongodb.org/manual/reference/command/update/
* @see https://mongodb.com/docs/manual/reference/command/update/
*/
class UpdateOne implements Executable, Explainable
{
@@ -47,19 +48,14 @@ class UpdateOne implements Executable, Explainable
* * arrayFilters (document array): A set of filters specifying to which
* array elements an update should apply.
*
* This is not supported for server versions < 3.6 and will result in an$
* exception at execution time if used.
*
* * bypassDocumentValidation (boolean): If true, allows the write to
* circumvent document level validation.
*
* For servers < 3.2, this option is ignored as document level validation
* is not available.
*
* * collation (document): Collation specification.
*
* This is not supported for server versions < 3.4 and will result in an
* exception at execution time if used.
* * comment (mixed): BSON value to attach as a comment to this command.
*
* This is not supported for servers versions < 4.4.
*
* * hint (string|document): The index to use. Specify either the index
* name as a string or the index key pattern as a document. If specified,
@@ -70,11 +66,14 @@ class UpdateOne implements Executable, Explainable
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
*
* * upsert (boolean): When true, a new document is created if no document
* matches the query. The default is false.
*
* * let (document): Map of parameter names and values. Values must be
* constant or closed expressions that do not reference document fields.
* Parameters can then be accessed as variables in an aggregate
* expression context (e.g. "$$var").
*
* * writeConcern (MongoDB\Driver\WriteConcern): Write concern.
*
* @param string $databaseName Database name
@@ -117,6 +116,13 @@ class UpdateOne implements Executable, Explainable
return $this->update->execute($server);
}
/**
* Returns the command document for this operation.
*
* @see Explainable::getCommandDocument()
* @param Server $server
* @return array
*/
public function getCommandDocument(Server $server)
{
return $this->update->getCommandDocument($server);
+67 -22
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2017 MongoDB, Inc.
* Copyright 2017-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -32,10 +32,13 @@ use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\UnexpectedValueException;
use MongoDB\Exception\UnsupportedException;
use MongoDB\Model\ChangeStreamIterator;
use function array_intersect_key;
use function array_key_exists;
use function array_unshift;
use function count;
use function is_array;
use function is_bool;
use function is_object;
use function is_string;
use function MongoDB\Driver\Monitoring\addSubscriber;
@@ -51,12 +54,18 @@ use function MongoDB\server_supports_feature;
*
* @api
* @see \MongoDB\Collection::watch()
* @see https://docs.mongodb.com/manual/changeStreams/
* @see https://mongodb.com/docs/manual/changeStreams/
*/
class Watch implements Executable, /* @internal */ CommandSubscriber
{
const FULL_DOCUMENT_DEFAULT = 'default';
const FULL_DOCUMENT_UPDATE_LOOKUP = 'updateLookup';
public const FULL_DOCUMENT_DEFAULT = 'default';
public const FULL_DOCUMENT_UPDATE_LOOKUP = 'updateLookup';
public const FULL_DOCUMENT_WHEN_AVAILABLE = 'whenAvailable';
public const FULL_DOCUMENT_REQUIRED = 'required';
public const FULL_DOCUMENT_BEFORE_CHANGE_OFF = 'off';
public const FULL_DOCUMENT_BEFORE_CHANGE_WHEN_AVAILABLE = 'whenAvailable';
public const FULL_DOCUMENT_BEFORE_CHANGE_REQUIRED = 'required';
/** @var integer */
private static $wireVersionForStartAtOperationTime = 7;
@@ -103,15 +112,37 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
*
* * collation (document): Specifies a collation.
*
* * fullDocument (string): Determines whether the "fullDocument" field
* will be populated for update operations. By default, change streams
* only return the delta of fields during the update operation (via the
* "updateDescription" field). To additionally return the most current
* majority-committed version of the updated document, specify
* "updateLookup" for this option. Defaults to "default".
* * comment (mixed): BSON value to attach as a comment to this command.
*
* Insert and replace operations always include the "fullDocument" field
* and delete operations omit the field as the document no longer exists.
* Only string values are supported for server versions < 4.4.
*
* * fullDocument (string): Determines how the "fullDocument" response
* field will be populated for update operations.
*
* By default, change streams only return the delta of fields (via an
* "updateDescription" field) for update operations and "fullDocument" is
* omitted. Insert and replace operations always include the
* "fullDocument" field. Delete operations omit the field as the document
* no longer exists.
*
* Specify "updateLookup" to return the current majority-committed
* version of the updated document.
*
* MongoDB 6.0+ allows returning the post-image of the modified document
* if the collection has changeStreamPreAndPostImages enabled. Specify
* "whenAvailable" to return the post-image if available or a null value
* if not. Specify "required" to return the post-image if available or
* raise an error if not.
*
* * fullDocumentBeforeChange (string): Determines how the
* "fullDocumentBeforeChange" response field will be populated. By
* default, the field is omitted.
*
* MongoDB 6.0+ allows returning the pre-image of the modified document
* if the collection has changeStreamPreAndPostImages enabled. Specify
* "whenAvailable" to return the pre-image if available or a null value
* if not. Specify "required" to return the pre-image if available or
* raise an error if not.
*
* * maxAwaitTimeMS (integer): The maximum amount of time for the server to
* wait on new documents to satisfy a change stream query.
@@ -131,7 +162,10 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
*
* * session (MongoDB\Driver\Session): Client session.
*
* Sessions are not supported for server versions < 3.6.
* * showExpandedEvents (boolean): Enables the server to send the expanded
* list of change stream events.
*
* This option is not supported for server versions < 6.0.
*
* * startAfter (document): Specifies the logical starting point for the
* new change stream. Unlike "resumeAfter", this option can be used with
@@ -174,14 +208,17 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
}
$options += [
'fullDocument' => self::FULL_DOCUMENT_DEFAULT,
'readPreference' => new ReadPreference(ReadPreference::RP_PRIMARY),
];
if (! is_string($options['fullDocument'])) {
if (array_key_exists('fullDocument', $options) && ! is_string($options['fullDocument'])) {
throw InvalidArgumentException::invalidType('"fullDocument" option', $options['fullDocument'], 'string');
}
if (isset($options['fullDocumentBeforeChange']) && ! is_string($options['fullDocumentBeforeChange'])) {
throw InvalidArgumentException::invalidType('"fullDocumentBeforeChange" option', $options['fullDocumentBeforeChange'], 'string');
}
if (! $options['readPreference'] instanceof ReadPreference) {
throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class);
}
@@ -198,6 +235,10 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
throw InvalidArgumentException::invalidType('"startAtOperationTime" option', $options['startAtOperationTime'], TimestampInterface::class);
}
if (isset($options['showExpandedEvents']) && ! is_bool($options['showExpandedEvents'])) {
throw InvalidArgumentException::invalidType('"showExpandedEvents" option', $options['showExpandedEvents'], 'bool');
}
/* In the absence of an explicit session, create one to ensure that the
* initial aggregation and any resume attempts can use the same session
* ("implicit from the user's perspective" per PHPLIB-342). Since this
@@ -212,8 +253,8 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
}
}
$this->aggregateOptions = array_intersect_key($options, ['batchSize' => 1, 'collation' => 1, 'maxAwaitTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1, 'typeMap' => 1]);
$this->changeStreamOptions = array_intersect_key($options, ['fullDocument' => 1, 'resumeAfter' => 1, 'startAfter' => 1, 'startAtOperationTime' => 1]);
$this->aggregateOptions = array_intersect_key($options, ['batchSize' => 1, 'collation' => 1, 'comment' => 1, 'maxAwaitTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1, 'typeMap' => 1]);
$this->changeStreamOptions = array_intersect_key($options, ['fullDocument' => 1, 'fullDocumentBeforeChange' => 1, 'resumeAfter' => 1, 'showExpandedEvents' => 1, 'startAfter' => 1, 'startAtOperationTime' => 1]);
// Null database name implies a cluster-wide change stream
if ($databaseName === null) {
@@ -264,8 +305,10 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
$this->postBatchResumeToken = $reply->cursor->postBatchResumeToken;
}
if ($this->shouldCaptureOperationTime($event->getServer()) &&
isset($reply->operationTime) && $reply->operationTime instanceof TimestampInterface) {
if (
$this->shouldCaptureOperationTime($event->getServer()) &&
isset($reply->operationTime) && $reply->operationTime instanceof TimestampInterface
) {
$this->operationTime = $reply->operationTime;
}
}
@@ -419,9 +462,11 @@ class Watch implements Executable, /* @internal */ CommandSubscriber
return false;
}
if (isset($this->changeStreamOptions['resumeAfter']) ||
if (
isset($this->changeStreamOptions['resumeAfter']) ||
isset($this->changeStreamOptions['startAfter']) ||
isset($this->changeStreamOptions['startAtOperationTime'])) {
isset($this->changeStreamOptions['startAtOperationTime'])
) {
return false;
}
+7 -3
View File
@@ -6,6 +6,7 @@ use Exception;
use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Driver\Session;
use Throwable;
use function call_user_func;
use function time;
@@ -69,7 +70,8 @@ class WithTransaction
$session->abortTransaction();
}
if ($e instanceof RuntimeException &&
if (
$e instanceof RuntimeException &&
$e->hasErrorLabel('TransientTransactionError') &&
! $this->isTransactionTimeLimitExceeded($startTime)
) {
@@ -88,7 +90,8 @@ class WithTransaction
try {
$session->commitTransaction();
} catch (RuntimeException $e) {
if ($e->getCode() !== 50 /* MaxTimeMSExpired */ &&
if (
$e->getCode() !== 50 /* MaxTimeMSExpired */ &&
$e->hasErrorLabel('UnknownTransactionCommitResult') &&
! $this->isTransactionTimeLimitExceeded($startTime)
) {
@@ -96,7 +99,8 @@ class WithTransaction
continue;
}
if ($e->hasErrorLabel('TransientTransactionError') &&
if (
$e->hasErrorLabel('TransientTransactionError') &&
! $this->isTransactionTimeLimitExceeded($startTime)
) {
// Restart the transaction, invoking the callback again
+2 -2
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
+165 -15
View File
@@ -1,12 +1,12 @@
<?php
/*
* Copyright 2015-2017 MongoDB, Inc.
* Copyright 2015-present MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,15 +19,19 @@ namespace MongoDB;
use Exception;
use MongoDB\BSON\Serializable;
use MongoDB\Driver\Exception\RuntimeException as DriverRuntimeException;
use MongoDB\Driver\Manager;
use MongoDB\Driver\ReadPreference;
use MongoDB\Driver\Server;
use MongoDB\Driver\Session;
use MongoDB\Driver\WriteConcern;
use MongoDB\Exception\InvalidArgumentException;
use MongoDB\Exception\RuntimeException;
use MongoDB\Operation\ListCollections;
use MongoDB\Operation\WithTransaction;
use ReflectionClass;
use ReflectionException;
use function end;
use function get_object_vars;
use function in_array;
@@ -40,6 +44,32 @@ use function MongoDB\BSON\toPHP;
use function reset;
use function substr;
/**
* Check whether all servers support executing a write stage on a secondary.
*
* @internal
* @param Server[] $servers
*/
function all_servers_support_write_stage_on_secondary(array $servers): bool
{
/* Write stages on secondaries are technically supported by FCV 4.4, but the
* CRUD spec requires all 5.0+ servers since FCV is not tracked by SDAM. */
static $wireVersionForWriteStageOnSecondary = 13;
foreach ($servers as $server) {
// We can assume that load balancers only front 5.0+ servers
if ($server->getType() === Server::TYPE_LOAD_BALANCER) {
continue;
}
if (! server_supports_feature($server, $wireVersionForWriteStageOnSecondary)) {
return false;
}
}
return true;
}
/**
* Applies a type map to a document.
*
@@ -71,7 +101,7 @@ function apply_type_map_to_document($document, array $typeMap)
* @return string
* @throws InvalidArgumentException
*/
function generate_index_name($document)
function generate_index_name($document): string
{
if ($document instanceof Serializable) {
$document = $document->bsonSerialize();
@@ -94,6 +124,53 @@ function generate_index_name($document)
return $name;
}
/**
* Return a collection's encryptedFields from the encryptedFieldsMap
* autoEncryption driver option (if available).
*
* @internal
* @see https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#drop-collection-helper
* @see Collection::drop
* @see Database::createCollection
* @see Database::dropCollection
* @return array|object|null
*/
function get_encrypted_fields_from_driver(string $databaseName, string $collectionName, Manager $manager)
{
$encryptedFieldsMap = (array) $manager->getEncryptedFieldsMap();
return $encryptedFieldsMap[$databaseName . '.' . $collectionName] ?? null;
}
/**
* Return a collection's encryptedFields option from the server (if any).
*
* @internal
* @see https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#drop-collection-helper
* @see Collection::drop
* @see Database::dropCollection
* @return array|object|null
*/
function get_encrypted_fields_from_server(string $databaseName, string $collectionName, Manager $manager, Server $server)
{
// No-op if the encryptedFieldsMap autoEncryption driver option was omitted
if ($manager->getEncryptedFieldsMap() === null) {
return null;
}
$collectionInfoIterator = (new ListCollections($databaseName, ['filter' => ['name' => $collectionName]]))->execute($server);
foreach ($collectionInfoIterator as $collectionInfo) {
/* Note: ListCollections applies a typeMap that converts BSON documents
* to PHP arrays. This should not be problematic as encryptedFields here
* is only used by drop helpers to obtain names of supporting encryption
* collections. */
return $collectionInfo['options']['encryptedFields'] ?? null;
}
return null;
}
/**
* Return whether the first key in the document starts with a "$" character.
*
@@ -104,7 +181,7 @@ function generate_index_name($document)
* @return boolean
* @throws InvalidArgumentException
*/
function is_first_key_operator($document)
function is_first_key_operator($document): bool
{
if ($document instanceof Serializable) {
$document = $document->bsonSerialize();
@@ -131,7 +208,7 @@ function is_first_key_operator($document)
* @param mixed $pipeline
* @return boolean
*/
function is_pipeline($pipeline)
function is_pipeline($pipeline): bool
{
if (! is_array($pipeline)) {
return false;
@@ -172,7 +249,7 @@ function is_pipeline($pipeline)
* @param array $options Command options
* @return boolean
*/
function is_in_transaction(array $options)
function is_in_transaction(array $options): bool
{
if (isset($options['session']) && $options['session'] instanceof Session && $options['session']->isInTransaction()) {
return true;
@@ -191,7 +268,7 @@ function is_in_transaction(array $options)
* @param array $pipeline List of pipeline operations
* @return boolean
*/
function is_last_pipeline_operator_write(array $pipeline)
function is_last_pipeline_operator_write(array $pipeline): bool
{
$lastOp = end($pipeline);
@@ -210,12 +287,12 @@ function is_last_pipeline_operator_write(array $pipeline)
* This is used to determine if a mapReduce command requires a primary.
*
* @internal
* @see https://docs.mongodb.com/manual/reference/command/mapReduce/#output-inline
* @see https://mongodb.com/docs/manual/reference/command/mapReduce/#output-inline
* @param string|array|object $out Output specification
* @return boolean
* @throws InvalidArgumentException
*/
function is_mapreduce_output_inline($out)
function is_mapreduce_output_inline($out): bool
{
if (! is_array($out) && ! is_object($out)) {
return false;
@@ -238,6 +315,25 @@ function is_mapreduce_output_inline($out)
return key($out) === 'inline';
}
/**
* Return whether the write concern is acknowledged.
*
* This function is similar to mongoc_write_concern_is_acknowledged but does not
* check the fsync option since that was never supported in the PHP driver.
*
* @internal
* @see https://mongodb.com/docs/manual/reference/write-concern/
* @param WriteConcern $writeConcern
* @return boolean
*/
function is_write_concern_acknowledged(WriteConcern $writeConcern): bool
{
/* Note: -1 corresponds to MONGOC_WRITE_CONCERN_W_ERRORS_IGNORED, which is
* deprecated synonym of MONGOC_WRITE_CONCERN_W_UNACKNOWLEDGED and slated
* for removal in libmongoc 2.0. */
return ($writeConcern->getW() !== 0 && $writeConcern->getW() !== -1) || $writeConcern->getJournal() === true;
}
/**
* Return whether the server supports a particular feature.
*
@@ -246,7 +342,7 @@ function is_mapreduce_output_inline($out)
* @param integer $feature Feature constant (i.e. wire protocol version)
* @return boolean
*/
function server_supports_feature(Server $server, $feature)
function server_supports_feature(Server $server, int $feature): bool
{
$info = $server->getInfo();
$maxWireVersion = isset($info['maxWireVersion']) ? (integer) $info['maxWireVersion'] : 0;
@@ -255,11 +351,19 @@ function server_supports_feature(Server $server, $feature)
return $minWireVersion <= $feature && $maxWireVersion >= $feature;
}
function is_string_array($input)
/**
* Return whether the input is an array of strings.
*
* @internal
* @param mixed $input
* @return boolean
*/
function is_string_array($input): bool
{
if (! is_array($input)) {
return false;
}
foreach ($input as $item) {
if (! is_string($item)) {
return false;
@@ -315,7 +419,7 @@ function recursive_copy($element)
* @param string $fieldPath The field path to apply the root type to
* @return array
*/
function create_field_path_type_map(array $typeMap, $fieldPath)
function create_field_path_type_map(array $typeMap, string $fieldPath): array
{
// If some field paths already exist, we prefix them with the field path we are assuming as the new root
if (isset($typeMap['fieldPaths']) && is_array($typeMap['fieldPaths'])) {
@@ -383,7 +487,7 @@ function with_transaction(Session $session, callable $callback, array $transacti
* @param array $options
* @return Session|null
*/
function extract_session_from_options(array $options)
function extract_session_from_options(array $options): ?Session
{
if (! isset($options['session']) || ! $options['session'] instanceof Session) {
return null;
@@ -399,7 +503,7 @@ function extract_session_from_options(array $options)
* @param array $options
* @return ReadPreference|null
*/
function extract_read_preference_from_options(array $options)
function extract_read_preference_from_options(array $options): ?ReadPreference
{
if (! isset($options['readPreference']) || ! $options['readPreference'] instanceof ReadPreference) {
return null;
@@ -415,7 +519,7 @@ function extract_read_preference_from_options(array $options)
* @internal
* @return Server
*/
function select_server(Manager $manager, array $options)
function select_server(Manager $manager, array $options): Server
{
$session = extract_session_from_options($options);
if ($session instanceof Session && $session->getServer() !== null) {
@@ -430,3 +534,49 @@ function select_server(Manager $manager, array $options)
return $manager->selectServer($readPreference);
}
/**
* Performs server selection for an aggregate operation with a write stage. The
* $options parameter may be modified by reference if a primary read preference
* must be forced due to the existence of pre-5.0 servers in the topology.
*
* @internal
* @see https://github.com/mongodb/specifications/blob/master/source/crud/crud.rst#aggregation-pipelines-with-write-stages
*/
function select_server_for_aggregate_write_stage(Manager $manager, array &$options): Server
{
$readPreference = extract_read_preference_from_options($options);
/* If there is either no read preference or a primary read preference, there
* is no special server selection logic to apply. */
if ($readPreference === null || $readPreference->getMode() === ReadPreference::RP_PRIMARY) {
return select_server($manager, $options);
}
$server = null;
$serverSelectionError = null;
try {
$server = select_server($manager, $options);
} catch (DriverRuntimeException $serverSelectionError) {
}
/* If any pre-5.0 servers exist in the topology, force a primary read
* preference and repeat server selection if it previously failed or
* selected a secondary. */
if (! all_servers_support_write_stage_on_secondary($manager->getServers())) {
$options['readPreference'] = new ReadPreference(ReadPreference::RP_PRIMARY);
if ($server === null || $server->isSecondary()) {
return select_server($manager, $options);
}
}
/* If the topology only contains 5.0+ servers, we should either return the
* previously selected server or propagate the server selection error. */
if ($serverSelectionError !== null) {
throw $serverSelectionError;
}
return $server;
}