From 6f2085c87e1123b39494da67f9fedba042685946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Thu, 26 Sep 2024 14:49:12 +0200 Subject: [PATCH] PHPLIB-1227 Use void return types for operations without meaningful result document --- psalm-baseline.xml | 18 ------ src/Client.php | 9 +-- src/Collection.php | 24 +++----- src/Database.php | 56 +++++-------------- src/Operation/CreateCollection.php | 16 +----- src/Operation/CreateEncryptedCollection.php | 8 +-- src/Operation/DropCollection.php | 15 +---- src/Operation/DropDatabase.php | 13 +---- src/Operation/DropEncryptedCollection.php | 10 +--- src/Operation/DropIndexes.php | 13 +---- src/Operation/DropSearchIndex.php | 1 - src/Operation/ModifyCollection.php | 22 +------- src/Operation/RenameCollection.php | 21 +------ src/Operation/UpdateSearchIndex.php | 1 - tests/ClientFunctionalTest.php | 2 +- tests/Collection/CollectionFunctionalTest.php | 6 +- .../CollectionManagementFunctionalTest.php | 14 ++--- tests/Database/DatabaseFunctionalTest.php | 16 +++--- tests/FunctionalTestCase.php | 48 +++++++++++++++- .../DropCollectionFunctionalTest.php | 2 +- tests/Operation/DropIndexesFunctionalTest.php | 6 +- .../RenameCollectionFunctionalTest.php | 2 +- ...rose21_AutomaticDataEncryptionKeysTest.php | 32 ++++++----- 23 files changed, 132 insertions(+), 223 deletions(-) diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 5ea414eb3..6846ed2ea 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -579,9 +579,6 @@ - - options['typeMap']]]> - @@ -653,9 +650,6 @@ - - options['typeMap']]]> - @@ -666,9 +660,6 @@ - - options['typeMap']]]> - @@ -681,9 +672,6 @@ - - options['typeMap']]]> - @@ -862,9 +850,6 @@ - - options['typeMap']]]> - @@ -872,9 +857,6 @@ - - options['typeMap']]]> - diff --git a/src/Client.php b/src/Client.php index 00a1a6ed3..c700f9058 100644 --- a/src/Client.php +++ b/src/Client.php @@ -214,17 +214,12 @@ public function createClientEncryption(array $options): ClientEncryption * @see DropDatabase::__construct() for supported options * @param string $databaseName Database name * @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 dropDatabase(string $databaseName, array $options = []): array|object + public function dropDatabase(string $databaseName, array $options = []): void { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - $server = select_server_for_write($this->manager, $options); if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { @@ -233,7 +228,7 @@ public function dropDatabase(string $databaseName, array $options = []): array|o $operation = new DropDatabase($databaseName, $options); - return $operation->execute($server); + $operation->execute($server); } /** diff --git a/src/Collection.php b/src/Collection.php index ec87cb928..92eaffe64 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -508,15 +508,13 @@ public function distinct(string $fieldName, array|object $filter = [], array $op * * @see DropCollection::__construct() for supported options * @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 drop(array $options = []): array|object + public function drop(array $options = []): void { $options = $this->inheritWriteOptions($options); - $options = $this->inheritTypeMap($options); $server = select_server_for_write($this->manager, $options); @@ -529,7 +527,7 @@ public function drop(array $options = []): array|object ? new DropEncryptedCollection($this->databaseName, $this->collectionName, $options) : new DropCollection($this->databaseName, $this->collectionName, $options); - return $operation->execute($server); + $operation->execute($server); } /** @@ -538,12 +536,11 @@ public function drop(array $options = []): array|object * @see DropIndexes::__construct() for supported options * @param string|IndexInfo $indexName Index name or model object * @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 dropIndex(string|IndexInfo $indexName, array $options = []): array|object + public function dropIndex(string|IndexInfo $indexName, array $options = []): void { $indexName = (string) $indexName; @@ -552,11 +549,10 @@ public function dropIndex(string|IndexInfo $indexName, array $options = []): arr } $options = $this->inheritWriteOptions($options); - $options = $this->inheritTypeMap($options); $operation = new DropIndexes($this->databaseName, $this->collectionName, $indexName, $options); - return $operation->execute(select_server_for_write($this->manager, $options)); + $operation->execute(select_server_for_write($this->manager, $options)); } /** @@ -564,19 +560,17 @@ public function dropIndex(string|IndexInfo $indexName, array $options = []): arr * * @see DropIndexes::__construct() for supported options * @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 dropIndexes(array $options = []): array|object + public function dropIndexes(array $options = []): void { $options = $this->inheritWriteOptions($options); - $options = $this->inheritTypeMap($options); $operation = new DropIndexes($this->databaseName, $this->collectionName, '*', $options); - return $operation->execute(select_server_for_write($this->manager, $options)); + $operation->execute(select_server_for_write($this->manager, $options)); } /** @@ -958,23 +952,21 @@ public function mapReduce(JavascriptInterface $map, JavascriptInterface $reduce, * @param string $toCollectionName New name of the collection * @param string|null $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 = []): array|object + public function rename(string $toCollectionName, ?string $toDatabaseName = null, array $options = []): void { if (! isset($toDatabaseName)) { $toDatabaseName = $this->databaseName; } $options = $this->inheritWriteOptions($options); - $options = $this->inheritTypeMap($options); $operation = new RenameCollection($this->databaseName, $this->collectionName, $toDatabaseName, $toCollectionName, $options); - return $operation->execute(select_server_for_write($this->manager, $options)); + $operation->execute(select_server_for_write($this->manager, $options)); } /** diff --git a/src/Database.php b/src/Database.php index e8e256c49..cfd9794b8 100644 --- a/src/Database.php +++ b/src/Database.php @@ -271,17 +271,12 @@ public function command(array|object $command, array $options = []): CursorInter * @see CreateCollection::__construct() for supported options * @see https://github.com/mongodb/specifications/blob/master/source/client-side-encryption/client-side-encryption.rst#create-collection-helper * @see https://www.mongodb.com/docs/manual/core/queryable-encryption/fundamentals/manage-collections/ - * @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 createCollection(string $collectionName, array $options = []): array|object + public function createCollection(string $collectionName, array $options = []): void { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { $options['writeConcern'] = $this->writeConcern; } @@ -296,7 +291,7 @@ public function createCollection(string $collectionName, array $options = []): a $server = select_server_for_write($this->manager, $options); - return $operation->execute($server); + $operation->execute($server); } /** @@ -314,17 +309,13 @@ public function createCollection(string $collectionName, array $options = []): a * getPrevious() and getEncryptedFields() methods, respectively. * * @see CreateCollection::__construct() for supported options - * @return array A tuple containing the command result document from creating the collection and the modified "encryptedFields" option + * @return array The modified "encryptedFields" option * @throws InvalidArgumentException for parameter/option parsing errors * @throws CreateEncryptedCollectionException for any errors creating data keys or creating the collection * @throws UnsupportedException if Queryable Encryption is not supported by the selected server */ public function createEncryptedCollection(string $collectionName, ClientEncryption $clientEncryption, string $kmsProvider, ?array $masterKey, array $options): array { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { $options['writeConcern'] = $this->writeConcern; } @@ -334,9 +325,11 @@ public function createEncryptedCollection(string $collectionName, ClientEncrypti try { $operation->createDataKeys($clientEncryption, $kmsProvider, $masterKey, $encryptedFields); - $result = $operation->execute($server); + $operation->execute($server); + + assert(is_array($encryptedFields), '$encryptedFields is set'); - return [$result, $encryptedFields]; + return $encryptedFields; } catch (Throwable $e) { throw new CreateEncryptedCollectionException($e, $encryptedFields ?? []); } @@ -347,17 +340,12 @@ public function createEncryptedCollection(string $collectionName, ClientEncrypti * * @see DropDatabase::__construct() for supported options * @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 drop(array $options = []): array|object + public function drop(array $options = []): void { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - $server = select_server_for_write($this->manager, $options); if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { @@ -366,7 +354,7 @@ public function drop(array $options = []): array|object $operation = new DropDatabase($this->databaseName, $options); - return $operation->execute($server); + $operation->execute($server); } /** @@ -375,17 +363,12 @@ public function drop(array $options = []): array|object * @see DropCollection::__construct() for supported options * @param string $collectionName Collection name * @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 dropCollection(string $collectionName, array $options = []): array|object + public function dropCollection(string $collectionName, array $options = []): void { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - $server = select_server_for_write($this->manager, $options); if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { @@ -401,7 +384,7 @@ public function dropCollection(string $collectionName, array $options = []): arr ? new DropEncryptedCollection($this->databaseName, $collectionName, $options) : new DropCollection($this->databaseName, $collectionName, $options); - return $operation->execute($server); + $operation->execute($server); } /** @@ -497,12 +480,8 @@ public function listCollections(array $options = []): CollectionInfoIterator * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function modifyCollection(string $collectionName, array $collectionOptions, array $options = []): array|object + public function modifyCollection(string $collectionName, array $collectionOptions, array $options = []): void { - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - $server = select_server_for_write($this->manager, $options); if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { @@ -511,7 +490,7 @@ public function modifyCollection(string $collectionName, array $collectionOption $operation = new ModifyCollection($this->databaseName, $collectionName, $collectionOptions, $options); - return $operation->execute($server); + $operation->execute($server); } /** @@ -522,21 +501,16 @@ public function modifyCollection(string $collectionName, array $collectionOption * @param string $toCollectionName New name of the collection * @param string|null $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 = []): array|object + public function renameCollection(string $fromCollectionName, string $toCollectionName, ?string $toDatabaseName = null, array $options = []): void { if (! isset($toDatabaseName)) { $toDatabaseName = $this->databaseName; } - if (! isset($options['typeMap'])) { - $options['typeMap'] = $this->typeMap; - } - $server = select_server_for_write($this->manager, $options); if (! isset($options['writeConcern']) && ! is_in_transaction($options)) { @@ -545,7 +519,7 @@ public function renameCollection(string $fromCollectionName, string $toCollectio $operation = new RenameCollection($this->databaseName, $fromCollectionName, $toDatabaseName, $toCollectionName, $options); - return $operation->execute($server); + $operation->execute($server); } /** diff --git a/src/Operation/CreateCollection.php b/src/Operation/CreateCollection.php index 6411d1d2e..abd4cb310 100644 --- a/src/Operation/CreateCollection.php +++ b/src/Operation/CreateCollection.php @@ -24,7 +24,6 @@ use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; -use function current; use function is_array; use function is_bool; use function is_integer; @@ -112,9 +111,6 @@ final class CreateCollection implements Executable * * 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. - * * * validationAction (string): Validation action. * * * validationLevel (string): Validation level. @@ -239,19 +235,11 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() - * @return array|object Command result document * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function execute(Server $server): array|object + public function execute(Server $server): void { - $cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); - - if (isset($this->options['typeMap'])) { - $cursor->setTypeMap($this->options['typeMap']); - } - - return current($cursor->toArray()); + $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); } /** diff --git a/src/Operation/CreateEncryptedCollection.php b/src/Operation/CreateEncryptedCollection.php index fec5f2d18..4a5fe9dc4 100644 --- a/src/Operation/CreateEncryptedCollection.php +++ b/src/Operation/CreateEncryptedCollection.php @@ -155,12 +155,10 @@ public function createDataKeys(ClientEncryption $clientEncryption, string $kmsPr } /** - * @see Executable::execute() - * @return array|object Command result document from creating the encrypted collection * @throws DriverRuntimeException for other driver errors (e.g. connection errors) * @throws UnsupportedException if the server does not support Queryable Encryption */ - public function execute(Server $server): array|object + public function execute(Server $server): void { if (! server_supports_feature($server, self::WIRE_VERSION_FOR_QUERYABLE_ENCRYPTION_V2)) { throw new UnsupportedException('Driver support of Queryable Encryption is incompatible with server. Upgrade server to use Queryable Encryption.'); @@ -170,10 +168,8 @@ public function execute(Server $server): array|object $createMetadataCollection->execute($server); } - $result = $this->createCollection->execute($server); + $this->createCollection->execute($server); $this->createSafeContentIndex->execute($server); - - return $result; } } diff --git a/src/Operation/DropCollection.php b/src/Operation/DropCollection.php index d1a0b65a8..1cd81d23f 100644 --- a/src/Operation/DropCollection.php +++ b/src/Operation/DropCollection.php @@ -26,7 +26,6 @@ use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedException; -use function current; use function is_array; /** @@ -83,12 +82,10 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() - * @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): array|object + public function execute(Server $server): void { $inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction(); if ($inTransaction && isset($this->options['writeConcern'])) { @@ -96,23 +93,17 @@ public function execute(Server $server): array|object } try { - $cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); + $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 and return the command reply instead of * throwing. */ if ($e->getCode() === self::ERROR_CODE_NAMESPACE_NOT_FOUND) { - return $e->getResultDocument(); + return; } throw $e; } - - if (isset($this->options['typeMap'])) { - $cursor->setTypeMap($this->options['typeMap']); - } - - return current($cursor->toArray()); } /** diff --git a/src/Operation/DropDatabase.php b/src/Operation/DropDatabase.php index c60015e5c..6ec11da89 100644 --- a/src/Operation/DropDatabase.php +++ b/src/Operation/DropDatabase.php @@ -24,7 +24,6 @@ use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; -use function current; use function is_array; /** @@ -78,19 +77,11 @@ public function __construct(private string $databaseName, private array $options /** * Execute the operation. * - * @see Executable::execute() - * @return array|object Command result document * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function execute(Server $server): array|object + public function execute(Server $server): void { - $cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); - - if (isset($this->options['typeMap'])) { - $cursor->setTypeMap($this->options['typeMap']); - } - - return current($cursor->toArray()); + $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); } /** diff --git a/src/Operation/DropEncryptedCollection.php b/src/Operation/DropEncryptedCollection.php index 32f143ee5..835b2ac6b 100644 --- a/src/Operation/DropEncryptedCollection.php +++ b/src/Operation/DropEncryptedCollection.php @@ -84,17 +84,13 @@ public function __construct(string $databaseName, string $collectionName, array $this->dropCollection = new DropCollection($databaseName, $collectionName, $options); } - /** - * @see Executable::execute() - * @return array|object Command result document from dropping the encrypted collection - * @throws DriverRuntimeException for other driver errors (e.g. connection errors) - */ - public function execute(Server $server): array|object + /** @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ + public function execute(Server $server): void { foreach ($this->dropMetadataCollections as $dropMetadataCollection) { $dropMetadataCollection->execute($server); } - return $this->dropCollection->execute($server); + $this->dropCollection->execute($server); } } diff --git a/src/Operation/DropIndexes.php b/src/Operation/DropIndexes.php index d6b1beb59..e78a8af10 100644 --- a/src/Operation/DropIndexes.php +++ b/src/Operation/DropIndexes.php @@ -25,7 +25,6 @@ use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedException; -use function current; use function is_array; use function is_integer; @@ -92,25 +91,17 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() - * @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): array|object + public function execute(Server $server): void { $inTransaction = isset($this->options['session']) && $this->options['session']->isInTransaction(); if ($inTransaction && isset($this->options['writeConcern'])) { throw UnsupportedException::writeConcernNotSupportedInTransaction(); } - $cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); - - if (isset($this->options['typeMap'])) { - $cursor->setTypeMap($this->options['typeMap']); - } - - return current($cursor->toArray()); + $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); } /** diff --git a/src/Operation/DropSearchIndex.php b/src/Operation/DropSearchIndex.php index 73b9c6e17..4dc49de68 100644 --- a/src/Operation/DropSearchIndex.php +++ b/src/Operation/DropSearchIndex.php @@ -53,7 +53,6 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() * @throws UnsupportedException if write concern is used and unsupported * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ diff --git a/src/Operation/ModifyCollection.php b/src/Operation/ModifyCollection.php index 45a5f1c4b..75d214f69 100644 --- a/src/Operation/ModifyCollection.php +++ b/src/Operation/ModifyCollection.php @@ -24,9 +24,6 @@ use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; -use function current; -use function is_array; - /** * Operation for the collMod command. * @@ -46,9 +43,6 @@ final class ModifyCollection implements Executable * * * 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. * * @param string $databaseName Database name @@ -67,10 +61,6 @@ public function __construct(private string $databaseName, private string $collec throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); - } - if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } @@ -83,19 +73,11 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() - * @return array|object Command result document * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function execute(Server $server): array|object + public function execute(Server $server): void { - $cursor = $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); - - if (isset($this->options['typeMap'])) { - $cursor->setTypeMap($this->options['typeMap']); - } - - return current($cursor->toArray()); + $server->executeWriteCommand($this->databaseName, $this->createCommand(), $this->createOptions()); } private function createCommand(): Command diff --git a/src/Operation/RenameCollection.php b/src/Operation/RenameCollection.php index 078bf487f..88562b2c0 100644 --- a/src/Operation/RenameCollection.php +++ b/src/Operation/RenameCollection.php @@ -25,8 +25,6 @@ use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedException; -use function current; -use function is_array; use function is_bool; /** @@ -53,9 +51,6 @@ final class RenameCollection implements Executable * * * 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 @@ -74,10 +69,6 @@ public function __construct(string $fromDatabaseName, string $fromCollectionName throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); - } - if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } @@ -97,25 +88,17 @@ public function __construct(string $fromDatabaseName, string $fromCollectionName /** * Execute the operation. * - * @see Executable::execute() - * @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): array|object + public function execute(Server $server): void { $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()); + $server->executeWriteCommand('admin', $this->createCommand(), $this->createOptions()); } /** diff --git a/src/Operation/UpdateSearchIndex.php b/src/Operation/UpdateSearchIndex.php index 9aff80662..f46b5ddb5 100644 --- a/src/Operation/UpdateSearchIndex.php +++ b/src/Operation/UpdateSearchIndex.php @@ -61,7 +61,6 @@ public function __construct(private string $databaseName, private string $collec /** * Execute the operation. * - * @see Executable::execute() * @throws UnsupportedException if write concern is used and unsupported * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ diff --git a/tests/ClientFunctionalTest.php b/tests/ClientFunctionalTest.php index ca0ea2722..4210f6f69 100644 --- a/tests/ClientFunctionalTest.php +++ b/tests/ClientFunctionalTest.php @@ -47,7 +47,7 @@ public function testDropDatabase(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->client->dropDatabase($this->getDatabaseName()); + $commandResult = self::commandResult(fn () => $this->client->dropDatabase($this->getDatabaseName())); $this->assertCommandSucceeded($commandResult); $this->assertCollectionCount($this->getNamespace(), 0); } diff --git a/tests/Collection/CollectionFunctionalTest.php b/tests/Collection/CollectionFunctionalTest.php index d63140ca4..b2be516e2 100644 --- a/tests/Collection/CollectionFunctionalTest.php +++ b/tests/Collection/CollectionFunctionalTest.php @@ -253,7 +253,7 @@ public function testDrop(): void $writeResult = $this->collection->insertOne(['x' => 1]); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->collection->drop(); + $commandResult = self::commandResult(fn () => $this->collection->drop()); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); } @@ -330,7 +330,7 @@ public function testRenameToSameDatabase(): void $writeResult = $this->collection->insertOne(['_id' => 1]); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->collection->rename($toCollectionName, null, ['dropTarget' => true]); + $commandResult = self::commandResult(fn () => $this->collection->rename($toCollectionName, null, ['dropTarget' => true])); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); $this->assertCollectionExists($toCollectionName); @@ -359,7 +359,7 @@ public function testRenameToDifferentDatabase(): void $writeResult = $this->collection->insertOne(['_id' => 1]); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->collection->rename($toCollectionName, $toDatabaseName); + $commandResult = self::commandResult(fn () => $this->collection->rename($toCollectionName, $toDatabaseName)); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); $this->assertCollectionExists($toCollectionName, $toDatabaseName); diff --git a/tests/Database/CollectionManagementFunctionalTest.php b/tests/Database/CollectionManagementFunctionalTest.php index 485bcd8e5..808e388f5 100644 --- a/tests/Database/CollectionManagementFunctionalTest.php +++ b/tests/Database/CollectionManagementFunctionalTest.php @@ -16,7 +16,7 @@ public function testCreateCollection(): void $that = $this; $basicCollectionName = $this->getCollectionName() . '.basic'; - $commandResult = $this->database->createCollection($basicCollectionName); + $commandResult = self::commandResult(fn () => $this->database->createCollection($basicCollectionName)); $this->assertCommandSucceeded($commandResult); $this->assertCollectionExists($basicCollectionName, null, function (CollectionInfo $info) use ($that): void { $that->assertFalse($info->isCapped()); @@ -29,7 +29,7 @@ public function testCreateCollection(): void 'size' => 1_048_576, ]; - $commandResult = $this->database->createCollection($cappedCollectionName, $cappedCollectionOptions); + $commandResult = self::commandResult(fn () => $this->database->createCollection($cappedCollectionName, $cappedCollectionOptions)); $this->assertCommandSucceeded($commandResult); $this->assertCollectionExists($cappedCollectionName, null, function (CollectionInfo $info) use ($that): void { $that->assertTrue($info->isCapped()); @@ -46,14 +46,14 @@ public function testDropCollection(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->database->dropCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->dropCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $this->assertCollectionCount($this->getNamespace(), 0); } public function testListCollections(): void { - $commandResult = $this->database->createCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->createCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $collections = $this->database->listCollections(); @@ -66,7 +66,7 @@ public function testListCollections(): void public function testListCollectionsWithFilter(): void { - $commandResult = $this->database->createCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->createCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $collectionName = $this->getCollectionName(); @@ -83,7 +83,7 @@ public function testListCollectionsWithFilter(): void public function testListCollectionNames(): void { - $commandResult = $this->database->createCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->createCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $collections = $this->database->listCollectionNames(); @@ -95,7 +95,7 @@ public function testListCollectionNames(): void public function testListCollectionNamesWithFilter(): void { - $commandResult = $this->database->createCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->createCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $collectionName = $this->getCollectionName(); diff --git a/tests/Database/DatabaseFunctionalTest.php b/tests/Database/DatabaseFunctionalTest.php index 2647f9f8b..24413d9c8 100644 --- a/tests/Database/DatabaseFunctionalTest.php +++ b/tests/Database/DatabaseFunctionalTest.php @@ -137,7 +137,7 @@ public function testDrop(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->database->drop(); + $commandResult = self::commandResult(fn () => $this->database->drop()); $this->assertCommandSucceeded($commandResult); $this->assertCollectionCount($this->getNamespace(), 0); } @@ -150,7 +150,7 @@ public function testDropCollection(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->database->dropCollection($this->getCollectionName()); + $commandResult = self::commandResult(fn () => $this->database->dropCollection($this->getCollectionName())); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); } @@ -183,11 +183,11 @@ public function testModifyCollection(): void $createIndexes = new CreateIndexes($this->getDatabaseName(), $this->getCollectionName(), $indexes); $createIndexes->execute($this->getPrimaryServer()); - $commandResult = $this->database->modifyCollection( + $commandResult = self::commandResult(fn () => $this->database->modifyCollection( $this->getCollectionName(), ['index' => ['keyPattern' => ['lastAccess' => 1], 'expireAfterSeconds' => 1000]], ['typeMap' => ['root' => 'array', 'document' => 'array']], - ); + )); $this->assertCommandSucceeded($commandResult); $commandResult = (array) $commandResult; @@ -219,12 +219,12 @@ public function testRenameCollectionToSameDatabase(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->database->renameCollection( + $commandResult = self::commandResult(fn () => $this->database->renameCollection( $this->getCollectionName(), $toCollectionName, null, ['dropTarget' => true], - ); + )); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); $this->assertCollectionExists($toCollectionName); @@ -256,11 +256,11 @@ public function testRenameCollectionToDifferentDatabase(): void $writeResult = $this->manager->executeBulkWrite($this->getNamespace(), $bulkWrite); $this->assertEquals(1, $writeResult->getInsertedCount()); - $commandResult = $this->database->renameCollection( + $commandResult = self::commandResult(fn () => $this->database->renameCollection( $this->getCollectionName(), $toCollectionName, $toDatabaseName, - ); + )); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); $this->assertCollectionExists($toCollectionName, $toDatabaseName); diff --git a/tests/FunctionalTestCase.php b/tests/FunctionalTestCase.php index cdff7ca48..c1da3ff89 100644 --- a/tests/FunctionalTestCase.php +++ b/tests/FunctionalTestCase.php @@ -9,6 +9,10 @@ use MongoDB\Driver\Command; use MongoDB\Driver\Exception\CommandException; use MongoDB\Driver\Manager; +use MongoDB\Driver\Monitoring\CommandFailedEvent; +use MongoDB\Driver\Monitoring\CommandStartedEvent; +use MongoDB\Driver\Monitoring\CommandSubscriber; +use MongoDB\Driver\Monitoring\CommandSucceededEvent; use MongoDB\Driver\ReadPreference; use MongoDB\Driver\Server; use MongoDB\Driver\ServerApi; @@ -35,10 +39,13 @@ use function is_readable; use function is_string; use function key; +use function MongoDB\Driver\Monitoring\addSubscriber; +use function MongoDB\Driver\Monitoring\removeSubscriber; use function ob_get_clean; use function ob_start; use function parse_url; use function phpinfo; +use function PHPUnit\Framework\assertNull; use function preg_match; use function preg_quote; use function preg_replace; @@ -189,6 +196,45 @@ protected function assertCollectionExists(string $collectionName, ?string $datab } } + /** @param callable():void $closure */ + protected static function commandResult(callable $closure): object + { + $subscriber = new class implements CommandSubscriber { + public ?object $result = null; + + public function commandFailed(CommandFailedEvent $event): void + { + assertNull($this->result, 'Expected only one command result'); + + $this->result = $event->getReply(); + } + + public function commandStarted(CommandStartedEvent $event): void + { + } + + public function commandSucceeded(CommandSucceededEvent $event): void + { + assertNull($this->result, 'Expected only one command result'); + + $this->result = $event->getReply(); + } + }; + + addSubscriber($subscriber); + + try { + $return = $closure(); + + self::assertNull($return, 'Expected void return type'); + self::assertNotNull($subscriber->result, 'Expected a command result'); + + return $subscriber->result; + } finally { + removeSubscriber($subscriber); + } + } + protected function assertCommandSucceeded($document): void { $document = is_object($document) ? (array) $document : $document; @@ -238,7 +284,7 @@ public function configureFailPoint(array|stdClass $command, ?Server $server = nu $failPointServer = $server ?: $this->getPrimaryServer(); $operation = new DatabaseCommand('admin', $command); - $cursor = $operation->execute($failPointServer); + $cursor = self::commandResult(fn () => $operation->execute($failPointServer)); $result = $cursor->toArray()[0]; $this->assertCommandSucceeded($result); diff --git a/tests/Operation/DropCollectionFunctionalTest.php b/tests/Operation/DropCollectionFunctionalTest.php index 602982f5c..32353859f 100644 --- a/tests/Operation/DropCollectionFunctionalTest.php +++ b/tests/Operation/DropCollectionFunctionalTest.php @@ -35,7 +35,7 @@ public function testDropExistingCollection(): void $this->assertEquals(1, $writeResult->getInsertedCount()); $operation = new DropCollection($this->getDatabaseName(), $this->getCollectionName()); - $commandResult = $operation->execute($server); + $commandResult = self::commandResult(fn () => $operation->execute($server)); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); diff --git a/tests/Operation/DropIndexesFunctionalTest.php b/tests/Operation/DropIndexesFunctionalTest.php index d54c8544a..a293a2e63 100644 --- a/tests/Operation/DropIndexesFunctionalTest.php +++ b/tests/Operation/DropIndexesFunctionalTest.php @@ -48,7 +48,7 @@ public function testDropOneIndexByName(): void $this->assertIndexExists('x_1'); $operation = new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), 'x_1'); - $this->assertCommandSucceeded($operation->execute($this->getPrimaryServer())); + $this->assertCommandSucceeded(self::commandResult(fn () => $operation->execute($this->getPrimaryServer()))); $operation = new ListIndexes($this->getDatabaseName(), $this->getCollectionName()); $indexes = $operation->execute($this->getPrimaryServer()); @@ -76,7 +76,7 @@ public function testDropAllIndexesByWildcard(): void $this->assertIndexExists('y_1'); $operation = new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), '*'); - $this->assertCommandSucceeded($operation->execute($this->getPrimaryServer())); + $this->assertCommandSucceeded(self::commandResult(fn () => $operation->execute($this->getPrimaryServer()))); $operation = new ListIndexes($this->getDatabaseName(), $this->getCollectionName()); $indexes = $operation->execute($this->getPrimaryServer()); @@ -108,7 +108,7 @@ public function testDropByIndexInfo(): void $this->assertIndexExists('x_1'); $operation = new DropIndexes($this->getDatabaseName(), $this->getCollectionName(), $info); - $this->assertCommandSucceeded($operation->execute($this->getPrimaryServer())); + $this->assertCommandSucceeded(self::commandResult(fn () => $operation->execute($this->getPrimaryServer()))); $operation = new ListIndexes($this->getDatabaseName(), $this->getCollectionName()); $indexes = $operation->execute($this->getPrimaryServer()); diff --git a/tests/Operation/RenameCollectionFunctionalTest.php b/tests/Operation/RenameCollectionFunctionalTest.php index 9dccae0e3..ca5ad99ee 100644 --- a/tests/Operation/RenameCollectionFunctionalTest.php +++ b/tests/Operation/RenameCollectionFunctionalTest.php @@ -65,7 +65,7 @@ public function testRenameCollectionToNonexistentTarget(): void $this->getDatabaseName(), $this->toCollectionName, ); - $commandResult = $operation->execute($server); + $commandResult = self::commandResult(fn () => $operation->execute($server)); $this->assertCommandSucceeded($commandResult); $this->assertCollectionDoesNotExist($this->getCollectionName()); diff --git a/tests/SpecTests/ClientSideEncryption/Prose21_AutomaticDataEncryptionKeysTest.php b/tests/SpecTests/ClientSideEncryption/Prose21_AutomaticDataEncryptionKeysTest.php index ddea08972..566b32c50 100644 --- a/tests/SpecTests/ClientSideEncryption/Prose21_AutomaticDataEncryptionKeysTest.php +++ b/tests/SpecTests/ClientSideEncryption/Prose21_AutomaticDataEncryptionKeysTest.php @@ -69,13 +69,15 @@ public function tearDown(): void */ public function testCase1_SimpleCreationAndValidation(string $kmsProvider, ?array $masterKey): void { - [$result, $encryptedFields] = $this->database->createEncryptedCollection( - $this->getCollectionName(), - $this->clientEncryption, - $kmsProvider, - $masterKey, - ['encryptedFields' => ['fields' => [['path' => 'ssn', 'bsonType' => 'string', 'keyId' => null]]]], - ); + $result = self::commandResult(function () use ($kmsProvider, $masterKey, &$encryptedFields): void { + $encryptedFields = $this->database->createEncryptedCollection( + $this->getCollectionName(), + $this->clientEncryption, + $kmsProvider, + $masterKey, + ['encryptedFields' => ['fields' => [['path' => 'ssn', 'bsonType' => 'string', 'keyId' => null]]]], + ); + }); $this->assertCommandSucceeded($result); $this->assertInstanceOf(Binary::class, $encryptedFields['fields'][0]['keyId'] ?? null); @@ -146,13 +148,15 @@ public function testCase3_InvalidKeyId(string $kmsProvider, ?array $masterKey): */ public function testCase4_InsertEncryptedValue(string $kmsProvider, ?array $masterKey): void { - [$result, $encryptedFields] = $this->database->createEncryptedCollection( - $this->getCollectionName(), - $this->clientEncryption, - $kmsProvider, - $masterKey, - ['encryptedFields' => ['fields' => [['path' => 'ssn', 'bsonType' => 'string', 'keyId' => null]]]], - ); + $result = self::commandResult(function () use ($kmsProvider, $masterKey, &$encryptedFields): void { + $encryptedFields = $this->database->createEncryptedCollection( + $this->getCollectionName(), + $this->clientEncryption, + $kmsProvider, + $masterKey, + ['encryptedFields' => ['fields' => [['path' => 'ssn', 'bsonType' => 'string', 'keyId' => null]]]], + ); + }); $this->assertCommandSucceeded($result); $this->assertInstanceOf(Binary::class, $encryptedFields['fields'][0]['keyId'] ?? null);