diff --git a/.evergreen/config.yml b/.evergreen/config.yml index 2843ac813..1c4e2a22a 100644 --- a/.evergreen/config.yml +++ b/.evergreen/config.yml @@ -71,4 +71,3 @@ include: - filename: .evergreen/config/generated/test/require-api-version.yml - filename: .evergreen/config/generated/test/csfle.yml - filename: .evergreen/config/generated/test-variant/modern-php-full.yml - - filename: .evergreen/config/generated/test-variant/legacy-php-full.yml diff --git a/.evergreen/config/build-task-groups.yml b/.evergreen/config/build-task-groups.yml index 892548181..f745f78ad 100644 --- a/.evergreen/config/build-task-groups.yml +++ b/.evergreen/config/build-task-groups.yml @@ -11,22 +11,10 @@ task_groups: # Builds all versions of PHP - name: "build-all-php" # Keep this number in sync with the number of PHP versions to allow for parallel builds - max_hosts: 4 + max_hosts: 3 setup_task: *build_setup setup_task_can_fail_task: true setup_task_timeout_secs: 1800 teardown_task: *build_teardown tasks: - ".build" - - # Builds all versions of PHP that support OpenSSL 3 (PHP 8.1+) - - name: "build-php-openssl3" - # Keep this number in sync with the number of PHP versions to allow for parallel builds - # Subtract 2 versions as PHP 7.4 and 8.0 are not built with OpenSSL 3 - max_hosts: 2 - setup_task: *build_setup - setup_task_can_fail_task: true - setup_task_timeout_secs: 1800 - teardown_task: *build_teardown - tasks: - - ".build !.php7.4 !.php8.0" diff --git a/.evergreen/config/build-variants.yml b/.evergreen/config/build-variants.yml index 2635e81a6..562791c38 100644 --- a/.evergreen/config/build-variants.yml +++ b/.evergreen/config/build-variants.yml @@ -8,7 +8,7 @@ buildvariants: tags: ["build", "debian", "x64"] run_on: debian12-small tasks: - - name: "build-php-openssl3" + - name: "build-all-php" - name: build-debian11 display_name: "Build: Debian 11" tags: ["build", "debian", "x64", "pr", "tag"] @@ -34,7 +34,7 @@ buildvariants: tags: ["build", "rhel", "x64", "pr", "tag"] run_on: rhel90-small tasks: - - name: "build-php-openssl3" + - name: "build-all-php" - name: build-rhel83-zseries display_name: "Build: RHEL 8.3 Zseries" tags: ["build", "rhel", "zseries", "tag"] @@ -66,13 +66,13 @@ buildvariants: tags: ["build", "ubuntu", "x64", "pr", "tag"] run_on: ubuntu2204-small tasks: - - name: "build-php-openssl3" + - name: "build-all-php" - name: build-ubuntu2204-arm64 display_name: "Build: Ubuntu 22.04 ARM64" tags: ["build", "ubuntu", "arm64", "tag"] run_on: ubuntu2204-arm64-small tasks: - - name: "build-php-openssl3" + - name: "build-all-php" - name: build-ubuntu2004 display_name: "Build: Ubuntu 20.04 x64" tags: ["build", "ubuntu", "x64", "pr", "tag"] diff --git a/.evergreen/config/generate-config.php b/.evergreen/config/generate-config.php index a87d262f7..ed2c6a28e 100644 --- a/.evergreen/config/generate-config.php +++ b/.evergreen/config/generate-config.php @@ -2,16 +2,11 @@ = 5.0, < 8.0 - - name: test-debian11-php-8.0-local - tags: ["test", "debian", "x64", "php8.0", "pr", "tag"] - display_name: "Test: Debian 11, PHP 8.0" - run_on: debian11-small - expansions: - FETCH_BUILD_VARIANT: "build-debian11" - FETCH_BUILD_TASK: "build-php-8.0" - PHP_VERSION: "8.0" - VARIANT: debian11 # Referenced by ADL build script for downloading MQLRun - depends_on: - - variant: "build-debian11" - name: "build-php-8.0" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - "test-atlas-data-lake" - - # Test versions < 5.0 - - name: test-debian92-php-8.0-local - tags: ["test", "debian", "x64", "php8.0", "pr", "tag"] - display_name: "Test: Debian 9.2, PHP 8.0" - run_on: debian92-small - expansions: - FETCH_BUILD_VARIANT: "build-debian92" - FETCH_BUILD_TASK: "build-php-8.0" - PHP_VERSION: "8.0" - depends_on: - - variant: "build-debian92" - name: "build-php-8.0" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - # Test Atlas and CSFLE on RHEL 8 - - name: test-rhel80-php-8.0-atlas - tags: ["test", "debian", "x64", "php8.0", "pr", "tag"] - display_name: "Test: RHEL 8.0, PHP 8.0" - run_on: rhel80-small - expansions: - FETCH_BUILD_VARIANT: "build-rhel80" - FETCH_BUILD_TASK: "build-php-8.0" - PHP_VERSION: "8.0" - depends_on: - - variant: "build-rhel80" - name: "build-php-8.0" - tasks: - - "test_atlas_task_group" - - ".csfle" -# TODO PHPLIB-955: This file can be removed when requiring PHP 8.1+ - # Test MongoDB >= 5.0, < 8.0 - - name: test-debian11-php-7.4-local - tags: ["test", "debian", "x64", "php7.4", "pr", "tag"] - display_name: "Test: Debian 11, PHP 7.4" - run_on: debian11-small - expansions: - FETCH_BUILD_VARIANT: "build-debian11" - FETCH_BUILD_TASK: "build-php-7.4" - PHP_VERSION: "7.4" - VARIANT: debian11 # Referenced by ADL build script for downloading MQLRun - depends_on: - - variant: "build-debian11" - name: "build-php-7.4" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - "test-atlas-data-lake" - - # Test versions < 5.0 - - name: test-debian92-php-7.4-local - tags: ["test", "debian", "x64", "php7.4", "pr", "tag"] - display_name: "Test: Debian 9.2, PHP 7.4" - run_on: debian92-small - expansions: - FETCH_BUILD_VARIANT: "build-debian92" - FETCH_BUILD_TASK: "build-php-7.4" - PHP_VERSION: "7.4" - depends_on: - - variant: "build-debian92" - name: "build-php-7.4" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - # Test Atlas and CSFLE on RHEL 8 - - name: test-rhel80-php-7.4-atlas - tags: ["test", "debian", "x64", "php7.4", "pr", "tag"] - display_name: "Test: RHEL 8.0, PHP 7.4" - run_on: rhel80-small - expansions: - FETCH_BUILD_VARIANT: "build-rhel80" - FETCH_BUILD_TASK: "build-php-7.4" - PHP_VERSION: "7.4" - depends_on: - - variant: "build-rhel80" - name: "build-php-7.4" - tasks: - - "test_atlas_task_group" - - ".csfle" diff --git a/.evergreen/config/templates/test-variant/legacy-php-full.yml b/.evergreen/config/templates/test-variant/legacy-php-full.yml deleted file mode 100644 index 82bef9b4b..000000000 --- a/.evergreen/config/templates/test-variant/legacy-php-full.yml +++ /dev/null @@ -1,56 +0,0 @@ -# TODO PHPLIB-955: This file can be removed when requiring PHP 8.1+ - # Test MongoDB >= 5.0, < 8.0 - - name: test-debian11-php-%phpVersion%-local - tags: ["test", "debian", "x64", "php%phpVersion%", "pr", "tag"] - display_name: "Test: Debian 11, PHP %phpVersion%" - run_on: debian11-small - expansions: - FETCH_BUILD_VARIANT: "build-debian11" - FETCH_BUILD_TASK: "build-php-%phpVersion%" - PHP_VERSION: "%phpVersion%" - VARIANT: debian11 # Referenced by ADL build script for downloading MQLRun - depends_on: - - variant: "build-debian11" - name: "build-php-%phpVersion%" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.4.0 !.4.2 !.4.4 !.8.0 !.rapid !.latest" - - "test-atlas-data-lake" - - # Test versions < 5.0 - - name: test-debian92-php-%phpVersion%-local - tags: ["test", "debian", "x64", "php%phpVersion%", "pr", "tag"] - display_name: "Test: Debian 9.2, PHP %phpVersion%" - run_on: debian92-small - expansions: - FETCH_BUILD_VARIANT: "build-debian92" - FETCH_BUILD_TASK: "build-php-%phpVersion%" - PHP_VERSION: "%phpVersion%" - depends_on: - - variant: "build-debian92" - name: "build-php-%phpVersion%" - tasks: - # Remember to add new major versions here as they are released - - ".standalone .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".replicaset .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".sharded .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - ".loadbalanced .local !.csfle !.6.0 !.7.0 !.8.0 !.rapid !.latest" - - # Test Atlas and CSFLE on RHEL 8 - - name: test-rhel80-php-%phpVersion%-atlas - tags: ["test", "debian", "x64", "php%phpVersion%", "pr", "tag"] - display_name: "Test: RHEL 8.0, PHP %phpVersion%" - run_on: rhel80-small - expansions: - FETCH_BUILD_VARIANT: "build-rhel80" - FETCH_BUILD_TASK: "build-php-%phpVersion%" - PHP_VERSION: "%phpVersion%" - depends_on: - - variant: "build-rhel80" - name: "build-php-%phpVersion%" - tasks: - - "test_atlas_task_group" - - ".csfle" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index e5ae92cdc..68ae09af4 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,8 +29,6 @@ jobs: os: - "ubuntu-20.04" php-version: - - "7.4" - - "8.0" - "8.1" - "8.2" - "8.3" @@ -41,23 +39,23 @@ jobs: - "server" include: - os: "ubuntu-20.04" - php-version: "8.0" + php-version: "8.1" mongodb-version: "6.0" topology: "replica_set" - os: "ubuntu-20.04" - php-version: "8.0" + php-version: "8.1" mongodb-version: "6.0" topology: "sharded_cluster" - os: "ubuntu-20.04" - php-version: "8.0" + php-version: "8.1" mongodb-version: "5.0" topology: "server" - os: "ubuntu-20.04" - php-version: "8.0" + php-version: "8.1" mongodb-version: "4.4" topology: "replica_set" - os: "ubuntu-20.04" - php-version: "8.0" + php-version: "8.1" mongodb-version: "4.4" topology: "sharded_cluster" diff --git a/benchmark/src/Fixtures/PassThruCodec.php b/benchmark/src/Fixtures/PassThruCodec.php index 7a8846cc6..fe4c725b0 100644 --- a/benchmark/src/Fixtures/PassThruCodec.php +++ b/benchmark/src/Fixtures/PassThruCodec.php @@ -13,20 +13,17 @@ final class PassThruCodec implements DocumentCodec use DecodeIfSupported; use EncodeIfSupported; - /** @param mixed $value */ - public function canDecode($value): bool + public function canDecode(mixed $value): bool { return $value instanceof Document; } - /** @param mixed $value */ - public function canEncode($value): bool + public function canEncode(mixed $value): bool { return $value instanceof Document; } - /** @param mixed $value */ - public function decode($value): Document + public function decode(mixed $value): Document { if (! $value instanceof Document) { throw UnsupportedValueException::invalidDecodableValue($value); @@ -35,8 +32,7 @@ public function decode($value): Document return $value; } - /** @param mixed $value */ - public function encode($value): Document + public function encode(mixed $value): Document { if (! $value instanceof Document) { throw UnsupportedValueException::invalidEncodableValue($value); diff --git a/benchmark/src/Fixtures/ToObjectCodec.php b/benchmark/src/Fixtures/ToObjectCodec.php index c212302ab..a193d58a4 100644 --- a/benchmark/src/Fixtures/ToObjectCodec.php +++ b/benchmark/src/Fixtures/ToObjectCodec.php @@ -15,20 +15,17 @@ final class ToObjectCodec implements DocumentCodec use DecodeIfSupported; use EncodeIfSupported; - /** @param mixed $value */ - public function canDecode($value): bool + public function canDecode(mixed $value): bool { return $value instanceof Document; } - /** @param mixed $value */ - public function canEncode($value): bool + public function canEncode(mixed $value): bool { return is_object($value); } - /** @param mixed $value */ - public function decode($value): object + public function decode(mixed $value): object { if (! $value instanceof Document) { throw UnsupportedValueException::invalidDecodableValue($value); @@ -37,8 +34,7 @@ public function decode($value): object return $value->toPHP(['root' => 'stdClass', 'array' => 'array', 'document' => 'stdClass']); } - /** @param mixed $value */ - public function encode($value): Document + public function encode(mixed $value): Document { if (! is_object($value)) { throw UnsupportedValueException::invalidEncodableValue($value); diff --git a/benchmark/src/ReadLargeDocumentBench.php b/benchmark/src/ReadLargeDocumentBench.php index de7d3ad02..bdf5b021d 100644 --- a/benchmark/src/ReadLargeDocumentBench.php +++ b/benchmark/src/ReadLargeDocumentBench.php @@ -129,8 +129,7 @@ public function benchAccessLastField(array $params): void } } - /** @param array|object $document */ - private function accessId($document, string $accessor): void + private function accessId(array|object $document, string $accessor): void { switch ($accessor) { case 'array': @@ -153,8 +152,7 @@ private function accessId($document, string $accessor): void } } - /** @param array|object $document */ - private function accessLastField($document, string $accessor): void + private function accessLastField(array|object $document, string $accessor): void { switch ($accessor) { case 'array': @@ -178,8 +176,7 @@ private function accessLastField($document, string $accessor): void } } - /** @param array|object $document */ - private function accessFirstField($document, string $accessor): void + private function accessFirstField(array|object $document, string $accessor): void { switch ($accessor) { case 'array': diff --git a/benchmark/src/ReadMultipleDocumentsBench.php b/benchmark/src/ReadMultipleDocumentsBench.php index 64c6ef7e3..74dbafe13 100644 --- a/benchmark/src/ReadMultipleDocumentsBench.php +++ b/benchmark/src/ReadMultipleDocumentsBench.php @@ -116,8 +116,7 @@ public function benchAccessNestedItem(array $params): void } } - /** @param array|object $document */ - private function accessId($document, string $accessor): void + private function accessId(array|object $document, string $accessor): void { switch ($accessor) { case 'array': @@ -140,8 +139,7 @@ private function accessId($document, string $accessor): void } } - /** @param array|object $document */ - private function accessNestedItem($document, string $accessor): void + private function accessNestedItem(array|object $document, string $accessor): void { switch ($accessor) { case 'array': diff --git a/composer.json b/composer.json index fceee1108..a6dd35b5a 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ { "name": "Jérôme Tamarelle", "email": "jerome.tamarelle@mongodb.com" } ], "require": { - "php": "^7.4 || ^8.0", + "php": "^8.1", "ext-hash": "*", "ext-json": "*", "ext-mongodb": "^1.20.0", diff --git a/examples/command_logger.php b/examples/command_logger.php index 7fd932dac..eab47882a 100644 --- a/examples/command_logger.php +++ b/examples/command_logger.php @@ -11,7 +11,6 @@ use MongoDB\Driver\Monitoring\CommandSucceededEvent; use function assert; -use function get_class; use function getenv; use function is_object; use function printf; @@ -46,7 +45,7 @@ public function commandFailed(CommandFailedEvent $event): void printf("reply: %s\n", toJson($event->getReply())); $exception = $event->getError(); - printf("exception: %s\n", get_class($exception)); + printf("exception: %s\n", $exception::class); printf("exception.code: %d\n", $exception->getCode()); printf("exception.message: %s\n", $exception->getMessage()); echo "\n"; diff --git a/examples/persistable.php b/examples/persistable.php index c7aa5617d..2a4c3614e 100644 --- a/examples/persistable.php +++ b/examples/persistable.php @@ -19,15 +19,12 @@ class PersistableEntry implements Persistable { private ObjectId $id; - public string $name; - /** @var array */ public array $emails = []; - public function __construct(string $name) + public function __construct(public string $name) { $this->id = new ObjectId(); - $this->name = $name; } public function getId(): ObjectId @@ -64,14 +61,8 @@ public function bsonUnserialize(array $data): void class PersistableEmail implements Persistable { - public string $type; - - public string $address; - - public function __construct(string $type, string $address) + public function __construct(public string $type, public string $address) { - $this->type = $type; - $this->address = $address; } public function bsonSerialize(): stdClass diff --git a/examples/sdam_logger.php b/examples/sdam_logger.php index 974e11dfb..2edf82302 100644 --- a/examples/sdam_logger.php +++ b/examples/sdam_logger.php @@ -16,14 +16,12 @@ use MongoDB\Driver\Monitoring\TopologyClosedEvent; use MongoDB\Driver\Monitoring\TopologyOpeningEvent; -use function get_class; use function getenv; use function printf; require __DIR__ . '/../vendor/autoload.php'; -/** @param array|object $document */ -function toJSON($document): string +function toJSON(array|object $document): string { return Document::fromPHP($document)->toRelaxedExtendedJSON(); } @@ -67,7 +65,7 @@ public function serverHeartbeatFailed(ServerHeartbeatFailedEvent $event): void $error = $event->getError(); - printf("error: %s(%d): %s\n", get_class($error), $error->getCode(), $error->getMessage()); + printf("error: %s(%d): %s\n", $error::class, $error->getCode(), $error->getMessage()); echo "\n"; } diff --git a/phpcs.xml.dist b/phpcs.xml.dist index c01b7025d..ace2991ac 100644 --- a/phpcs.xml.dist +++ b/phpcs.xml.dist @@ -17,7 +17,7 @@ rector.php - + @@ -40,6 +40,7 @@ + diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 8ba6e2760..8589b8024 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -133,6 +133,11 @@ + + + options['typeMap']]]> + + cursor->nextBatch]]> @@ -337,7 +342,7 @@ - + options['encryptedFields']]]> options['encryptedFields']]]> diff --git a/src/BulkWriteResult.php b/src/BulkWriteResult.php index 9f86c3a81..4fb556e0b 100644 --- a/src/BulkWriteResult.php +++ b/src/BulkWriteResult.php @@ -25,16 +25,10 @@ */ class BulkWriteResult { - private WriteResult $writeResult; - - private array $insertedIds; - private bool $isAcknowledged; - public function __construct(WriteResult $writeResult, array $insertedIds) + public function __construct(private WriteResult $writeResult, private array $insertedIds) { - $this->writeResult = $writeResult; - $this->insertedIds = $insertedIds; $this->isAcknowledged = $writeResult->isAcknowledged(); } diff --git a/src/ChangeStream.php b/src/ChangeStream.php index 9565adfb0..506300d80 100644 --- a/src/ChangeStream.php +++ b/src/ChangeStream.php @@ -80,8 +80,6 @@ class ChangeStream implements Iterator /** @var ResumeCallable|null */ private $resumeCallable; - private ChangeStreamIterator $iterator; - private int $key = 0; /** @@ -90,8 +88,6 @@ class ChangeStream implements Iterator */ private bool $hasAdvanced = false; - private ?DocumentCodec $codec; - /** * @see https://php.net/iterator.current * @return array|object|null @@ -207,11 +203,9 @@ public function valid() * * @param ResumeCallable $resumeCallable */ - public function __construct(ChangeStreamIterator $iterator, callable $resumeCallable, ?DocumentCodec $codec = null) + public function __construct(private ChangeStreamIterator $iterator, callable $resumeCallable, private ?DocumentCodec $codec = null) { - $this->iterator = $iterator; $this->resumeCallable = $resumeCallable; - $this->codec = $codec; if ($codec) { $this->iterator->getInnerIterator()->setTypeMap(['root' => 'bson']); diff --git a/src/Client.php b/src/Client.php index b5fc18246..0b9282cf0 100644 --- a/src/Client.php +++ b/src/Client.php @@ -397,7 +397,7 @@ private static function getVersion(): string if (self::$version === null) { try { self::$version = InstalledVersions::getPrettyVersion('mongodb/mongodb') ?? 'unknown'; - } catch (Throwable $t) { + } catch (Throwable) { self::$version = 'error'; } } diff --git a/src/Codec/DecodeIfSupported.php b/src/Codec/DecodeIfSupported.php index 56dcfb9ec..7fd768011 100644 --- a/src/Codec/DecodeIfSupported.php +++ b/src/Codec/DecodeIfSupported.php @@ -25,27 +25,22 @@ */ trait DecodeIfSupported { - /** - * @param mixed $value - * @psalm-assert-if-true BSONType $value - */ - abstract public function canDecode($value): bool; + /** @psalm-assert-if-true BSONType $value */ + abstract public function canDecode(mixed $value): bool; /** - * @param mixed $value * @psalm-param BSONType $value * @return mixed * @psalm-return NativeType * @throws UnsupportedValueException if the decoder does not support the value */ - abstract public function decode($value); + abstract public function decode(mixed $value); /** - * @param mixed $value * @return mixed * @psalm-return ($value is BSONType ? NativeType : $value) */ - public function decodeIfSupported($value) + public function decodeIfSupported(mixed $value) { return $this->canDecode($value) ? $this->decode($value) : $value; } diff --git a/src/Codec/Decoder.php b/src/Codec/Decoder.php index 904e097fe..432fb2dd7 100644 --- a/src/Codec/Decoder.php +++ b/src/Codec/Decoder.php @@ -28,22 +28,20 @@ interface Decoder /** * Checks if the decoder supports a given value. * - * @param mixed $value * @psalm-assert-if-true BSONType $value */ - public function canDecode($value): bool; + public function canDecode(mixed $value): bool; /** * Decodes a given value. If the decoder does not support the value, it * should throw an exception. * - * @param mixed $value * @psalm-param BSONType $value * @return mixed * @psalm-return NativeType * @throws UnsupportedValueException if the decoder does not support the value */ - public function decode($value); + public function decode(mixed $value); /** * Decodes a given value if supported, otherwise returns the value as-is. @@ -51,9 +49,8 @@ public function decode($value); * The DecodeIfSupported trait provides a default implementation of this * method. * - * @param mixed $value * @return mixed * @psalm-return ($value is BSONType ? NativeType : $value) */ - public function decodeIfSupported($value); + public function decodeIfSupported(mixed $value); } diff --git a/src/Codec/DocumentCodec.php b/src/Codec/DocumentCodec.php index ba4488b08..6fabdb936 100644 --- a/src/Codec/DocumentCodec.php +++ b/src/Codec/DocumentCodec.php @@ -30,17 +30,15 @@ interface DocumentCodec extends Codec { /** - * @param mixed $value * @psalm-param Document $value * @psalm-return ObjectType * @throws UnsupportedValueException if the decoder does not support the value */ - public function decode($value): object; + public function decode(mixed $value): object; /** - * @param mixed $value * @psalm-param ObjectType $value * @throws UnsupportedValueException if the encoder does not support the value */ - public function encode($value): Document; + public function encode(mixed $value): Document; } diff --git a/src/Codec/EncodeIfSupported.php b/src/Codec/EncodeIfSupported.php index c4aebac6b..33823cfd6 100644 --- a/src/Codec/EncodeIfSupported.php +++ b/src/Codec/EncodeIfSupported.php @@ -25,27 +25,22 @@ */ trait EncodeIfSupported { - /** - * @param mixed $value - * @psalm-assert-if-true NativeType $value - */ - abstract public function canEncode($value): bool; + /** @psalm-assert-if-true NativeType $value */ + abstract public function canEncode(mixed $value): bool; /** - * @param mixed $value * @psalm-param NativeType $value * @return mixed * @psalm-return BSONType * @throws UnsupportedValueException if the encoder does not support the value */ - abstract public function encode($value); + abstract public function encode(mixed $value); /** - * @param mixed $value * @return mixed * @psalm-return ($value is NativeType ? BSONType : $value) */ - public function encodeIfSupported($value) + public function encodeIfSupported(mixed $value) { return $this->canEncode($value) ? $this->encode($value) : $value; } diff --git a/src/Codec/Encoder.php b/src/Codec/Encoder.php index dba58d9d5..0cd0d58cb 100644 --- a/src/Codec/Encoder.php +++ b/src/Codec/Encoder.php @@ -28,22 +28,20 @@ interface Encoder /** * Checks if the encoder supports a given value. * - * @param mixed $value * @psalm-assert-if-true NativeType $value */ - public function canEncode($value): bool; + public function canEncode(mixed $value): bool; /** * Encodes a given value. If the encoder does not support the value, it * should throw an exception. * - * @param mixed $value * @psalm-param NativeType $value * @return mixed * @psalm-return BSONType * @throws UnsupportedValueException if the encoder does not support the value */ - public function encode($value); + public function encode(mixed $value); /** * Encodes a given value if supported, otherwise returns the value as-is. @@ -51,9 +49,8 @@ public function encode($value); * The EncodeIfSupported trait provides a default implementation of this * method. * - * @param mixed $value * @return mixed * @psalm-return ($value is NativeType ? BSONType : $value) */ - public function encodeIfSupported($value); + public function encodeIfSupported(mixed $value); } diff --git a/src/Collection.php b/src/Collection.php index 708d43d68..5399892bf 100644 --- a/src/Collection.php +++ b/src/Collection.php @@ -86,12 +86,6 @@ class Collection private ?DocumentCodec $codec = null; - private string $collectionName; - - private string $databaseName; - - private Manager $manager; - private ReadConcern $readConcern; private ReadPreference $readPreference; @@ -130,7 +124,7 @@ class Collection * @param array $options Collection options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(Manager $manager, string $databaseName, string $collectionName, array $options = []) + public function __construct(private Manager $manager, private string $databaseName, private string $collectionName, array $options = []) { if (strlen($databaseName) < 1) { throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName); @@ -160,10 +154,6 @@ public function __construct(Manager $manager, string $databaseName, string $coll throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); } - $this->manager = $manager; - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->codec = $options['codec'] ?? null; $this->readConcern = $options['readConcern'] ?? $this->manager->getReadConcern(); $this->readPreference = $options['readPreference'] ?? $this->manager->getReadPreference(); @@ -277,7 +267,7 @@ public function bulkWrite(array $operations, array $options = []) * * @deprecated 1.4 */ - public function count($filter = [], array $options = []) + public function count(array|object $filter = [], array $options = []) { $options = $this->inheritReadOptions($options); @@ -298,7 +288,7 @@ public function count($filter = [], array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function countDocuments($filter = [], array $options = []) + public function countDocuments(array|object $filter = [], array $options = []) { $options = $this->inheritReadOptions($options); @@ -320,7 +310,7 @@ public function countDocuments($filter = [], array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function createIndex($key, array $options = []) + public function createIndex(array|object $key, array $options = []) { $operationOptionKeys = ['comment' => 1, 'commitQuorum' => 1, 'maxTimeMS' => 1, 'session' => 1, 'writeConcern' => 1]; $indexOptions = array_diff_key($options, $operationOptionKeys); @@ -378,7 +368,7 @@ public function createIndexes(array $indexes, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function createSearchIndex($definition, array $options = []): string + public function createSearchIndex(array|object $definition, array $options = []): string { $index = ['definition' => $definition]; if (isset($options['name'])) { @@ -435,7 +425,7 @@ public function createSearchIndexes(array $indexes, array $options = []): array * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function deleteMany($filter, array $options = []) + public function deleteMany(array|object $filter, array $options = []) { $options = $this->inheritWriteOptions($options); @@ -456,7 +446,7 @@ public function deleteMany($filter, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function deleteOne($filter, array $options = []) + public function deleteOne(array|object $filter, array $options = []) { $options = $this->inheritWriteOptions($options); @@ -478,7 +468,7 @@ public function deleteOne($filter, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function distinct(string $fieldName, $filter = [], array $options = []) + public function distinct(string $fieldName, array|object $filter = [], array $options = []) { $options = $this->inheritReadOptions($options); $options = $this->inheritTypeMap($options); @@ -528,7 +518,7 @@ public function drop(array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function dropIndex($indexName, array $options = []) + public function dropIndex(string|IndexInfo $indexName, array $options = []) { $indexName = (string) $indexName; @@ -636,7 +626,7 @@ public function explain(Explainable $explainable, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function find($filter = [], array $options = []) + public function find(array|object $filter = [], array $options = []) { $options = $this->inheritReadOptions($options); $options = $this->inheritCodecOrTypeMap($options); @@ -658,7 +648,7 @@ public function find($filter = [], array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function findOne($filter = [], array $options = []) + public function findOne(array|object $filter = [], array $options = []) { $options = $this->inheritReadOptions($options); $options = $this->inheritCodecOrTypeMap($options); @@ -683,7 +673,7 @@ public function findOne($filter = [], array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function findOneAndDelete($filter, array $options = []) + public function findOneAndDelete(array|object $filter, array $options = []) { $options = $this->inheritWriteOptions($options); $options = $this->inheritCodecOrTypeMap($options); @@ -713,7 +703,7 @@ public function findOneAndDelete($filter, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function findOneAndReplace($filter, $replacement, array $options = []) + public function findOneAndReplace(array|object $filter, array|object $replacement, array $options = []) { $options = $this->inheritWriteOptions($options); $options = $this->inheritCodecOrTypeMap($options); @@ -743,7 +733,7 @@ public function findOneAndReplace($filter, $replacement, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function findOneAndUpdate($filter, $update, array $options = []) + public function findOneAndUpdate(array|object $filter, array|object $update, array $options = []) { $options = $this->inheritWriteOptions($options); $options = $this->inheritCodecOrTypeMap($options); @@ -868,7 +858,7 @@ public function insertMany(array $documents, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function insertOne($document, array $options = []) + public function insertOne(array|object $document, array $options = []) { $options = $this->inheritWriteOptions($options); $options = $this->inheritCodec($options); @@ -926,7 +916,7 @@ public function listSearchIndexes(array $options = []): Iterator * @throws DriverRuntimeException for other driver errors (e.g. connection errors) * @throws UnexpectedValueException if the command response was malformed */ - public function mapReduce(JavascriptInterface $map, JavascriptInterface $reduce, $out, array $options = []) + public function mapReduce(JavascriptInterface $map, JavascriptInterface $reduce, string|array|object $out, array $options = []) { $hasOutputCollection = ! is_mapreduce_output_inline($out); @@ -991,7 +981,7 @@ public function rename(string $toCollectionName, ?string $toDatabaseName = null, * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function replaceOne($filter, $replacement, array $options = []) + public function replaceOne(array|object $filter, array|object $replacement, array $options = []) { $options = $this->inheritWriteOptions($options); $options = $this->inheritCodec($options); @@ -1014,7 +1004,7 @@ public function replaceOne($filter, $replacement, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function updateMany($filter, $update, array $options = []) + public function updateMany(array|object $filter, array|object $update, array $options = []) { $options = $this->inheritWriteOptions($options); @@ -1036,7 +1026,7 @@ public function updateMany($filter, $update, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function updateOne($filter, $update, array $options = []) + public function updateOne(array|object $filter, array|object $update, array $options = []) { $options = $this->inheritWriteOptions($options); @@ -1056,7 +1046,7 @@ public function updateOne($filter, $update, array $options = []) * @throws InvalidArgumentException for parameter parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function updateSearchIndex(string $name, $definition, array $options = []): void + public function updateSearchIndex(string $name, array|object $definition, array $options = []): void { $operation = new UpdateSearchIndex($this->databaseName, $this->collectionName, $name, $definition, $options); $server = select_server_for_write($this->manager, $options); diff --git a/src/Command/ListCollections.php b/src/Command/ListCollections.php index 857b35254..454e145f3 100644 --- a/src/Command/ListCollections.php +++ b/src/Command/ListCollections.php @@ -38,10 +38,6 @@ */ class ListCollections implements Executable { - private string $databaseName; - - private array $options; - /** * Constructs a listCollections command. * @@ -71,7 +67,7 @@ class ListCollections implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, array $options = []) + public function __construct(private string $databaseName, private array $options = []) { if (isset($options['authorizedCollections']) && ! is_bool($options['authorizedCollections'])) { throw InvalidArgumentException::invalidType('"authorizedCollections" option', $options['authorizedCollections'], 'boolean'); @@ -92,9 +88,6 @@ public function __construct(string $databaseName, array $options = []) if (isset($options['session']) && ! $options['session'] instanceof Session) { throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); } - - $this->databaseName = $databaseName; - $this->options = $options; } /** diff --git a/src/Command/ListDatabases.php b/src/Command/ListDatabases.php index 3aba5f835..5386559db 100644 --- a/src/Command/ListDatabases.php +++ b/src/Command/ListDatabases.php @@ -39,8 +39,6 @@ */ class ListDatabases implements Executable { - private array $options; - /** * Constructs a listDatabases command. * @@ -69,7 +67,7 @@ class ListDatabases implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(array $options = []) + public function __construct(private array $options = []) { if (isset($options['authorizedDatabases']) && ! is_bool($options['authorizedDatabases'])) { throw InvalidArgumentException::invalidType('"authorizedDatabases" option', $options['authorizedDatabases'], 'boolean'); @@ -90,8 +88,6 @@ public function __construct(array $options = []) if (isset($options['session']) && ! $options['session'] instanceof Session) { throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); } - - $this->options = $options; } /** diff --git a/src/Database.php b/src/Database.php index 95933df8a..d466dcb6a 100644 --- a/src/Database.php +++ b/src/Database.php @@ -61,10 +61,6 @@ class Database private const WIRE_VERSION_FOR_READ_CONCERN_WITH_WRITE_STAGE = 8; - private string $databaseName; - - private Manager $manager; - private ReadConcern $readConcern; private ReadPreference $readPreference; @@ -100,7 +96,7 @@ class Database * @param array $options Database options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(Manager $manager, string $databaseName, array $options = []) + public function __construct(private Manager $manager, private string $databaseName, array $options = []) { if (strlen($databaseName) < 1) { throw new InvalidArgumentException('$databaseName is invalid: ' . $databaseName); @@ -122,8 +118,6 @@ public function __construct(Manager $manager, string $databaseName, array $optio throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); } - $this->manager = $manager; - $this->databaseName = $databaseName; $this->readConcern = $options['readConcern'] ?? $this->manager->getReadConcern(); $this->readPreference = $options['readPreference'] ?? $this->manager->getReadPreference(); $this->typeMap = $options['typeMap'] ?? self::DEFAULT_TYPE_MAP; @@ -237,7 +231,7 @@ public function aggregate(array $pipeline, array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function command($command, array $options = []) + public function command(array|object $command, array $options = []) { if (! isset($options['typeMap'])) { $options['typeMap'] = $this->typeMap; diff --git a/src/DeleteResult.php b/src/DeleteResult.php index 7d2744ccc..56f3f072d 100644 --- a/src/DeleteResult.php +++ b/src/DeleteResult.php @@ -25,13 +25,10 @@ */ class DeleteResult { - private WriteResult $writeResult; - private bool $isAcknowledged; - public function __construct(WriteResult $writeResult) + public function __construct(private WriteResult $writeResult) { - $this->writeResult = $writeResult; $this->isAcknowledged = $writeResult->isAcknowledged(); } diff --git a/src/Exception/CreateEncryptedCollectionException.php b/src/Exception/CreateEncryptedCollectionException.php index 3aca268fe..5f348edd7 100644 --- a/src/Exception/CreateEncryptedCollectionException.php +++ b/src/Exception/CreateEncryptedCollectionException.php @@ -19,7 +19,6 @@ use Throwable; -use function get_class; use function sprintf; /** @@ -28,13 +27,9 @@ */ final class CreateEncryptedCollectionException extends RuntimeException { - private array $encryptedFields; - - public function __construct(Throwable $previous, array $encryptedFields) + public function __construct(Throwable $previous, private array $encryptedFields) { - parent::__construct(sprintf('Creating encrypted collection failed due to previous %s: %s', get_class($previous), $previous->getMessage()), 0, $previous); - - $this->encryptedFields = $encryptedFields; + parent::__construct(sprintf('Creating encrypted collection failed due to previous %s: %s', $previous::class, $previous->getMessage()), 0, $previous); } /** diff --git a/src/Exception/InvalidArgumentException.php b/src/Exception/InvalidArgumentException.php index 7091e82af..115f6a5c7 100644 --- a/src/Exception/InvalidArgumentException.php +++ b/src/Exception/InvalidArgumentException.php @@ -40,7 +40,7 @@ public static function cannotCombineCodecAndTypeMap(): self * @param string $name Name of the argument or option * @param mixed $value Actual value (used to derive the type) */ - public static function expectedDocumentType(string $name, $value): self + public static function expectedDocumentType(string $name, mixed $value): self { return new self(sprintf('Expected %s to have type "document" (array or object) but found "%s"', $name, get_debug_type($value))); } @@ -53,7 +53,7 @@ public static function expectedDocumentType(string $name, $value): self * @param string|list $expectedType Expected type as a string or an array containing one or more strings * @return self */ - public static function invalidType(string $name, $value, $expectedType) + public static function invalidType(string $name, mixed $value, string|array $expectedType) { if (is_array($expectedType)) { $expectedType = self::expectedTypesToString($expectedType); diff --git a/src/Exception/ResumeTokenException.php b/src/Exception/ResumeTokenException.php index ce7a35c71..fc8808271 100644 --- a/src/Exception/ResumeTokenException.php +++ b/src/Exception/ResumeTokenException.php @@ -28,7 +28,7 @@ class ResumeTokenException extends RuntimeException * @param mixed $value Actual value (used to derive the type) * @return self */ - public static function invalidType($value) + public static function invalidType(mixed $value) { return new self(sprintf('Expected resume token to have type "array or object" but found "%s"', get_debug_type($value))); } diff --git a/src/Exception/UnsupportedValueException.php b/src/Exception/UnsupportedValueException.php index 33635d8a0..d744baa13 100644 --- a/src/Exception/UnsupportedValueException.php +++ b/src/Exception/UnsupportedValueException.php @@ -24,32 +24,24 @@ class UnsupportedValueException extends InvalidArgumentException implements Exception { - /** @var mixed */ - private $value; - /** @return mixed */ public function getValue() { return $this->value; } - /** @param mixed $value */ - public static function invalidDecodableValue($value): self + public static function invalidDecodableValue(mixed $value): self { return new self(sprintf('Could not decode value of type "%s".', get_debug_type($value)), $value); } - /** @param mixed $value */ - public static function invalidEncodableValue($value): self + public static function invalidEncodableValue(mixed $value): self { return new self(sprintf('Could not encode value of type "%s".', get_debug_type($value)), $value); } - /** @param mixed $value */ - private function __construct(string $message, $value) + private function __construct(string $message, private mixed $value) { parent::__construct($message); - - $this->value = $value; } } diff --git a/src/GridFS/Bucket.php b/src/GridFS/Bucket.php index 8a7ef25b5..56a4e26e2 100644 --- a/src/GridFS/Bucket.php +++ b/src/GridFS/Bucket.php @@ -86,10 +86,6 @@ class Bucket private CollectionWrapper $collectionWrapper; - private string $databaseName; - - private Manager $manager; - private string $bucketName; private bool $disableMD5; @@ -131,7 +127,7 @@ class Bucket * @param array $options Bucket options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(Manager $manager, string $databaseName, array $options = []) + public function __construct(private Manager $manager, private string $databaseName, array $options = []) { if (isset($options['disableMD5']) && $options['disableMD5'] === false) { @trigger_error('Setting GridFS "disableMD5" option to "false" is deprecated since mongodb/mongodb 1.18 and will not be supported in version 2.0.', E_USER_DEPRECATED); @@ -183,8 +179,6 @@ public function __construct(Manager $manager, string $databaseName, array $optio throw InvalidArgumentException::cannotCombineCodecAndTypeMap(); } - $this->manager = $manager; - $this->databaseName = $databaseName; $this->bucketName = $options['bucketName']; $this->chunkSizeBytes = $options['chunkSizeBytes']; $this->codec = $options['codec'] ?? null; @@ -238,7 +232,7 @@ public function __debugInfo() * @throws FileNotFoundException if no file could be selected * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function delete($id) + public function delete(mixed $id) { $file = $this->collectionWrapper->findFileById($id); $this->collectionWrapper->deleteFileAndChunksById($id); @@ -259,7 +253,7 @@ public function delete($id) * @throws StreamException if the file could not be uploaded * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function downloadToStream($id, $destination) + public function downloadToStream(mixed $id, $destination) { if (! is_resource($destination) || get_resource_type($destination) != 'stream') { throw InvalidArgumentException::invalidType('$destination', $destination, 'resource'); @@ -335,7 +329,7 @@ public function drop() * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function find($filter = [], array $options = []) + public function find(array|object $filter = [], array $options = []) { if ($this->codec && ! array_key_exists('codec', $options)) { $options['codec'] = $this->codec; @@ -356,7 +350,7 @@ public function find($filter = [], array $options = []) * @throws InvalidArgumentException for parameter/option parsing errors * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function findOne($filter = [], array $options = []) + public function findOne(array|object $filter = [], array $options = []) { if ($this->codec && ! array_key_exists('codec', $options)) { $options['codec'] = $this->codec; @@ -512,7 +506,7 @@ public function getWriteConcern() * @throws FileNotFoundException if no file could be selected * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function openDownloadStream($id) + public function openDownloadStream(mixed $id) { $file = $this->collectionWrapper->findFileById($id); @@ -632,7 +626,7 @@ public function registerGlobalStreamWrapperAlias(string $alias): void * @throws FileNotFoundException if no file could be selected * @throws DriverRuntimeException for other driver errors (e.g. connection errors) */ - public function rename($id, string $newFilename) + public function rename(mixed $id, string $newFilename) { $updateResult = $this->collectionWrapper->updateFilenameForId($id, $newFilename); diff --git a/src/GridFS/CollectionWrapper.php b/src/GridFS/CollectionWrapper.php index 25e8b32a7..0c6b9b96c 100644 --- a/src/GridFS/CollectionWrapper.php +++ b/src/GridFS/CollectionWrapper.php @@ -41,12 +41,8 @@ */ class CollectionWrapper { - private string $bucketName; - private Collection $chunksCollection; - private string $databaseName; - private bool $checkedIndexes = false; private Collection $filesCollection; @@ -61,21 +57,16 @@ class CollectionWrapper * @param array $collectionOptions Collection options * @throws InvalidArgumentException */ - public function __construct(Manager $manager, string $databaseName, string $bucketName, array $collectionOptions = []) + public function __construct(Manager $manager, private string $databaseName, private string $bucketName, array $collectionOptions = []) { - $this->databaseName = $databaseName; - $this->bucketName = $bucketName; - $this->filesCollection = new Collection($manager, $databaseName, sprintf('%s.files', $bucketName), $collectionOptions); $this->chunksCollection = new Collection($manager, $databaseName, sprintf('%s.chunks', $bucketName), $collectionOptions); } /** * Deletes all GridFS chunks for a given file ID. - * - * @param mixed $id */ - public function deleteChunksByFilesId($id): void + public function deleteChunksByFilesId(mixed $id): void { $this->chunksCollection->deleteMany(['files_id' => $id]); } @@ -105,10 +96,8 @@ public function deleteFileAndChunksByFilename(string $filename): ?int /** * Deletes a GridFS file and related chunks by ID. - * - * @param mixed $id */ - public function deleteFileAndChunksById($id): void + public function deleteFileAndChunksById(mixed $id): void { $this->filesCollection->deleteOne(['_id' => $id]); $this->chunksCollection->deleteMany(['files_id' => $id]); @@ -130,7 +119,7 @@ public function dropCollections(): void * @param integer $fromChunk Starting chunk (inclusive) * @return CursorInterface&Iterator */ - public function findChunksByFileId($id, int $fromChunk = 0) + public function findChunksByFileId(mixed $id, int $fromChunk = 0) { return $this->chunksCollection->find( [ @@ -187,10 +176,8 @@ public function findFileByFilenameAndRevision(string $filename, int $revision): /** * Finds a GridFS file document for a given ID. - * - * @param mixed $id */ - public function findFileById($id): ?object + public function findFileById(mixed $id): ?object { $file = $this->filesCollection->findOne( ['_id' => $id], @@ -209,7 +196,7 @@ public function findFileById($id): ?object * @param array $options Additional options * @return CursorInterface&Iterator */ - public function findFiles($filter, array $options = []) + public function findFiles(array|object $filter, array $options = []) { return $this->filesCollection->find($filter, $options); } @@ -221,7 +208,7 @@ public function findFiles($filter, array $options = []) * @param array $options Additional options * @return array|object|null */ - public function findOneFile($filter, array $options = []) + public function findOneFile(array|object $filter, array $options = []) { return $this->filesCollection->findOne($filter, $options); } @@ -251,7 +238,7 @@ public function getFilesCollection(): Collection * * @param array|object $chunk Chunk document */ - public function insertChunk($chunk): void + public function insertChunk(array|object $chunk): void { if (! $this->checkedIndexes) { $this->ensureIndexes(); @@ -267,7 +254,7 @@ public function insertChunk($chunk): void * * @param array|object $file File document */ - public function insertFile($file): void + public function insertFile(array|object $file): void { if (! $this->checkedIndexes) { $this->ensureIndexes(); @@ -289,10 +276,8 @@ public function updateFilenameForFilename(string $filename, string $newFilename) /** * Updates the filename field in the file document for a given ID. - * - * @param mixed $id */ - public function updateFilenameForId($id, string $filename): UpdateResult + public function updateFilenameForId(mixed $id, string $filename): UpdateResult { return $this->filesCollection->updateOne( ['_id' => $id], diff --git a/src/GridFS/Exception/FileNotFoundException.php b/src/GridFS/Exception/FileNotFoundException.php index 9243db6f4..99c6d854a 100644 --- a/src/GridFS/Exception/FileNotFoundException.php +++ b/src/GridFS/Exception/FileNotFoundException.php @@ -55,7 +55,7 @@ public static function byFilenameAndRevision(string $filename, int $revision, st * @param string $namespace Namespace for the files collection * @return self */ - public static function byId($id, string $namespace) + public static function byId(mixed $id, string $namespace) { $json = Document::fromPHP(['_id' => $id])->toRelaxedExtendedJSON(); diff --git a/src/GridFS/Exception/LogicException.php b/src/GridFS/Exception/LogicException.php index a2b6378c7..a6835423c 100644 --- a/src/GridFS/Exception/LogicException.php +++ b/src/GridFS/Exception/LogicException.php @@ -39,10 +39,9 @@ public static function bucketAliasNotRegistered(string $alias): self /** * Throw when an invalid "gridfs" context option is provided. * - * @param mixed $context * @internal */ - public static function invalidContext($context): self + public static function invalidContext(mixed $context): self { return new self(sprintf('Expected "gridfs" stream context to have type "array" but found "%s"', get_debug_type($context))); } @@ -50,10 +49,9 @@ public static function invalidContext($context): self /** * Thrown when a context is provided with an incorrect collection wrapper. * - * @param mixed $object * @internal */ - public static function invalidContextCollectionWrapper($object): self + public static function invalidContextCollectionWrapper(mixed $object): self { return new self(sprintf('Expected "collectionWrapper" in "gridfs" stream context to have type "%s" but found "%s"', CollectionWrapper::class, get_debug_type($object))); } diff --git a/src/GridFS/Exception/StreamException.php b/src/GridFS/Exception/StreamException.php index 8dab6d668..880182588 100644 --- a/src/GridFS/Exception/StreamException.php +++ b/src/GridFS/Exception/StreamException.php @@ -23,11 +23,10 @@ public static function downloadFromFilenameFailed(string $filename, $source, $de } /** - * @param mixed $id * @param resource $source * @param resource $destination */ - public static function downloadFromIdFailed($id, $source, $destination): self + public static function downloadFromIdFailed(mixed $id, $source, $destination): self { $idString = Document::fromPHP(['_id' => $id])->toRelaxedExtendedJSON(); $sourceMetadata = stream_get_meta_data($source); diff --git a/src/GridFS/ReadableStream.php b/src/GridFS/ReadableStream.php index f0e433140..980e3e19f 100644 --- a/src/GridFS/ReadableStream.php +++ b/src/GridFS/ReadableStream.php @@ -51,12 +51,8 @@ class ReadableStream /** @var (CursorInterface&Iterator)|null */ private ?Iterator $chunksIterator = null; - private CollectionWrapper $collectionWrapper; - private int $expectedLastChunkSize = 0; - private object $file; - private int $length; private int $numChunks = 0; @@ -68,7 +64,7 @@ class ReadableStream * @param object $file GridFS file document * @throws CorruptFileException */ - public function __construct(CollectionWrapper $collectionWrapper, object $file) + public function __construct(private CollectionWrapper $collectionWrapper, private object $file) { if (! isset($file->chunkSize) || ! is_integer($file->chunkSize) || $file->chunkSize < 1) { throw new CorruptFileException('file.chunkSize is not an integer >= 1'); @@ -82,12 +78,9 @@ public function __construct(CollectionWrapper $collectionWrapper, object $file) throw new CorruptFileException('file._id does not exist'); } - $this->file = $file; $this->chunkSize = $file->chunkSize; $this->length = $file->length; - $this->collectionWrapper = $collectionWrapper; - if ($this->length > 0) { $this->numChunks = (integer) ceil($this->length / $this->chunkSize); $this->expectedLastChunkSize = $this->length - (($this->numChunks - 1) * $this->chunkSize); diff --git a/src/GridFS/StreamWrapper.php b/src/GridFS/StreamWrapper.php index b433c8dd6..cc1d89fc9 100644 --- a/src/GridFS/StreamWrapper.php +++ b/src/GridFS/StreamWrapper.php @@ -54,8 +54,7 @@ class StreamWrapper /** @var resource|null Stream context (set by PHP) */ public $context; - /** @var ReadableStream|WritableStream|null */ - private $stream; + private ReadableStream|WritableStream|null $stream = null; /** @var array */ private static array $contextResolvers = []; @@ -323,7 +322,7 @@ public function url_stat(string $path, int $flags) try { $this->stream_open($path, 'r', 0, $openedPath); - } catch (FileNotFoundException $e) { + } catch (FileNotFoundException) { return false; } diff --git a/src/GridFS/WritableStream.php b/src/GridFS/WritableStream.php index 096968bb6..65b35de90 100644 --- a/src/GridFS/WritableStream.php +++ b/src/GridFS/WritableStream.php @@ -54,8 +54,6 @@ class WritableStream private bool $disableMD5; - private CollectionWrapper $collectionWrapper; - private array $file; private ?HashContext $hashCtx = null; @@ -92,7 +90,7 @@ class WritableStream * @param array $options Upload options * @throws InvalidArgumentException */ - public function __construct(CollectionWrapper $collectionWrapper, string $filename, array $options = []) + public function __construct(private CollectionWrapper $collectionWrapper, string $filename, array $options = []) { $options += [ '_id' => new ObjectId(), @@ -125,7 +123,6 @@ public function __construct(CollectionWrapper $collectionWrapper, string $filena } $this->chunkSize = $options['chunkSizeBytes']; - $this->collectionWrapper = $collectionWrapper; $this->disableMD5 = $options['disableMD5']; if (! $this->disableMD5) { @@ -239,7 +236,7 @@ private function abort(): void { try { $this->collectionWrapper->deleteChunksByFilesId($this->file['_id']); - } catch (DriverRuntimeException $e) { + } catch (DriverRuntimeException) { // We are already handling an error if abort() is called, so suppress this } diff --git a/src/InsertManyResult.php b/src/InsertManyResult.php index f8c33ad0b..6ad2a9595 100644 --- a/src/InsertManyResult.php +++ b/src/InsertManyResult.php @@ -25,16 +25,10 @@ */ class InsertManyResult { - private WriteResult $writeResult; - - private array $insertedIds; - private bool $isAcknowledged; - public function __construct(WriteResult $writeResult, array $insertedIds) + public function __construct(private WriteResult $writeResult, private array $insertedIds) { - $this->writeResult = $writeResult; - $this->insertedIds = $insertedIds; $this->isAcknowledged = $writeResult->isAcknowledged(); } diff --git a/src/InsertOneResult.php b/src/InsertOneResult.php index da851d204..9c72775c8 100644 --- a/src/InsertOneResult.php +++ b/src/InsertOneResult.php @@ -25,18 +25,10 @@ */ class InsertOneResult { - private WriteResult $writeResult; - - /** @var mixed */ - private $insertedId; - private bool $isAcknowledged; - /** @param mixed $insertedId */ - public function __construct(WriteResult $writeResult, $insertedId) + public function __construct(private WriteResult $writeResult, private mixed $insertedId) { - $this->writeResult = $writeResult; - $this->insertedId = $insertedId; $this->isAcknowledged = $writeResult->isAcknowledged(); } diff --git a/src/Model/BSONIterator.php b/src/Model/BSONIterator.php index 43dae2ed2..2ca257c7f 100644 --- a/src/Model/BSONIterator.php +++ b/src/Model/BSONIterator.php @@ -44,16 +44,12 @@ class BSONIterator implements Iterator private int $bufferLength; - /** @var array|object|null */ - private $current = null; + private array|object|null $current = null; private int $key = 0; private int $position = 0; - /** @var array{typeMap: array, ...} */ - private array $options; - /** * @see https://php.net/iterator.current * @return mixed @@ -119,19 +115,18 @@ public function valid(): bool * @param array $options Iterator options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $data, array $options = []) + public function __construct(string $data, private array $options = []) { if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); } if (! isset($options['typeMap'])) { - $options['typeMap'] = []; + $this->options['typeMap'] = []; } $this->buffer = $data; $this->bufferLength = strlen($data); - $this->options = $options; } private function advance(): void diff --git a/src/Model/ChangeStreamIterator.php b/src/Model/ChangeStreamIterator.php index d2a9b6ac8..aa635dda9 100644 --- a/src/Model/ChangeStreamIterator.php +++ b/src/Model/ChangeStreamIterator.php @@ -61,10 +61,7 @@ class ChangeStreamIterator extends IteratorIterator implements CommandSubscriber private bool $isValid = false; - private ?object $postBatchResumeToken = null; - - /** @var array|object|null */ - private $resumeToken; + private array|object|null $resumeToken = null; private Server $server; @@ -176,10 +173,9 @@ public function valid(): bool /** * @internal - * @param array|object|null $initialResumeToken * @psalm-param CursorInterface&Iterator $cursor */ - public function __construct(CursorInterface $cursor, int $firstBatchSize, $initialResumeToken, ?object $postBatchResumeToken) + public function __construct(CursorInterface $cursor, int $firstBatchSize, array|object|null $initialResumeToken, private ?object $postBatchResumeToken = null) { if (! $cursor instanceof Iterator) { throw InvalidArgumentException::invalidType( @@ -197,7 +193,6 @@ public function __construct(CursorInterface $cursor, int $firstBatchSize, $initi $this->batchSize = $firstBatchSize; $this->isRewindNop = ($firstBatchSize === 0); - $this->postBatchResumeToken = $postBatchResumeToken; $this->resumeToken = $initialResumeToken; $this->server = $cursor->getServer(); } @@ -247,7 +242,7 @@ final public function commandSucceeded(CommandSucceededEvent $event): void * @throws InvalidArgumentException * @throws ResumeTokenException if the resume token is not found or invalid */ - private function extractResumeToken($document) + private function extractResumeToken(array|object $document) { if (! is_document($document)) { throw InvalidArgumentException::expectedDocumentType('$document', $document); diff --git a/src/Model/CodecCursor.php b/src/Model/CodecCursor.php index 556f76c0f..e6d1c4db3 100644 --- a/src/Model/CodecCursor.php +++ b/src/Model/CodecCursor.php @@ -44,11 +44,6 @@ class CodecCursor implements CursorInterface, Iterator { private const TYPEMAP = ['root' => 'bson']; - private Cursor $cursor; - - /** @var DocumentCodec */ - private DocumentCodec $codec; - /** @var TValue|null */ private ?object $current = null; @@ -140,9 +135,7 @@ public function valid(): bool } /** @param DocumentCodec $codec */ - private function __construct(Cursor $cursor, DocumentCodec $codec) + private function __construct(private Cursor $cursor, private DocumentCodec $codec) { - $this->cursor = $cursor; - $this->codec = $codec; } } diff --git a/src/Model/CollectionInfo.php b/src/Model/CollectionInfo.php index 20f72b14e..2850a4be4 100644 --- a/src/Model/CollectionInfo.php +++ b/src/Model/CollectionInfo.php @@ -36,12 +36,9 @@ */ class CollectionInfo implements ArrayAccess { - private array $info; - /** @param array $info Collection info */ - public function __construct(array $info) + public function __construct(private array $info) { - $this->info = $info; } /** @@ -147,12 +144,11 @@ public function isCapped() * Check whether a field exists in the collection information. * * @see https://php.net/arrayaccess.offsetexists - * @param mixed $offset * @return boolean * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetExists($offset) + public function offsetExists(mixed $offset) { return array_key_exists($offset, $this->info); } @@ -161,12 +157,11 @@ public function offsetExists($offset) * Return the field's value from the collection information. * * @see https://php.net/arrayaccess.offsetget - * @param mixed $offset * @return mixed * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet(mixed $offset) { return $this->info[$offset]; } @@ -175,13 +170,11 @@ public function offsetGet($offset) * Not supported. * * @see https://php.net/arrayaccess.offsetset - * @param mixed $offset - * @param mixed $value * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet(mixed $offset, mixed $value) { throw BadMethodCallException::classIsImmutable(self::class); } @@ -190,12 +183,11 @@ public function offsetSet($offset, $value) * Not supported. * * @see https://php.net/arrayaccess.offsetunset - * @param mixed $offset * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset(mixed $offset) { throw BadMethodCallException::classIsImmutable(self::class); } diff --git a/src/Model/CollectionInfoCommandIterator.php b/src/Model/CollectionInfoCommandIterator.php index 9a70b4c1d..14ef39a02 100644 --- a/src/Model/CollectionInfoCommandIterator.php +++ b/src/Model/CollectionInfoCommandIterator.php @@ -34,14 +34,10 @@ */ class CollectionInfoCommandIterator extends IteratorIterator implements CollectionInfoIterator { - private ?string $databaseName = null; - /** @param Traversable $iterator */ - public function __construct(Traversable $iterator, ?string $databaseName = null) + public function __construct(Traversable $iterator, private ?string $databaseName = null) { parent::__construct($iterator); - - $this->databaseName = $databaseName; } /** diff --git a/src/Model/DatabaseInfo.php b/src/Model/DatabaseInfo.php index 05cb312b9..2803532f8 100644 --- a/src/Model/DatabaseInfo.php +++ b/src/Model/DatabaseInfo.php @@ -35,12 +35,9 @@ */ class DatabaseInfo implements ArrayAccess { - private array $info; - /** @param array $info Database info */ - public function __construct(array $info) + public function __construct(private array $info) { - $this->info = $info; } /** @@ -89,12 +86,11 @@ public function isEmpty() * Check whether a field exists in the database information. * * @see https://php.net/arrayaccess.offsetexists - * @param mixed $offset * @return boolean * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetExists($offset) + public function offsetExists(mixed $offset) { return array_key_exists($offset, $this->info); } @@ -103,12 +99,11 @@ public function offsetExists($offset) * Return the field's value from the database information. * * @see https://php.net/arrayaccess.offsetget - * @param mixed $offset * @return mixed * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet(mixed $offset) { return $this->info[$offset]; } @@ -117,13 +112,11 @@ public function offsetGet($offset) * Not supported. * * @see https://php.net/arrayaccess.offsetset - * @param mixed $offset - * @param mixed $value * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet(mixed $offset, mixed $value) { throw BadMethodCallException::classIsImmutable(self::class); } @@ -132,12 +125,11 @@ public function offsetSet($offset, $value) * Not supported. * * @see https://php.net/arrayaccess.offsetunset - * @param mixed $offset * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset(mixed $offset) { throw BadMethodCallException::classIsImmutable(self::class); } diff --git a/src/Model/DatabaseInfoLegacyIterator.php b/src/Model/DatabaseInfoLegacyIterator.php index 4bbf46a42..da657acec 100644 --- a/src/Model/DatabaseInfoLegacyIterator.php +++ b/src/Model/DatabaseInfoLegacyIterator.php @@ -34,11 +34,8 @@ */ class DatabaseInfoLegacyIterator implements DatabaseInfoIterator { - private array $databases; - - public function __construct(array $databases) + public function __construct(private array $databases) { - $this->databases = $databases; } /** diff --git a/src/Model/IndexInfo.php b/src/Model/IndexInfo.php index a5df7111c..45eea5027 100644 --- a/src/Model/IndexInfo.php +++ b/src/Model/IndexInfo.php @@ -44,12 +44,9 @@ */ class IndexInfo implements ArrayAccess { - private array $info; - /** @param array $info Index info */ - public function __construct(array $info) + public function __construct(private array $info) { - $this->info = $info; } /** @@ -183,12 +180,11 @@ public function isUnique() * Check whether a field exists in the index information. * * @see https://php.net/arrayaccess.offsetexists - * @param mixed $offset * @return boolean * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetExists($offset) + public function offsetExists(mixed $offset) { return array_key_exists($offset, $this->info); } @@ -202,12 +198,11 @@ public function offsetExists($offset) * * @see https://php.net/arrayaccess.offsetget * @see https://github.com/mongodb/specifications/blob/master/source/enumerate-indexes.rst#getting-full-index-information - * @param mixed $offset * @return mixed * @psalm-param array-key $offset */ #[ReturnTypeWillChange] - public function offsetGet($offset) + public function offsetGet(mixed $offset) { return $this->info[$offset]; } @@ -216,13 +211,11 @@ public function offsetGet($offset) * Not supported. * * @see https://php.net/arrayaccess.offsetset - * @param mixed $offset - * @param mixed $value * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetSet($offset, $value) + public function offsetSet(mixed $offset, mixed $value) { throw BadMethodCallException::classIsImmutable(self::class); } @@ -231,12 +224,11 @@ public function offsetSet($offset, $value) * Not supported. * * @see https://php.net/arrayaccess.offsetunset - * @param mixed $offset * @throws BadMethodCallException * @return void */ #[ReturnTypeWillChange] - public function offsetUnset($offset) + public function offsetUnset(mixed $offset) { throw BadMethodCallException::classIsImmutable(self::class); } diff --git a/src/Model/IndexInfoIteratorIterator.php b/src/Model/IndexInfoIteratorIterator.php index 3bbbcd53f..a2fa85d6f 100644 --- a/src/Model/IndexInfoIteratorIterator.php +++ b/src/Model/IndexInfoIteratorIterator.php @@ -38,14 +38,10 @@ */ class IndexInfoIteratorIterator extends IteratorIterator implements IndexInfoIterator { - private ?string $ns = null; - /** @param Traversable $iterator */ - public function __construct(Traversable $iterator, ?string $ns = null) + public function __construct(Traversable $iterator, private ?string $ns = null) { parent::__construct($iterator); - - $this->ns = $ns; } /** diff --git a/src/Model/IndexInput.php b/src/Model/IndexInput.php index ae1726550..657c2b6da 100644 --- a/src/Model/IndexInput.php +++ b/src/Model/IndexInput.php @@ -40,13 +40,11 @@ */ class IndexInput implements Serializable { - private array $index; - /** * @param array $index Index specification * @throws InvalidArgumentException */ - public function __construct(array $index) + public function __construct(private array $index) { if (! isset($index['key'])) { throw new InvalidArgumentException('Required "key" document is missing from index specification'); @@ -63,14 +61,12 @@ public function __construct(array $index) } if (! isset($index['name'])) { - $index['name'] = $this->generateIndexName($index['key']); + $this->index['name'] = $this->generateIndexName($index['key']); } - if (! is_string($index['name'])) { - throw InvalidArgumentException::invalidType('"name" option', $index['name'], 'string'); + if (! is_string($this->index['name'])) { + throw InvalidArgumentException::invalidType('"name" option', $this->index['name'], 'string'); } - - $this->index = $index; } /** @@ -99,7 +95,7 @@ public function bsonSerialize(): stdClass * which denote order or an index type * @throws InvalidArgumentException if $document is not an array or object */ - private function generateIndexName($document): string + private function generateIndexName(array|object $document): string { $document = document_to_array($document); diff --git a/src/Model/SearchIndexInput.php b/src/Model/SearchIndexInput.php index e28aea9b0..1b8baf533 100644 --- a/src/Model/SearchIndexInput.php +++ b/src/Model/SearchIndexInput.php @@ -36,13 +36,11 @@ */ class SearchIndexInput implements Serializable { - private array $index; - /** * @param array{name?: string, definition: array|object} $index Search index specification * @throws InvalidArgumentException */ - public function __construct(array $index) + public function __construct(private array $index) { if (! isset($index['definition'])) { throw new InvalidArgumentException('Required "definition" document is missing from search index specification'); @@ -56,8 +54,6 @@ public function __construct(array $index) if (isset($index['name']) && ! is_string($index['name'])) { throw InvalidArgumentException::invalidType('"name" option', $index['name'], 'string'); } - - $this->index = $index; } /** diff --git a/src/Operation/Aggregate.php b/src/Operation/Aggregate.php index 0b49748de..ba6e1ea93 100644 --- a/src/Operation/Aggregate.php +++ b/src/Operation/Aggregate.php @@ -51,14 +51,6 @@ */ class Aggregate implements Executable, Explainable { - private string $databaseName; - - private ?string $collectionName = null; - - private array $pipeline; - - private array $options; - private bool $isWrite; /** @@ -126,102 +118,97 @@ class Aggregate implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, ?string $collectionName, array $pipeline, array $options = []) + public function __construct(private string $databaseName, private ?string $collectionName = null, private array $pipeline, private array $options = []) { if (! is_pipeline($pipeline, true /* allowEmpty */)) { throw new InvalidArgumentException('$pipeline is not a valid aggregation pipeline'); } - if (isset($options['allowDiskUse']) && ! is_bool($options['allowDiskUse'])) { - throw InvalidArgumentException::invalidType('"allowDiskUse" option', $options['allowDiskUse'], 'boolean'); + if (isset($this->options['allowDiskUse']) && ! is_bool($this->options['allowDiskUse'])) { + throw InvalidArgumentException::invalidType('"allowDiskUse" option', $this->options['allowDiskUse'], 'boolean'); } - if (isset($options['batchSize']) && ! is_integer($options['batchSize'])) { - throw InvalidArgumentException::invalidType('"batchSize" option', $options['batchSize'], 'integer'); + if (isset($this->options['batchSize']) && ! is_integer($this->options['batchSize'])) { + throw InvalidArgumentException::invalidType('"batchSize" option', $this->options['batchSize'], 'integer'); } - if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) { - throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); + if (isset($this->options['bypassDocumentValidation']) && ! is_bool($this->options['bypassDocumentValidation'])) { + throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $this->options['bypassDocumentValidation'], 'boolean'); } - if (isset($options['codec']) && ! $options['codec'] instanceof DocumentCodec) { - throw InvalidArgumentException::invalidType('"codec" option', $options['codec'], DocumentCodec::class); + if (isset($this->options['codec']) && ! $this->options['codec'] instanceof DocumentCodec) { + throw InvalidArgumentException::invalidType('"codec" option', $this->options['codec'], DocumentCodec::class); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['explain']) && ! is_bool($options['explain'])) { - throw InvalidArgumentException::invalidType('"explain" option', $options['explain'], 'boolean'); + if (isset($this->options['explain']) && ! is_bool($this->options['explain'])) { + throw InvalidArgumentException::invalidType('"explain" option', $this->options['explain'], 'boolean'); } - if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) { - throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object'); + if (isset($this->options['hint']) && ! is_string($this->options['hint']) && ! is_array($this->options['hint']) && ! is_object($this->options['hint'])) { + throw InvalidArgumentException::invalidType('"hint" option', $this->options['hint'], 'string or array or object'); } - if (isset($options['let']) && ! is_document($options['let'])) { - throw InvalidArgumentException::expectedDocumentType('"let" option', $options['let']); + if (isset($this->options['let']) && ! is_document($this->options['let'])) { + throw InvalidArgumentException::expectedDocumentType('"let" option', $this->options['let']); } - if (isset($options['maxAwaitTimeMS']) && ! is_integer($options['maxAwaitTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxAwaitTimeMS" option', $options['maxAwaitTimeMS'], 'integer'); + if (isset($this->options['maxAwaitTimeMS']) && ! is_integer($this->options['maxAwaitTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxAwaitTimeMS" option', $this->options['maxAwaitTimeMS'], 'integer'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { - throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); + if (isset($this->options['readConcern']) && ! $this->options['readConcern'] instanceof ReadConcern) { + throw InvalidArgumentException::invalidType('"readConcern" option', $this->options['readConcern'], ReadConcern::class); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) { - unset($options['bypassDocumentValidation']); + if (isset($this->options['bypassDocumentValidation']) && ! $this->options['bypassDocumentValidation']) { + unset($this->options['bypassDocumentValidation']); } - if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { - unset($options['readConcern']); + if (isset($this->options['readConcern']) && $this->options['readConcern']->isDefault()) { + unset($this->options['readConcern']); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - if (isset($options['codec']) && isset($options['typeMap'])) { + if (isset($this->options['codec']) && isset($this->options['typeMap'])) { throw InvalidArgumentException::cannotCombineCodecAndTypeMap(); } - $this->isWrite = is_last_pipeline_operator_write($pipeline) && ! ($options['explain'] ?? false); + $this->isWrite = is_last_pipeline_operator_write($pipeline) && ! ($this->options['explain'] ?? false); if ($this->isWrite) { /* Ignore batchSize for writes, since no documents are returned and * a batchSize of zero could prevent the pipeline from executing. */ - unset($options['batchSize']); + unset($this->options['batchSize']); } else { - unset($options['writeConcern']); + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->pipeline = $pipeline; - $this->options = $options; } /** diff --git a/src/Operation/BulkWrite.php b/src/Operation/BulkWrite.php index 4457d9930..700ce3943 100644 --- a/src/Operation/BulkWrite.php +++ b/src/Operation/BulkWrite.php @@ -53,10 +53,6 @@ class BulkWrite implements Executable public const UPDATE_MANY = 'updateMany'; public const UPDATE_ONE = 'updateOne'; - private string $databaseName; - - private string $collectionName; - /** @var array[] */ private array $operations; @@ -129,7 +125,7 @@ class BulkWrite implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $operations, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array $operations, array $options = []) { if (empty($operations)) { throw new InvalidArgumentException('$operations is empty'); @@ -173,8 +169,6 @@ public function __construct(string $databaseName, string $collectionName, array unset($options['writeConcern']); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; $this->operations = $this->validateOperations($operations, $options['codec'] ?? null); $this->options = $options; } diff --git a/src/Operation/Count.php b/src/Operation/Count.php index e8aaf8a21..b29aa826a 100644 --- a/src/Operation/Count.php +++ b/src/Operation/Count.php @@ -43,15 +43,6 @@ */ class Count implements Executable, Explainable { - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $filter; - - private array $options; - /** * Constructs a count command. * @@ -87,52 +78,47 @@ class Count implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter = [], array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array|object $filter = [], private array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) { - throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object'); + if (isset($this->options['hint']) && ! is_string($this->options['hint']) && ! is_array($this->options['hint']) && ! is_object($this->options['hint'])) { + throw InvalidArgumentException::invalidType('"hint" option', $this->options['hint'], 'string or array or object'); } - if (isset($options['limit']) && ! is_integer($options['limit'])) { - throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); + if (isset($this->options['limit']) && ! is_integer($this->options['limit'])) { + throw InvalidArgumentException::invalidType('"limit" option', $this->options['limit'], 'integer'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { - throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); + if (isset($this->options['readConcern']) && ! $this->options['readConcern'] instanceof ReadConcern) { + throw InvalidArgumentException::invalidType('"readConcern" option', $this->options['readConcern'], ReadConcern::class); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['skip']) && ! is_integer($options['skip'])) { - throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); + if (isset($this->options['skip']) && ! is_integer($this->options['skip'])) { + throw InvalidArgumentException::invalidType('"skip" option', $this->options['skip'], 'integer'); } - if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { - unset($options['readConcern']); + if (isset($this->options['readConcern']) && $this->options['readConcern']->isDefault()) { + unset($this->options['readConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->filter = $filter; - $this->options = $options; } /** diff --git a/src/Operation/CountDocuments.php b/src/Operation/CountDocuments.php index fad2e94db..5d6502fca 100644 --- a/src/Operation/CountDocuments.php +++ b/src/Operation/CountDocuments.php @@ -39,13 +39,6 @@ */ class CountDocuments implements Executable { - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $filter; - private array $aggregateOptions; private array $countOptions; @@ -87,7 +80,7 @@ class CountDocuments implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array|object $filter, array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); @@ -101,10 +94,6 @@ public function __construct(string $databaseName, string $collectionName, $filte throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->filter = $filter; - $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]); diff --git a/src/Operation/CreateCollection.php b/src/Operation/CreateCollection.php index 470359542..3292e6fa7 100644 --- a/src/Operation/CreateCollection.php +++ b/src/Operation/CreateCollection.php @@ -46,12 +46,6 @@ class CreateCollection implements Executable public const USE_POWER_OF_2_SIZES = 1; public const NO_PADDING = 2; - private string $databaseName; - - private string $collectionName; - - private array $options = []; - /** * Constructs a create command. * @@ -139,111 +133,107 @@ class CreateCollection implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array $options = []) { - if (isset($options['autoIndexId']) && ! is_bool($options['autoIndexId'])) { - throw InvalidArgumentException::invalidType('"autoIndexId" option', $options['autoIndexId'], 'boolean'); + if (isset($this->options['autoIndexId']) && ! is_bool($this->options['autoIndexId'])) { + throw InvalidArgumentException::invalidType('"autoIndexId" option', $this->options['autoIndexId'], 'boolean'); } - if (isset($options['capped']) && ! is_bool($options['capped'])) { - throw InvalidArgumentException::invalidType('"capped" option', $options['capped'], 'boolean'); + if (isset($this->options['capped']) && ! is_bool($this->options['capped'])) { + throw InvalidArgumentException::invalidType('"capped" option', $this->options['capped'], 'boolean'); } - if (isset($options['changeStreamPreAndPostImages']) && ! is_document($options['changeStreamPreAndPostImages'])) { - throw InvalidArgumentException::expectedDocumentType('"changeStreamPreAndPostImages" option', $options['changeStreamPreAndPostImages']); + if (isset($this->options['changeStreamPreAndPostImages']) && ! is_document($this->options['changeStreamPreAndPostImages'])) { + throw InvalidArgumentException::expectedDocumentType('"changeStreamPreAndPostImages" option', $this->options['changeStreamPreAndPostImages']); } - if (isset($options['clusteredIndex']) && ! is_document($options['clusteredIndex'])) { - throw InvalidArgumentException::expectedDocumentType('"clusteredIndex" option', $options['clusteredIndex']); + if (isset($this->options['clusteredIndex']) && ! is_document($this->options['clusteredIndex'])) { + throw InvalidArgumentException::expectedDocumentType('"clusteredIndex" option', $this->options['clusteredIndex']); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['encryptedFields']) && ! is_document($options['encryptedFields'])) { - throw InvalidArgumentException::expectedDocumentType('"encryptedFields" option', $options['encryptedFields']); + if (isset($this->options['encryptedFields']) && ! is_document($this->options['encryptedFields'])) { + throw InvalidArgumentException::expectedDocumentType('"encryptedFields" option', $this->options['encryptedFields']); } - if (isset($options['expireAfterSeconds']) && ! is_integer($options['expireAfterSeconds'])) { - throw InvalidArgumentException::invalidType('"expireAfterSeconds" option', $options['expireAfterSeconds'], 'integer'); + if (isset($this->options['expireAfterSeconds']) && ! is_integer($this->options['expireAfterSeconds'])) { + throw InvalidArgumentException::invalidType('"expireAfterSeconds" option', $this->options['expireAfterSeconds'], 'integer'); } - if (isset($options['flags']) && ! is_integer($options['flags'])) { - throw InvalidArgumentException::invalidType('"flags" option', $options['flags'], 'integer'); + if (isset($this->options['flags']) && ! is_integer($this->options['flags'])) { + throw InvalidArgumentException::invalidType('"flags" option', $this->options['flags'], 'integer'); } - if (isset($options['indexOptionDefaults']) && ! is_document($options['indexOptionDefaults'])) { - throw InvalidArgumentException::expectedDocumentType('"indexOptionDefaults" option', $options['indexOptionDefaults']); + if (isset($this->options['indexOptionDefaults']) && ! is_document($this->options['indexOptionDefaults'])) { + throw InvalidArgumentException::expectedDocumentType('"indexOptionDefaults" option', $this->options['indexOptionDefaults']); } - if (isset($options['max']) && ! is_integer($options['max'])) { - throw InvalidArgumentException::invalidType('"max" option', $options['max'], 'integer'); + if (isset($this->options['max']) && ! is_integer($this->options['max'])) { + throw InvalidArgumentException::invalidType('"max" option', $this->options['max'], 'integer'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['pipeline']) && ! is_array($options['pipeline'])) { - throw InvalidArgumentException::invalidType('"pipeline" option', $options['pipeline'], 'array'); + if (isset($this->options['pipeline']) && ! is_array($this->options['pipeline'])) { + throw InvalidArgumentException::invalidType('"pipeline" option', $this->options['pipeline'], 'array'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['size']) && ! is_integer($options['size'])) { - throw InvalidArgumentException::invalidType('"size" option', $options['size'], 'integer'); + if (isset($this->options['size']) && ! is_integer($this->options['size'])) { + throw InvalidArgumentException::invalidType('"size" option', $this->options['size'], 'integer'); } - if (isset($options['storageEngine']) && ! is_document($options['storageEngine'])) { - throw InvalidArgumentException::expectedDocumentType('"storageEngine" option', $options['storageEngine']); + if (isset($this->options['storageEngine']) && ! is_document($this->options['storageEngine'])) { + throw InvalidArgumentException::expectedDocumentType('"storageEngine" option', $this->options['storageEngine']); } - if (isset($options['timeseries']) && ! is_document($options['timeseries'])) { - throw InvalidArgumentException::expectedDocumentType('"timeseries" option', $options['timeseries']); + if (isset($this->options['timeseries']) && ! is_document($this->options['timeseries'])) { + throw InvalidArgumentException::expectedDocumentType('"timeseries" option', $this->options['timeseries']); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['validationAction']) && ! is_string($options['validationAction'])) { - throw InvalidArgumentException::invalidType('"validationAction" option', $options['validationAction'], 'string'); + if (isset($this->options['validationAction']) && ! is_string($this->options['validationAction'])) { + throw InvalidArgumentException::invalidType('"validationAction" option', $this->options['validationAction'], 'string'); } - if (isset($options['validationLevel']) && ! is_string($options['validationLevel'])) { - throw InvalidArgumentException::invalidType('"validationLevel" option', $options['validationLevel'], 'string'); + if (isset($this->options['validationLevel']) && ! is_string($this->options['validationLevel'])) { + throw InvalidArgumentException::invalidType('"validationLevel" option', $this->options['validationLevel'], 'string'); } - if (isset($options['validator']) && ! is_document($options['validator'])) { - throw InvalidArgumentException::expectedDocumentType('"validator" option', $options['validator']); + if (isset($this->options['validator']) && ! is_document($this->options['validator'])) { + throw InvalidArgumentException::expectedDocumentType('"validator" option', $this->options['validator']); } - if (isset($options['viewOn']) && ! is_string($options['viewOn'])) { - throw InvalidArgumentException::invalidType('"viewOn" option', $options['viewOn'], 'string'); + if (isset($this->options['viewOn']) && ! is_string($this->options['viewOn'])) { + throw InvalidArgumentException::invalidType('"viewOn" option', $this->options['viewOn'], 'string'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - if (isset($options['autoIndexId'])) { + if (isset($this->options['autoIndexId'])) { trigger_error('The "autoIndexId" option is deprecated and will be removed in a future release', E_USER_DEPRECATED); } - if (isset($options['pipeline']) && ! is_pipeline($options['pipeline'], true /* allowEmpty */)) { + if (isset($this->options['pipeline']) && ! is_pipeline($this->options['pipeline'], true /* allowEmpty */)) { throw new InvalidArgumentException('"pipeline" option is not a valid aggregation pipeline'); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/CreateEncryptedCollection.php b/src/Operation/CreateEncryptedCollection.php index 113b83171..a5cde6514 100644 --- a/src/Operation/CreateEncryptedCollection.php +++ b/src/Operation/CreateEncryptedCollection.php @@ -59,12 +59,6 @@ class CreateEncryptedCollection implements Executable private CreateIndexes $createSafeContentIndex; - private string $databaseName; - - private string $collectionName; - - private array $options; - /** * @see CreateCollection::__construct() for supported options * @param string $databaseName Database name @@ -72,20 +66,20 @@ class CreateEncryptedCollection implements Executable * @param array $options CreateCollection options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options) + public function __construct(private string $databaseName, private string $collectionName, private array $options) { - if (! isset($options['encryptedFields'])) { + if (! isset($this->options['encryptedFields'])) { throw new InvalidArgumentException('"encryptedFields" option is required'); } - if (! is_document($options['encryptedFields'])) { - throw InvalidArgumentException::expectedDocumentType('"encryptedFields" option', $options['encryptedFields']); + if (! is_document($this->options['encryptedFields'])) { + throw InvalidArgumentException::expectedDocumentType('"encryptedFields" option', $this->options['encryptedFields']); } - $this->createCollection = new CreateCollection($databaseName, $collectionName, $options); + $this->createCollection = new CreateCollection($databaseName, $collectionName, $this->options); /** @psalm-var array{ecocCollection?: ?string, escCollection?: ?string} */ - $encryptedFields = document_to_array($options['encryptedFields']); + $encryptedFields = document_to_array($this->options['encryptedFields']); $enxcolOptions = ['clusteredIndex' => ['key' => ['_id' => 1], 'unique' => true]]; $this->createMetadataCollections = [ @@ -94,10 +88,6 @@ public function __construct(string $databaseName, string $collectionName, array ]; $this->createSafeContentIndex = new CreateIndexes($databaseName, $collectionName, [['key' => ['__safeContent__' => 1]]]); - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/CreateIndexes.php b/src/Operation/CreateIndexes.php index e5fc9b73c..396cc8163 100644 --- a/src/Operation/CreateIndexes.php +++ b/src/Operation/CreateIndexes.php @@ -45,15 +45,9 @@ class CreateIndexes implements Executable { private const WIRE_VERSION_FOR_COMMIT_QUORUM = 9; - private string $databaseName; - - private string $collectionName; - /** @var list */ private array $indexes = []; - private array $options = []; - /** * Constructs a createIndexes command. * @@ -80,7 +74,7 @@ class CreateIndexes implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $indexes, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array $indexes, private array $options = []) { if (empty($indexes)) { throw new InvalidArgumentException('$indexes is empty'); @@ -98,29 +92,25 @@ public function __construct(string $databaseName, string $collectionName, array $this->indexes[] = new IndexInput($index); } - if (isset($options['commitQuorum']) && ! is_string($options['commitQuorum']) && ! is_integer($options['commitQuorum'])) { - throw InvalidArgumentException::invalidType('"commitQuorum" option', $options['commitQuorum'], ['integer', 'string']); + if (isset($this->options['commitQuorum']) && ! is_string($this->options['commitQuorum']) && ! is_integer($this->options['commitQuorum'])) { + throw InvalidArgumentException::invalidType('"commitQuorum" option', $this->options['commitQuorum'], ['integer', 'string']); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/CreateSearchIndexes.php b/src/Operation/CreateSearchIndexes.php index 96e529b08..fd27b043c 100644 --- a/src/Operation/CreateSearchIndexes.php +++ b/src/Operation/CreateSearchIndexes.php @@ -39,10 +39,7 @@ */ class CreateSearchIndexes implements Executable { - private string $databaseName; - private string $collectionName; private array $indexes = []; - private array $options; /** * Constructs a createSearchIndexes command. @@ -53,7 +50,7 @@ class CreateSearchIndexes implements Executable * @param array{comment?: mixed} $options Command options * @throws InvalidArgumentException for parameter parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $indexes, array $options) + public function __construct(private string $databaseName, private string $collectionName, array $indexes, private array $options) { if (! array_is_list($indexes)) { throw new InvalidArgumentException('$indexes is not a list'); @@ -66,10 +63,6 @@ public function __construct(string $databaseName, string $collectionName, array $this->indexes[] = new SearchIndexInput($index); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/DatabaseCommand.php b/src/Operation/DatabaseCommand.php index adcccca37..4ae8214f1 100644 --- a/src/Operation/DatabaseCommand.php +++ b/src/Operation/DatabaseCommand.php @@ -34,12 +34,8 @@ */ class DatabaseCommand implements Executable { - private string $databaseName; - private Command $command; - private array $options; - /** * Constructs a command. * @@ -61,27 +57,25 @@ class DatabaseCommand implements Executable * @param array $options Options for command execution * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, $command, array $options = []) + public function __construct(private string $databaseName, array|object $command, private array $options = []) { if (! is_document($command)) { throw InvalidArgumentException::expectedDocumentType('$command', $command); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - $this->databaseName = $databaseName; $this->command = $command instanceof Command ? $command : new Command($command); - $this->options = $options; } /** diff --git a/src/Operation/Delete.php b/src/Operation/Delete.php index b23e1eac9..477cade91 100644 --- a/src/Operation/Delete.php +++ b/src/Operation/Delete.php @@ -46,17 +46,6 @@ class Delete implements Executable, Explainable { private const WIRE_VERSION_FOR_HINT = 9; - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $filter; - - private int $limit; - - private array $options; - /** * Constructs a delete command. * @@ -93,7 +82,7 @@ class Delete implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, int $limit, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array|object $filter, private int $limit, private array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); @@ -103,35 +92,29 @@ public function __construct(string $databaseName, string $collectionName, $filte throw new InvalidArgumentException('$limit must be 0 or 1'); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) { - throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], ['string', 'array', 'object']); + if (isset($this->options['hint']) && ! is_string($this->options['hint']) && ! is_array($this->options['hint']) && ! is_object($this->options['hint'])) { + throw InvalidArgumentException::invalidType('"hint" option', $this->options['hint'], ['string', 'array', 'object']); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['let']) && ! is_document($options['let'])) { - throw InvalidArgumentException::expectedDocumentType('"let" option', $options['let']); + if (isset($this->options['let']) && ! is_document($this->options['let'])) { + throw InvalidArgumentException::expectedDocumentType('"let" option', $this->options['let']); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->filter = $filter; - $this->limit = $limit; - $this->options = $options; } /** diff --git a/src/Operation/DeleteMany.php b/src/Operation/DeleteMany.php index 9f580133e..20ca38d1d 100644 --- a/src/Operation/DeleteMany.php +++ b/src/Operation/DeleteMany.php @@ -66,7 +66,7 @@ class DeleteMany implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array $options = []) { $this->delete = new Delete($databaseName, $collectionName, $filter, 0, $options); } diff --git a/src/Operation/DeleteOne.php b/src/Operation/DeleteOne.php index 3e2c3e089..1aaad5d27 100644 --- a/src/Operation/DeleteOne.php +++ b/src/Operation/DeleteOne.php @@ -66,7 +66,7 @@ class DeleteOne implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array $options = []) { $this->delete = new Delete($databaseName, $collectionName, $filter, 1, $options); } diff --git a/src/Operation/Distinct.php b/src/Operation/Distinct.php index 6397c300e..1483012f3 100644 --- a/src/Operation/Distinct.php +++ b/src/Operation/Distinct.php @@ -42,17 +42,6 @@ */ class Distinct implements Executable, Explainable { - private string $databaseName; - - private string $collectionName; - - private string $fieldName; - - /** @var array|object */ - private $filter; - - private array $options; - /** * Constructs a distinct command. * @@ -82,45 +71,39 @@ class Distinct implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, string $fieldName, $filter = [], array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private string $fieldName, private array|object $filter = [], private array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { - throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); + if (isset($this->options['readConcern']) && ! $this->options['readConcern'] instanceof ReadConcern) { + throw InvalidArgumentException::invalidType('"readConcern" option', $this->options['readConcern'], ReadConcern::class); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { - unset($options['readConcern']); + if (isset($this->options['readConcern']) && $this->options['readConcern']->isDefault()) { + unset($this->options['readConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->fieldName = $fieldName; - $this->filter = $filter; - $this->options = $options; } /** diff --git a/src/Operation/DropCollection.php b/src/Operation/DropCollection.php index d24f9fd88..a467a7391 100644 --- a/src/Operation/DropCollection.php +++ b/src/Operation/DropCollection.php @@ -40,12 +40,6 @@ class DropCollection implements Executable { private const ERROR_CODE_NAMESPACE_NOT_FOUND = 26; - private string $databaseName; - - private string $collectionName; - - private array $options; - /** * Constructs a drop command. * @@ -67,27 +61,23 @@ class DropCollection implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array $options = []) { - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/DropDatabase.php b/src/Operation/DropDatabase.php index 76a3d772f..15cb0c34e 100644 --- a/src/Operation/DropDatabase.php +++ b/src/Operation/DropDatabase.php @@ -36,10 +36,6 @@ */ class DropDatabase implements Executable { - private string $databaseName; - - private array $options; - /** * Constructs a dropDatabase command. * @@ -60,26 +56,23 @@ class DropDatabase implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, array $options = []) + public function __construct(private string $databaseName, private array $options = []) { - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->options = $options; } /** diff --git a/src/Operation/DropIndexes.php b/src/Operation/DropIndexes.php index 0bbd08247..c5302e250 100644 --- a/src/Operation/DropIndexes.php +++ b/src/Operation/DropIndexes.php @@ -37,14 +37,6 @@ */ class DropIndexes implements Executable { - private string $databaseName; - - private string $collectionName; - - private string $indexName; - - private array $options; - /** * Constructs a dropIndexes command. * @@ -70,36 +62,31 @@ class DropIndexes implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, string $indexName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private string $indexName, private array $options = []) { if ($indexName === '') { throw new InvalidArgumentException('$indexName cannot be empty'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->indexName = $indexName; - $this->options = $options; } /** diff --git a/src/Operation/DropSearchIndex.php b/src/Operation/DropSearchIndex.php index a8a6ff1b7..42fc58baa 100644 --- a/src/Operation/DropSearchIndex.php +++ b/src/Operation/DropSearchIndex.php @@ -34,11 +34,6 @@ class DropSearchIndex implements Executable { private const ERROR_CODE_NAMESPACE_NOT_FOUND = 26; - private string $databaseName; - private string $collectionName; - private string $name; - private array $options; - /** * Constructs a dropSearchIndex command. * @@ -48,16 +43,11 @@ class DropSearchIndex implements Executable * @param array{comment?: mixed} $options Command options * @throws InvalidArgumentException for parameter parsing errors */ - public function __construct(string $databaseName, string $collectionName, string $name, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private string $name, private array $options = []) { if ($name === '') { throw new InvalidArgumentException('Index name cannot be empty'); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->name = $name; - $this->options = $options; } /** diff --git a/src/Operation/EstimatedDocumentCount.php b/src/Operation/EstimatedDocumentCount.php index 718a0142c..e3c240c78 100644 --- a/src/Operation/EstimatedDocumentCount.php +++ b/src/Operation/EstimatedDocumentCount.php @@ -37,10 +37,6 @@ */ class EstimatedDocumentCount implements Executable, Explainable { - private string $databaseName; - - private string $collectionName; - private array $options; /** @@ -67,11 +63,8 @@ class EstimatedDocumentCount implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array $options = []) { - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); } diff --git a/src/Operation/Explain.php b/src/Operation/Explain.php index e90278a73..1c132b2f5 100644 --- a/src/Operation/Explain.php +++ b/src/Operation/Explain.php @@ -41,12 +41,6 @@ class Explain implements Executable public const VERBOSITY_EXEC_STATS = 'executionStats'; public const VERBOSITY_QUERY = 'queryPlanner'; - private string $databaseName; - - private Explainable $explainable; - - private array $options; - /** * Constructs an explain command for explainable operations. * @@ -70,27 +64,23 @@ class Explain implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, Explainable $explainable, array $options = []) + public function __construct(private string $databaseName, private Explainable $explainable, private array $options = []) { - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['verbosity']) && ! is_string($options['verbosity'])) { - throw InvalidArgumentException::invalidType('"verbosity" option', $options['verbosity'], 'string'); + if (isset($this->options['verbosity']) && ! is_string($this->options['verbosity'])) { + throw InvalidArgumentException::invalidType('"verbosity" option', $this->options['verbosity'], 'string'); } - - $this->databaseName = $databaseName; - $this->explainable = $explainable; - $this->options = $options; } /** diff --git a/src/Operation/Find.php b/src/Operation/Find.php index 23b33d482..13944a682 100644 --- a/src/Operation/Find.php +++ b/src/Operation/Find.php @@ -54,15 +54,6 @@ class Find implements Executable, Explainable public const TAILABLE = 2; public const TAILABLE_AWAIT = 3; - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $filter; - - private array $options; - /** * Constructs a find command. * @@ -164,150 +155,145 @@ class Find implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array|object $filter, private array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); } - if (isset($options['allowDiskUse']) && ! is_bool($options['allowDiskUse'])) { - throw InvalidArgumentException::invalidType('"allowDiskUse" option', $options['allowDiskUse'], 'boolean'); + if (isset($this->options['allowDiskUse']) && ! is_bool($this->options['allowDiskUse'])) { + throw InvalidArgumentException::invalidType('"allowDiskUse" option', $this->options['allowDiskUse'], 'boolean'); } - if (isset($options['allowPartialResults']) && ! is_bool($options['allowPartialResults'])) { - throw InvalidArgumentException::invalidType('"allowPartialResults" option', $options['allowPartialResults'], 'boolean'); + if (isset($this->options['allowPartialResults']) && ! is_bool($this->options['allowPartialResults'])) { + throw InvalidArgumentException::invalidType('"allowPartialResults" option', $this->options['allowPartialResults'], 'boolean'); } - if (isset($options['batchSize']) && ! is_integer($options['batchSize'])) { - throw InvalidArgumentException::invalidType('"batchSize" option', $options['batchSize'], 'integer'); + if (isset($this->options['batchSize']) && ! is_integer($this->options['batchSize'])) { + throw InvalidArgumentException::invalidType('"batchSize" option', $this->options['batchSize'], 'integer'); } - if (isset($options['codec']) && ! $options['codec'] instanceof DocumentCodec) { - throw InvalidArgumentException::invalidType('"codec" option', $options['codec'], DocumentCodec::class); + if (isset($this->options['codec']) && ! $this->options['codec'] instanceof DocumentCodec) { + throw InvalidArgumentException::invalidType('"codec" option', $this->options['codec'], DocumentCodec::class); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['cursorType'])) { - if (! is_integer($options['cursorType'])) { - throw InvalidArgumentException::invalidType('"cursorType" option', $options['cursorType'], 'integer'); + if (isset($this->options['cursorType'])) { + if (! is_integer($this->options['cursorType'])) { + throw InvalidArgumentException::invalidType('"cursorType" option', $this->options['cursorType'], 'integer'); } if ( - $options['cursorType'] !== self::NON_TAILABLE && - $options['cursorType'] !== self::TAILABLE && - $options['cursorType'] !== self::TAILABLE_AWAIT + $this->options['cursorType'] !== self::NON_TAILABLE && + $this->options['cursorType'] !== self::TAILABLE && + $this->options['cursorType'] !== self::TAILABLE_AWAIT ) { - throw new InvalidArgumentException('Invalid value for "cursorType" option: ' . $options['cursorType']); + throw new InvalidArgumentException('Invalid value for "cursorType" option: ' . $this->options['cursorType']); } } - if (isset($options['hint']) && ! is_string($options['hint']) && ! is_array($options['hint']) && ! is_object($options['hint'])) { - throw InvalidArgumentException::invalidType('"hint" option', $options['hint'], 'string or array or object'); + if (isset($this->options['hint']) && ! is_string($this->options['hint']) && ! is_array($this->options['hint']) && ! is_object($this->options['hint'])) { + throw InvalidArgumentException::invalidType('"hint" option', $this->options['hint'], 'string or array or object'); } - if (isset($options['limit']) && ! is_integer($options['limit'])) { - throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); + if (isset($this->options['limit']) && ! is_integer($this->options['limit'])) { + throw InvalidArgumentException::invalidType('"limit" option', $this->options['limit'], 'integer'); } - if (isset($options['max']) && ! is_document($options['max'])) { - throw InvalidArgumentException::expectedDocumentType('"max" option', $options['max']); + if (isset($this->options['max']) && ! is_document($this->options['max'])) { + throw InvalidArgumentException::expectedDocumentType('"max" option', $this->options['max']); } - if (isset($options['maxAwaitTimeMS']) && ! is_integer($options['maxAwaitTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxAwaitTimeMS" option', $options['maxAwaitTimeMS'], 'integer'); + if (isset($this->options['maxAwaitTimeMS']) && ! is_integer($this->options['maxAwaitTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxAwaitTimeMS" option', $this->options['maxAwaitTimeMS'], 'integer'); } - if (isset($options['maxScan']) && ! is_integer($options['maxScan'])) { - throw InvalidArgumentException::invalidType('"maxScan" option', $options['maxScan'], 'integer'); + if (isset($this->options['maxScan']) && ! is_integer($this->options['maxScan'])) { + throw InvalidArgumentException::invalidType('"maxScan" option', $this->options['maxScan'], 'integer'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['min']) && ! is_document($options['min'])) { - throw InvalidArgumentException::expectedDocumentType('"min" option', $options['min']); + if (isset($this->options['min']) && ! is_document($this->options['min'])) { + throw InvalidArgumentException::expectedDocumentType('"min" option', $this->options['min']); } - if (isset($options['modifiers']) && ! is_document($options['modifiers'])) { - throw InvalidArgumentException::expectedDocumentType('"modifiers" option', $options['modifiers']); + if (isset($this->options['modifiers']) && ! is_document($this->options['modifiers'])) { + throw InvalidArgumentException::expectedDocumentType('"modifiers" option', $this->options['modifiers']); } - if (isset($options['noCursorTimeout']) && ! is_bool($options['noCursorTimeout'])) { - throw InvalidArgumentException::invalidType('"noCursorTimeout" option', $options['noCursorTimeout'], 'boolean'); + if (isset($this->options['noCursorTimeout']) && ! is_bool($this->options['noCursorTimeout'])) { + throw InvalidArgumentException::invalidType('"noCursorTimeout" option', $this->options['noCursorTimeout'], 'boolean'); } - if (isset($options['oplogReplay']) && ! is_bool($options['oplogReplay'])) { - throw InvalidArgumentException::invalidType('"oplogReplay" option', $options['oplogReplay'], 'boolean'); + if (isset($this->options['oplogReplay']) && ! is_bool($this->options['oplogReplay'])) { + throw InvalidArgumentException::invalidType('"oplogReplay" option', $this->options['oplogReplay'], 'boolean'); } - if (isset($options['projection']) && ! is_document($options['projection'])) { - throw InvalidArgumentException::expectedDocumentType('"projection" option', $options['projection']); + if (isset($this->options['projection']) && ! is_document($this->options['projection'])) { + throw InvalidArgumentException::expectedDocumentType('"projection" option', $this->options['projection']); } - if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { - throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); + if (isset($this->options['readConcern']) && ! $this->options['readConcern'] instanceof ReadConcern) { + throw InvalidArgumentException::invalidType('"readConcern" option', $this->options['readConcern'], ReadConcern::class); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['returnKey']) && ! is_bool($options['returnKey'])) { - throw InvalidArgumentException::invalidType('"returnKey" option', $options['returnKey'], 'boolean'); + if (isset($this->options['returnKey']) && ! is_bool($this->options['returnKey'])) { + throw InvalidArgumentException::invalidType('"returnKey" option', $this->options['returnKey'], 'boolean'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['showRecordId']) && ! is_bool($options['showRecordId'])) { - throw InvalidArgumentException::invalidType('"showRecordId" option', $options['showRecordId'], 'boolean'); + if (isset($this->options['showRecordId']) && ! is_bool($this->options['showRecordId'])) { + throw InvalidArgumentException::invalidType('"showRecordId" option', $this->options['showRecordId'], 'boolean'); } - if (isset($options['skip']) && ! is_integer($options['skip'])) { - throw InvalidArgumentException::invalidType('"skip" option', $options['skip'], 'integer'); + if (isset($this->options['skip']) && ! is_integer($this->options['skip'])) { + throw InvalidArgumentException::invalidType('"skip" option', $this->options['skip'], 'integer'); } - if (isset($options['snapshot']) && ! is_bool($options['snapshot'])) { - throw InvalidArgumentException::invalidType('"snapshot" option', $options['snapshot'], 'boolean'); + if (isset($this->options['snapshot']) && ! is_bool($this->options['snapshot'])) { + throw InvalidArgumentException::invalidType('"snapshot" option', $this->options['snapshot'], 'boolean'); } - if (isset($options['sort']) && ! is_document($options['sort'])) { - throw InvalidArgumentException::expectedDocumentType('"sort" option', $options['sort']); + if (isset($this->options['sort']) && ! is_document($this->options['sort'])) { + throw InvalidArgumentException::expectedDocumentType('"sort" option', $this->options['sort']); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['let']) && ! is_document($options['let'])) { - throw InvalidArgumentException::expectedDocumentType('"let" option', $options['let']); + if (isset($this->options['let']) && ! is_document($this->options['let'])) { + throw InvalidArgumentException::expectedDocumentType('"let" option', $this->options['let']); } - if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { - unset($options['readConcern']); + if (isset($this->options['readConcern']) && $this->options['readConcern']->isDefault()) { + unset($this->options['readConcern']); } - if (isset($options['snapshot'])) { + if (isset($this->options['snapshot'])) { trigger_error('The "snapshot" option is deprecated and will be removed in a future release', E_USER_DEPRECATED); } - if (isset($options['maxScan'])) { + if (isset($this->options['maxScan'])) { trigger_error('The "maxScan" option is deprecated and will be removed in a future release', E_USER_DEPRECATED); } - if (isset($options['codec']) && isset($options['typeMap'])) { + if (isset($this->options['codec']) && isset($this->options['typeMap'])) { throw InvalidArgumentException::cannotCombineCodecAndTypeMap(); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->filter = $filter; - $this->options = $options; } /** diff --git a/src/Operation/FindAndModify.php b/src/Operation/FindAndModify.php index 300f4e97a..e67413b6c 100644 --- a/src/Operation/FindAndModify.php +++ b/src/Operation/FindAndModify.php @@ -57,10 +57,6 @@ class FindAndModify implements Executable, Explainable private const WIRE_VERSION_FOR_UNSUPPORTED_OPTION_SERVER_SIDE_ERROR = 8; - private string $databaseName; - - private string $collectionName; - private array $options; /** @@ -131,7 +127,7 @@ class FindAndModify implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options) + public function __construct(private string $databaseName, private string $collectionName, array $options) { $options += ['remove' => false]; @@ -219,8 +215,6 @@ public function __construct(string $databaseName, string $collectionName, array throw InvalidArgumentException::cannotCombineCodecAndTypeMap(); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; $this->options = $options; } diff --git a/src/Operation/FindOne.php b/src/Operation/FindOne.php index 48f931fab..6fdff0a29 100644 --- a/src/Operation/FindOne.php +++ b/src/Operation/FindOne.php @@ -104,7 +104,7 @@ class FindOne implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array $options = []) { $this->find = new Find( $databaseName, diff --git a/src/Operation/FindOneAndDelete.php b/src/Operation/FindOneAndDelete.php index cae2a1788..ae5148872 100644 --- a/src/Operation/FindOneAndDelete.php +++ b/src/Operation/FindOneAndDelete.php @@ -81,7 +81,7 @@ class FindOneAndDelete implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); diff --git a/src/Operation/FindOneAndReplace.php b/src/Operation/FindOneAndReplace.php index 20412d645..6f4409406 100644 --- a/src/Operation/FindOneAndReplace.php +++ b/src/Operation/FindOneAndReplace.php @@ -102,7 +102,7 @@ class FindOneAndReplace implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $replacement, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array|object $replacement, array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); @@ -171,11 +171,8 @@ public function getCommandDocument() return $this->findAndModify->getCommandDocument(); } - /** - * @param array|object $replacement - * @return array|object - */ - private function validateReplacement($replacement, ?DocumentCodec $codec) + /** @return array|object */ + private function validateReplacement(array|object $replacement, ?DocumentCodec $codec) { if (isset($codec)) { $replacement = $codec->encode($replacement); diff --git a/src/Operation/FindOneAndUpdate.php b/src/Operation/FindOneAndUpdate.php index 783888b1f..0fbe127d0 100644 --- a/src/Operation/FindOneAndUpdate.php +++ b/src/Operation/FindOneAndUpdate.php @@ -23,9 +23,7 @@ use MongoDB\Exception\UnsupportedException; use function array_key_exists; -use function is_array; use function is_integer; -use function is_object; use function MongoDB\is_document; use function MongoDB\is_first_key_operator; use function MongoDB\is_pipeline; @@ -106,16 +104,12 @@ class FindOneAndUpdate implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $update, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array|object $update, array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); } - if (! is_array($update) && ! is_object($update)) { - throw InvalidArgumentException::invalidType('$update', $update, 'array or object'); - } - if (! is_first_key_operator($update) && ! is_pipeline($update)) { throw new InvalidArgumentException('Expected update operator(s) or non-empty pipeline for $update'); } diff --git a/src/Operation/InsertMany.php b/src/Operation/InsertMany.php index 42b3a344f..01640da2f 100644 --- a/src/Operation/InsertMany.php +++ b/src/Operation/InsertMany.php @@ -40,10 +40,6 @@ */ class InsertMany implements Executable { - private string $databaseName; - - private string $collectionName; - /** @var list */ private array $documents; @@ -79,7 +75,7 @@ class InsertMany implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $documents, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array $documents, array $options = []) { $options += ['ordered' => true]; @@ -111,8 +107,6 @@ public function __construct(string $databaseName, string $collectionName, array unset($options['writeConcern']); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; $this->documents = $this->validateDocuments($documents, $options['codec'] ?? null); $this->options = $options; } diff --git a/src/Operation/InsertOne.php b/src/Operation/InsertOne.php index f745664d7..8626364f8 100644 --- a/src/Operation/InsertOne.php +++ b/src/Operation/InsertOne.php @@ -38,14 +38,7 @@ */ class InsertOne implements Executable { - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $document; - - private array $options; + private array|object $document; /** * Constructs an insert command. @@ -72,36 +65,33 @@ class InsertOne implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $document, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array|object $document, private array $options = []) { - if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) { - throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); + if (isset($this->options['bypassDocumentValidation']) && ! is_bool($this->options['bypassDocumentValidation'])) { + throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $this->options['bypassDocumentValidation'], 'boolean'); } - if (isset($options['codec']) && ! $options['codec'] instanceof DocumentCodec) { - throw InvalidArgumentException::invalidType('"codec" option', $options['codec'], DocumentCodec::class); + if (isset($this->options['codec']) && ! $this->options['codec'] instanceof DocumentCodec) { + throw InvalidArgumentException::invalidType('"codec" option', $this->options['codec'], DocumentCodec::class); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) { - unset($options['bypassDocumentValidation']); + if (isset($this->options['bypassDocumentValidation']) && ! $this->options['bypassDocumentValidation']) { + unset($this->options['bypassDocumentValidation']); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->document = $this->validateDocument($document, $options['codec'] ?? null); - $this->options = $options; + $this->document = $this->validateDocument($document, $this->options['codec'] ?? null); } /** @@ -166,11 +156,8 @@ private function createExecuteOptions(): array return $options; } - /** - * @param array|object $document - * @return array|object - */ - private function validateDocument($document, ?DocumentCodec $codec) + /** @return array|object */ + private function validateDocument(array|object $document, ?DocumentCodec $codec) { if ($codec) { $document = $codec->encode($document); diff --git a/src/Operation/ListCollections.php b/src/Operation/ListCollections.php index 36d0bc446..340c11017 100644 --- a/src/Operation/ListCollections.php +++ b/src/Operation/ListCollections.php @@ -32,8 +32,6 @@ */ class ListCollections implements Executable { - private string $databaseName; - private ListCollectionsCommand $listCollections; /** @@ -61,9 +59,8 @@ class ListCollections implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, array $options = []) + public function __construct(private string $databaseName, array $options = []) { - $this->databaseName = $databaseName; $this->listCollections = new ListCollectionsCommand($databaseName, ['nameOnly' => false] + $options); } diff --git a/src/Operation/ListIndexes.php b/src/Operation/ListIndexes.php index 1a5723d70..384a5f498 100644 --- a/src/Operation/ListIndexes.php +++ b/src/Operation/ListIndexes.php @@ -41,12 +41,6 @@ class ListIndexes implements Executable private const ERROR_CODE_DATABASE_NOT_FOUND = 60; private const ERROR_CODE_NAMESPACE_NOT_FOUND = 26; - private string $databaseName; - - private string $collectionName; - - private array $options; - /** * Constructs a listIndexes command. * @@ -66,19 +60,15 @@ class ListIndexes implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array $options = []) { - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->options = $options; } /** diff --git a/src/Operation/ListSearchIndexes.php b/src/Operation/ListSearchIndexes.php index 8cf7f1e56..2dbb3688b 100644 --- a/src/Operation/ListSearchIndexes.php +++ b/src/Operation/ListSearchIndexes.php @@ -37,8 +37,6 @@ */ class ListSearchIndexes implements Executable { - private string $databaseName; - private string $collectionName; private array $listSearchIndexesOptions; private array $aggregateOptions; private Aggregate $aggregate; @@ -50,7 +48,7 @@ class ListSearchIndexes implements Executable * @param string $collectionName Collection name * @param array{name?: string} $options Command options */ - public function __construct(string $databaseName, string $collectionName, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, array $options = []) { if (isset($options['name']) && ! is_string($options['name'])) { throw InvalidArgumentException::invalidType('"name" option', $options['name'], 'string'); @@ -60,8 +58,6 @@ public function __construct(string $databaseName, string $collectionName, array throw new InvalidArgumentException('"name" option cannot be empty'); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; $this->listSearchIndexesOptions = array_intersect_key($options, ['name' => 1]); $this->aggregateOptions = array_intersect_key($options, ['batchSize' => 1, 'codec' => 1, 'collation' => 1, 'comment' => 1, 'maxTimeMS' => 1, 'readConcern' => 1, 'readPreference' => 1, 'session' => 1, 'typeMap' => 1]); diff --git a/src/Operation/MapReduce.php b/src/Operation/MapReduce.php index 211b20176..faf91019c 100644 --- a/src/Operation/MapReduce.php +++ b/src/Operation/MapReduce.php @@ -56,18 +56,7 @@ */ class MapReduce implements Executable { - private string $databaseName; - - private string $collectionName; - - private JavascriptInterface $map; - - private JavascriptInterface $reduce; - - /** @var array|object|string */ - private $out; - - private array $options; + private array|object|string $out; /** * Constructs a mapReduce command. @@ -156,82 +145,78 @@ class MapReduce implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, JavascriptInterface $map, JavascriptInterface $reduce, $out, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private JavascriptInterface $map, private JavascriptInterface $reduce, string|array|object $out, private array $options = []) { - if (! is_string($out) && ! is_array($out) && ! is_object($out)) { - throw InvalidArgumentException::invalidType('$out', $out, 'string or array or object'); - } - - if (isset($options['bypassDocumentValidation']) && ! is_bool($options['bypassDocumentValidation'])) { - throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $options['bypassDocumentValidation'], 'boolean'); + if (isset($this->options['bypassDocumentValidation']) && ! is_bool($this->options['bypassDocumentValidation'])) { + throw InvalidArgumentException::invalidType('"bypassDocumentValidation" option', $this->options['bypassDocumentValidation'], 'boolean'); } - if (isset($options['collation']) && ! is_document($options['collation'])) { - throw InvalidArgumentException::expectedDocumentType('"collation" option', $options['collation']); + if (isset($this->options['collation']) && ! is_document($this->options['collation'])) { + throw InvalidArgumentException::expectedDocumentType('"collation" option', $this->options['collation']); } - if (isset($options['finalize']) && ! $options['finalize'] instanceof JavascriptInterface) { - throw InvalidArgumentException::invalidType('"finalize" option', $options['finalize'], JavascriptInterface::class); + if (isset($this->options['finalize']) && ! $this->options['finalize'] instanceof JavascriptInterface) { + throw InvalidArgumentException::invalidType('"finalize" option', $this->options['finalize'], JavascriptInterface::class); } - if (isset($options['jsMode']) && ! is_bool($options['jsMode'])) { - throw InvalidArgumentException::invalidType('"jsMode" option', $options['jsMode'], 'boolean'); + if (isset($this->options['jsMode']) && ! is_bool($this->options['jsMode'])) { + throw InvalidArgumentException::invalidType('"jsMode" option', $this->options['jsMode'], 'boolean'); } - if (isset($options['limit']) && ! is_integer($options['limit'])) { - throw InvalidArgumentException::invalidType('"limit" option', $options['limit'], 'integer'); + if (isset($this->options['limit']) && ! is_integer($this->options['limit'])) { + throw InvalidArgumentException::invalidType('"limit" option', $this->options['limit'], 'integer'); } - if (isset($options['maxTimeMS']) && ! is_integer($options['maxTimeMS'])) { - throw InvalidArgumentException::invalidType('"maxTimeMS" option', $options['maxTimeMS'], 'integer'); + if (isset($this->options['maxTimeMS']) && ! is_integer($this->options['maxTimeMS'])) { + throw InvalidArgumentException::invalidType('"maxTimeMS" option', $this->options['maxTimeMS'], 'integer'); } - if (isset($options['query']) && ! is_document($options['query'])) { - throw InvalidArgumentException::expectedDocumentType('"query" option', $options['query']); + if (isset($this->options['query']) && ! is_document($this->options['query'])) { + throw InvalidArgumentException::expectedDocumentType('"query" option', $this->options['query']); } - if (isset($options['readConcern']) && ! $options['readConcern'] instanceof ReadConcern) { - throw InvalidArgumentException::invalidType('"readConcern" option', $options['readConcern'], ReadConcern::class); + if (isset($this->options['readConcern']) && ! $this->options['readConcern'] instanceof ReadConcern) { + throw InvalidArgumentException::invalidType('"readConcern" option', $this->options['readConcern'], ReadConcern::class); } - if (isset($options['readPreference']) && ! $options['readPreference'] instanceof ReadPreference) { - throw InvalidArgumentException::invalidType('"readPreference" option', $options['readPreference'], ReadPreference::class); + if (isset($this->options['readPreference']) && ! $this->options['readPreference'] instanceof ReadPreference) { + throw InvalidArgumentException::invalidType('"readPreference" option', $this->options['readPreference'], ReadPreference::class); } - if (isset($options['scope']) && ! is_document($options['scope'])) { - throw InvalidArgumentException::expectedDocumentType('"scope" option', $options['scope']); + if (isset($this->options['scope']) && ! is_document($this->options['scope'])) { + throw InvalidArgumentException::expectedDocumentType('"scope" option', $this->options['scope']); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['sort']) && ! is_document($options['sort'])) { - throw InvalidArgumentException::expectedDocumentType('"sort" option', $options['sort']); + if (isset($this->options['sort']) && ! is_document($this->options['sort'])) { + throw InvalidArgumentException::expectedDocumentType('"sort" option', $this->options['sort']); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['verbose']) && ! is_bool($options['verbose'])) { - throw InvalidArgumentException::invalidType('"verbose" option', $options['verbose'], 'boolean'); + if (isset($this->options['verbose']) && ! is_bool($this->options['verbose'])) { + throw InvalidArgumentException::invalidType('"verbose" option', $this->options['verbose'], 'boolean'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['bypassDocumentValidation']) && ! $options['bypassDocumentValidation']) { - unset($options['bypassDocumentValidation']); + if (isset($this->options['bypassDocumentValidation']) && ! $this->options['bypassDocumentValidation']) { + unset($this->options['bypassDocumentValidation']); } - if (isset($options['readConcern']) && $options['readConcern']->isDefault()) { - unset($options['readConcern']); + if (isset($this->options['readConcern']) && $this->options['readConcern']->isDefault()) { + unset($this->options['readConcern']); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } // Handle deprecation of CodeWScope @@ -243,18 +228,13 @@ public function __construct(string $databaseName, string $collectionName, Javasc @trigger_error('Use of Javascript with scope in "$reduce" argument for MapReduce is deprecated. Put all scope variables in the "scope" option of the MapReduce operation.', E_USER_DEPRECATED); } - if (isset($options['finalize']) && $options['finalize']->getScope() !== null) { + if (isset($this->options['finalize']) && $this->options['finalize']->getScope() !== null) { @trigger_error('Use of Javascript with scope in "finalize" option for MapReduce is deprecated. Put all scope variables in the "scope" option of the MapReduce operation.', E_USER_DEPRECATED); } $this->checkOutDeprecations($out); - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->map = $map; - $this->reduce = $reduce; $this->out = $out; - $this->options = $options; } /** @@ -306,8 +286,7 @@ public function execute(Server $server) return new MapReduceResult($getIterator, $result); } - /** @param string|array|object $out */ - private function checkOutDeprecations($out): void + private function checkOutDeprecations(string|array|object $out): void { if (is_string($out)) { return; diff --git a/src/Operation/ModifyCollection.php b/src/Operation/ModifyCollection.php index a10bce5e8..53eaa9e09 100644 --- a/src/Operation/ModifyCollection.php +++ b/src/Operation/ModifyCollection.php @@ -35,14 +35,6 @@ */ class ModifyCollection implements Executable { - private string $databaseName; - - private string $collectionName; - - private array $collectionOptions; - - private array $options; - /** * Constructs a collMod command. * @@ -65,32 +57,27 @@ class ModifyCollection implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, array $collectionOptions, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array $collectionOptions, private array $options = []) { if (empty($collectionOptions)) { throw new InvalidArgumentException('$collectionOptions is empty'); } - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->collectionOptions = $collectionOptions; - $this->options = $options; } /** diff --git a/src/Operation/RenameCollection.php b/src/Operation/RenameCollection.php index 5be7d4dff..5b69cce41 100644 --- a/src/Operation/RenameCollection.php +++ b/src/Operation/RenameCollection.php @@ -42,8 +42,6 @@ class RenameCollection implements Executable private string $toNamespace; - private array $options; - /** * Constructs a renameCollection command. * @@ -70,31 +68,30 @@ class RenameCollection implements Executable * @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 = []) + public function __construct(string $fromDatabaseName, string $fromCollectionName, string $toDatabaseName, string $toCollectionName, private array $options = []) { - if (isset($options['session']) && ! $options['session'] instanceof Session) { - throw InvalidArgumentException::invalidType('"session" option', $options['session'], Session::class); + if (isset($this->options['session']) && ! $this->options['session'] instanceof Session) { + throw InvalidArgumentException::invalidType('"session" option', $this->options['session'], Session::class); } - if (isset($options['typeMap']) && ! is_array($options['typeMap'])) { - throw InvalidArgumentException::invalidType('"typeMap" option', $options['typeMap'], 'array'); + if (isset($this->options['typeMap']) && ! is_array($this->options['typeMap'])) { + throw InvalidArgumentException::invalidType('"typeMap" option', $this->options['typeMap'], 'array'); } - if (isset($options['writeConcern']) && ! $options['writeConcern'] instanceof WriteConcern) { - throw InvalidArgumentException::invalidType('"writeConcern" option', $options['writeConcern'], WriteConcern::class); + if (isset($this->options['writeConcern']) && ! $this->options['writeConcern'] instanceof WriteConcern) { + throw InvalidArgumentException::invalidType('"writeConcern" option', $this->options['writeConcern'], WriteConcern::class); } - if (isset($options['writeConcern']) && $options['writeConcern']->isDefault()) { - unset($options['writeConcern']); + if (isset($this->options['writeConcern']) && $this->options['writeConcern']->isDefault()) { + unset($this->options['writeConcern']); } - if (isset($options['dropTarget']) && ! is_bool($options['dropTarget'])) { - throw InvalidArgumentException::invalidType('"dropTarget" option', $options['dropTarget'], 'boolean'); + if (isset($this->options['dropTarget']) && ! is_bool($this->options['dropTarget'])) { + throw InvalidArgumentException::invalidType('"dropTarget" option', $this->options['dropTarget'], 'boolean'); } $this->fromNamespace = $fromDatabaseName . '.' . $fromCollectionName; $this->toNamespace = $toDatabaseName . '.' . $toCollectionName; - $this->options = $options; } /** diff --git a/src/Operation/ReplaceOne.php b/src/Operation/ReplaceOne.php index 943206761..32bf5a06d 100644 --- a/src/Operation/ReplaceOne.php +++ b/src/Operation/ReplaceOne.php @@ -81,7 +81,7 @@ class ReplaceOne implements Executable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $replacement, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array|object $replacement, array $options = []) { if (isset($options['codec']) && ! $options['codec'] instanceof DocumentCodec) { throw InvalidArgumentException::invalidType('"codec" option', $options['codec'], DocumentCodec::class); @@ -113,11 +113,8 @@ public function execute(Server $server) return $this->update->execute($server); } - /** - * @param array|object $replacement - * @return array|object - */ - private function validateReplacement($replacement, ?DocumentCodec $codec) + /** @return array|object */ + private function validateReplacement(array|object $replacement, ?DocumentCodec $codec) { if ($codec) { $replacement = $codec->encode($replacement); diff --git a/src/Operation/Update.php b/src/Operation/Update.php index a026ec7e4..0b47b1cc1 100644 --- a/src/Operation/Update.php +++ b/src/Operation/Update.php @@ -49,16 +49,6 @@ class Update implements Executable, Explainable { private const WIRE_VERSION_FOR_HINT = 8; - private string $databaseName; - - private string $collectionName; - - /** @var array|object */ - private $filter; - - /** @var array|object */ - private $update; - private array $options; /** @@ -109,16 +99,12 @@ class Update implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $update, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private array|object $filter, private array|object $update, array $options = []) { if (! is_document($filter)) { throw InvalidArgumentException::expectedDocumentType('$filter', $filter); } - if (! is_array($update) && ! is_object($update)) { - throw InvalidArgumentException::invalidType('$update', $filter, 'array or object'); - } - $options += [ 'multi' => false, 'upsert' => false, @@ -172,10 +158,6 @@ public function __construct(string $databaseName, string $collectionName, $filte unset($options['writeConcern']); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->filter = $filter; - $this->update = $update; $this->options = $options; } diff --git a/src/Operation/UpdateMany.php b/src/Operation/UpdateMany.php index d836a7c83..e61731622 100644 --- a/src/Operation/UpdateMany.php +++ b/src/Operation/UpdateMany.php @@ -23,8 +23,6 @@ use MongoDB\Exception\UnsupportedException; use MongoDB\UpdateResult; -use function is_array; -use function is_object; use function MongoDB\is_first_key_operator; use function MongoDB\is_pipeline; @@ -81,12 +79,8 @@ class UpdateMany implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $update, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array|object $update, array $options = []) { - if (! is_array($update) && ! is_object($update)) { - throw InvalidArgumentException::invalidType('$update', $update, 'array or object'); - } - if (! is_first_key_operator($update) && ! is_pipeline($update)) { throw new InvalidArgumentException('Expected update operator(s) or non-empty pipeline for $update'); } diff --git a/src/Operation/UpdateOne.php b/src/Operation/UpdateOne.php index ff0c53f7a..40d71addf 100644 --- a/src/Operation/UpdateOne.php +++ b/src/Operation/UpdateOne.php @@ -23,8 +23,6 @@ use MongoDB\Exception\UnsupportedException; use MongoDB\UpdateResult; -use function is_array; -use function is_object; use function MongoDB\is_first_key_operator; use function MongoDB\is_pipeline; @@ -81,12 +79,8 @@ class UpdateOne implements Executable, Explainable * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(string $databaseName, string $collectionName, $filter, $update, array $options = []) + public function __construct(string $databaseName, string $collectionName, array|object $filter, array|object $update, array $options = []) { - if (! is_array($update) && ! is_object($update)) { - throw InvalidArgumentException::invalidType('$update', $update, 'array or object'); - } - if (! is_first_key_operator($update) && ! is_pipeline($update)) { throw new InvalidArgumentException('Expected update operator(s) or non-empty pipeline for $update'); } diff --git a/src/Operation/UpdateSearchIndex.php b/src/Operation/UpdateSearchIndex.php index a44bc4103..31d86ca8e 100644 --- a/src/Operation/UpdateSearchIndex.php +++ b/src/Operation/UpdateSearchIndex.php @@ -33,11 +33,7 @@ */ class UpdateSearchIndex implements Executable { - private string $databaseName; - private string $collectionName; - private string $name; private object $definition; - private array $options = []; /** * Constructs a createSearchIndexes command. @@ -49,7 +45,7 @@ class UpdateSearchIndex implements Executable * @param array{comment?: mixed} $options Command options * @throws InvalidArgumentException for parameter parsing errors */ - public function __construct(string $databaseName, string $collectionName, string $name, $definition, array $options = []) + public function __construct(private string $databaseName, private string $collectionName, private string $name, array|object $definition, private array $options = []) { if ($name === '') { throw new InvalidArgumentException('Index name cannot be empty'); @@ -59,11 +55,7 @@ public function __construct(string $databaseName, string $collectionName, string throw InvalidArgumentException::expectedDocumentType('$definition', $definition); } - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->name = $name; $this->definition = (object) $definition; - $this->options = $options; } /** diff --git a/src/Operation/Watch.php b/src/Operation/Watch.php index 99e0f0380..1ae781d11 100644 --- a/src/Operation/Watch.php +++ b/src/Operation/Watch.php @@ -74,20 +74,14 @@ class Watch implements Executable, /* @internal */ CommandSubscriber private array $changeStreamOptions; - private ?string $collectionName = null; - private string $databaseName; private int $firstBatchSize = 0; private bool $hasResumed = false; - private Manager $manager; - private ?TimestampInterface $operationTime = null; - private array $pipeline; - private ?object $postBatchResumeToken = null; private ?DocumentCodec $codec; @@ -193,7 +187,7 @@ class Watch implements Executable, /* @internal */ CommandSubscriber * @param array $options Command options * @throws InvalidArgumentException for parameter/option parsing errors */ - public function __construct(Manager $manager, ?string $databaseName, ?string $collectionName, array $pipeline, array $options = []) + public function __construct(private Manager $manager, ?string $databaseName, private ?string $collectionName = null, private array $pipeline, array $options = []) { if (isset($collectionName) && ! isset($databaseName)) { throw new InvalidArgumentException('$collectionName should also be null if $databaseName is null'); @@ -247,7 +241,7 @@ public function __construct(Manager $manager, ?string $databaseName, ?string $co if (! isset($options['session'])) { try { $options['session'] = $manager->startSession(['causalConsistency' => false]); - } catch (RuntimeException $e) { + } catch (RuntimeException) { /* We can ignore the exception, as libmongoc likely cannot * create its own session and there is no risk of a mismatch. */ } @@ -262,10 +256,7 @@ public function __construct(Manager $manager, ?string $databaseName, ?string $co $this->changeStreamOptions['allChangesForCluster'] = true; } - $this->manager = $manager; $this->databaseName = $databaseName; - $this->collectionName = $collectionName; - $this->pipeline = $pipeline; $this->codec = $options['codec'] ?? null; $this->aggregate = $this->createAggregate(); @@ -403,15 +394,10 @@ private function getInitialResumeToken() * Resumes a change stream. * * @see https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst#resume-process - * @param array|object|null $resumeToken * @throws InvalidArgumentException */ - private function resume($resumeToken = null, bool $hasAdvanced = false): ChangeStreamIterator + private function resume(array|object|null $resumeToken = null, bool $hasAdvanced = false): ChangeStreamIterator { - if (isset($resumeToken) && ! is_array($resumeToken) && ! is_object($resumeToken)) { - throw InvalidArgumentException::invalidType('$resumeToken', $resumeToken, 'array or object'); - } - $this->hasResumed = true; /* Select a new server using the original read preference. While watch diff --git a/src/Operation/WithTransaction.php b/src/Operation/WithTransaction.php index de5644073..f0b5b0ec7 100644 --- a/src/Operation/WithTransaction.php +++ b/src/Operation/WithTransaction.php @@ -16,18 +16,15 @@ class WithTransaction /** @var callable */ private $callback; - private array $transactionOptions; - /** * @see Session::startTransaction for supported transaction options * * @param callable $callback A callback that will be invoked within the transaction * @param array $transactionOptions Additional options that are passed to Session::startTransaction */ - public function __construct(callable $callback, array $transactionOptions = []) + public function __construct(callable $callback, private array $transactionOptions = []) { $this->callback = $callback; - $this->transactionOptions = $transactionOptions; } /** diff --git a/src/UpdateResult.php b/src/UpdateResult.php index 76f042ae1..58a73a890 100644 --- a/src/UpdateResult.php +++ b/src/UpdateResult.php @@ -25,13 +25,10 @@ */ class UpdateResult { - private WriteResult $writeResult; - private bool $isAcknowledged; - public function __construct(WriteResult $writeResult) + public function __construct(private WriteResult $writeResult) { - $this->writeResult = $writeResult; $this->isAcknowledged = $writeResult->isAcknowledged(); } diff --git a/src/functions.php b/src/functions.php index b3b5167e7..bf3a736ec 100644 --- a/src/functions.php +++ b/src/functions.php @@ -107,7 +107,7 @@ function all_servers_support_write_stage_on_secondary(array $servers): bool * @return array|object * @throws InvalidArgumentException */ -function apply_type_map_to_document($document, array $typeMap) +function apply_type_map_to_document(array|object $document, array $typeMap) { if (! is_document($document)) { throw InvalidArgumentException::expectedDocumentType('$document', $document); @@ -127,10 +127,9 @@ function apply_type_map_to_document($document, array $typeMap) * encode as BSON arrays. * * @internal - * @param array|object $document * @throws InvalidArgumentException if $document is not an array or object */ -function document_to_array($document): array +function document_to_array(array|object $document): array { if ($document instanceof Document || $document instanceof PackedArray) { /* Nested documents and arrays are intentionally left as BSON. We avoid @@ -154,10 +153,6 @@ function document_to_array($document): array $document = get_object_vars($document); } - if (! is_array($document)) { - throw InvalidArgumentException::expectedDocumentType('$document', $document); - } - return $document; } @@ -215,9 +210,8 @@ function get_encrypted_fields_from_server(string $databaseName, string $collecti * BSON PackedArray instances * * @internal - * @param mixed $document */ -function is_document($document): bool +function is_document(mixed $document): bool { return is_array($document) || (is_object($document) && ! $document instanceof PackedArray); } @@ -231,10 +225,9 @@ function is_document($document): bool * $document has an unexpected type instead of returning false. * * @internal - * @param array|object $document * @throws InvalidArgumentException if $document is not an array or object */ -function is_first_key_operator($document): bool +function is_first_key_operator(array|object $document): bool { if ($document instanceof PackedArray) { return false; @@ -274,10 +267,9 @@ function is_first_key_operator($document): bool * returns a non-array, non-object value from its bsonSerialize() method. * * @internal - * @param array|object $pipeline * @throws InvalidArgumentException */ -function is_pipeline($pipeline, bool $allowEmpty = false): bool +function is_pipeline(array|object $pipeline, bool $allowEmpty = false): bool { if ($pipeline instanceof PackedArray) { /* Nested documents and arrays are intentionally left as BSON. We avoid @@ -368,7 +360,7 @@ function is_last_pipeline_operator_write(array $pipeline): bool * @see https://mongodb.com/docs/manual/reference/command/mapReduce/#output-inline * @param string|array|object $out Output specification */ -function is_mapreduce_output_inline($out): bool +function is_mapreduce_output_inline(string|array|object $out): bool { if (! is_array($out) && ! is_object($out)) { return false; @@ -414,9 +406,8 @@ function server_supports_feature(Server $server, int $feature): bool * Return whether the input is an array of strings. * * @internal - * @param mixed $input */ -function is_string_array($input): bool +function is_string_array(mixed $input): bool { if (! is_array($input)) { return false; @@ -442,7 +433,7 @@ function is_string_array($input): bool * @return mixed * @throws ReflectionException */ -function recursive_copy($element) +function recursive_copy(mixed $element) { if (is_array($element)) { foreach ($element as $key => $value) { diff --git a/tests/Database/DatabaseFunctionalTest.php b/tests/Database/DatabaseFunctionalTest.php index c5854e882..c5f337bfc 100644 --- a/tests/Database/DatabaseFunctionalTest.php +++ b/tests/Database/DatabaseFunctionalTest.php @@ -2,6 +2,7 @@ namespace MongoDB\Tests\Database; +use MongoDB\BSON\PackedArray; use MongoDB\Collection; use MongoDB\Database; use MongoDB\Driver\BulkWrite; @@ -124,7 +125,7 @@ public function testCommandAppliesTypeMapToCursor(): void /** @dataProvider provideInvalidDocumentValues */ public function testCommandCommandArgumentTypeCheck($command): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($command instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); $this->database->command($command); } diff --git a/tests/DocumentationExamplesTest.php b/tests/DocumentationExamplesTest.php index 8d4062c57..e325b4914 100644 --- a/tests/DocumentationExamplesTest.php +++ b/tests/DocumentationExamplesTest.php @@ -1501,7 +1501,7 @@ private function doUpdateEmployeeInfo(\MongoDB\Client $client): void try { $this->runTransactionWithRetry3([$this, 'updateEmployeeInfo3'], $client, $session); - } catch (\MongoDB\Driver\Exception\Exception $error) { + } catch (\MongoDB\Driver\Exception\Exception) { // Do something with error } } @@ -1547,7 +1547,7 @@ public function testCausalConsistency(): void * around this, we run a query on a secondary and rely on an * exception to let us know that no secondary is available. */ $items->countDocuments([], ['readPreference' => new ReadPreference(ReadPreference::SECONDARY)]); - } catch (Exception $e) { + } catch (Exception) { $this->markTestSkipped('Secondary is not available'); } diff --git a/tests/ExamplesTest.php b/tests/ExamplesTest.php index aa3e8580e..7946622f4 100644 --- a/tests/ExamplesTest.php +++ b/tests/ExamplesTest.php @@ -144,7 +144,6 @@ public static function provideExamples(): Generator [oid] => %s ) - [name] => alcaeus [emails] => Array ( [0] => MongoDB\Examples\Persistable\PersistableEmail Object @@ -161,6 +160,7 @@ public static function provideExamples(): Generator ) + [name] => alcaeus ) OUTPUT; diff --git a/tests/FunctionalTestCase.php b/tests/FunctionalTestCase.php index 53d1c3558..cdff7ca48 100644 --- a/tests/FunctionalTestCase.php +++ b/tests/FunctionalTestCase.php @@ -213,7 +213,7 @@ protected function assertSameObjectId($expectedObjectId, $actualObjectId): void * @param array|stdClass $command configureFailPoint command document * @throws InvalidArgumentException if $command is not a configureFailPoint command */ - public function configureFailPoint($command, ?Server $server = null): void + public function configureFailPoint(array|stdClass $command, ?Server $server = null): void { if (! $this->isFailCommandSupported()) { $this->markTestSkipped('failCommand is only supported on mongod >= 4.0.0 and mongos >= 4.1.5.'); @@ -393,7 +393,7 @@ protected function isApiVersionRequired(): bool ); $document = current($cursor->toArray()); - } catch (CommandException $e) { + } catch (CommandException) { return false; } @@ -710,7 +710,7 @@ private function isFailCommandEnabled(): bool ); $document = current($cursor->toArray()); - } catch (CommandException $e) { + } catch (CommandException) { return false; } diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php index 428028d0c..7098cb24a 100644 --- a/tests/FunctionsTest.php +++ b/tests/FunctionsTest.php @@ -5,9 +5,9 @@ use MongoDB\BSON\Document; use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; -use MongoDB\Exception\InvalidArgumentException; use MongoDB\Model\BSONArray; use MongoDB\Model\BSONDocument; +use TypeError; use function MongoDB\apply_type_map_to_document; use function MongoDB\create_field_path_type_map; @@ -115,8 +115,7 @@ public function provideDocumentsAndExpectedArrays(): array /** @dataProvider provideInvalidDocumentValuesForChecks */ public function testDocumentToArrayArgumentTypeCheck($document): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Expected $document to have type "document" (array or object)'); + $this->expectException(TypeError::class); document_to_array($document); } @@ -154,7 +153,7 @@ public function testIsFirstKeyOperator(callable $cast): void /** @dataProvider provideInvalidDocumentValuesForChecks */ public function testIsFirstKeyOperatorArgumentTypeCheck($document): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException(TypeError::class); is_first_key_operator($document); } diff --git a/tests/GridFS/BucketFunctionalTest.php b/tests/GridFS/BucketFunctionalTest.php index 46c0c9294..795764900 100644 --- a/tests/GridFS/BucketFunctionalTest.php +++ b/tests/GridFS/BucketFunctionalTest.php @@ -152,7 +152,7 @@ public function testDeleteStillRemovesChunksIfFileDoesNotExist($input, $expected try { $this->bucket->delete($id); $this->fail('FileNotFoundException was not thrown'); - } catch (FileNotFoundException $e) { + } catch (FileNotFoundException) { } $this->assertCollectionCount($this->chunksCollection, 0); diff --git a/tests/Model/CallbackIteratorTest.php b/tests/Model/CallbackIteratorTest.php index 6705e79f5..9f71415f7 100644 --- a/tests/Model/CallbackIteratorTest.php +++ b/tests/Model/CallbackIteratorTest.php @@ -28,11 +28,8 @@ public static function provideTests(): Generator $iteratorAggregate = new class ($listIterator) implements IteratorAggregate { - private Iterator $iterator; - - public function __construct(Iterator $iterator) + public function __construct(private Iterator $iterator) { - $this->iterator = $iterator; } public function getIterator(): Iterator diff --git a/tests/Model/ChangeStreamIteratorTest.php b/tests/Model/ChangeStreamIteratorTest.php index bdc062be6..890870445 100644 --- a/tests/Model/ChangeStreamIteratorTest.php +++ b/tests/Model/ChangeStreamIteratorTest.php @@ -7,6 +7,7 @@ namespace MongoDB\Tests\Model; +use MongoDB\BSON\PackedArray; use MongoDB\Collection; use MongoDB\Driver\Exception\LogicException; use MongoDB\Exception\InvalidArgumentException; @@ -52,7 +53,7 @@ public function testInitialResumeToken(): void /** @dataProvider provideInvalidDocumentValues */ public function testInitialResumeTokenArgumentTypeCheck($initialResumeToken): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($initialResumeToken instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new ChangeStreamIterator($this->collection->find(), 0, $initialResumeToken, null); } diff --git a/tests/Model/IndexInputTest.php b/tests/Model/IndexInputTest.php index 3f5e814e5..bc0539b51 100644 --- a/tests/Model/IndexInputTest.php +++ b/tests/Model/IndexInputTest.php @@ -48,11 +48,8 @@ public function testConstructorShouldRequireNameToBeString($name): void new IndexInput(['key' => ['x' => 1], 'name' => $name]); } - /** - * @dataProvider provideExpectedNameAndKey - * @param array|object $key - */ - public function testNameGeneration($expectedName, $key): void + /** @dataProvider provideExpectedNameAndKey */ + public function testNameGeneration($expectedName, array|object $key): void { $this->assertSame($expectedName, (string) new IndexInput(['key' => $key])); } diff --git a/tests/Operation/BulkWriteTest.php b/tests/Operation/BulkWriteTest.php index 2c255bec5..e0783ad38 100644 --- a/tests/Operation/BulkWriteTest.php +++ b/tests/Operation/BulkWriteTest.php @@ -2,10 +2,12 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedValueException; use MongoDB\Operation\BulkWrite; use MongoDB\Tests\Fixtures\Codec\TestDocumentCodec; +use TypeError; class BulkWriteTest extends TestCase { @@ -287,8 +289,7 @@ public function testUpdateManyUpdateArgumentMissing(): void /** @dataProvider provideInvalidDocumentValues */ public function testUpdateManyUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Expected update operator(s) or non-empty pipeline for $operations[0]["updateMany"][1]'); + $this->expectException($update instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [ [BulkWrite::UPDATE_MANY => [['x' => 1], $update]], ]); @@ -380,8 +381,7 @@ public function testUpdateOneUpdateArgumentMissing(): void /** @dataProvider provideInvalidDocumentValues */ public function testUpdateOneUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Expected update operator(s) or non-empty pipeline for $operations[0]["updateOne"][1]'); + $this->expectException($update instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new BulkWrite($this->getDatabaseName(), $this->getCollectionName(), [ [BulkWrite::UPDATE_ONE => [['x' => 1], $update]], ]); diff --git a/tests/Operation/CountDocumentsTest.php b/tests/Operation/CountDocumentsTest.php index a7a048be1..0a16e4399 100644 --- a/tests/Operation/CountDocumentsTest.php +++ b/tests/Operation/CountDocumentsTest.php @@ -2,15 +2,17 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\CountDocuments; +use TypeError; class CountDocumentsTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new CountDocuments($this->getDatabaseName(), $this->getCollectionName(), $filter); } diff --git a/tests/Operation/CountTest.php b/tests/Operation/CountTest.php index 7a26341f6..a096859ae 100644 --- a/tests/Operation/CountTest.php +++ b/tests/Operation/CountTest.php @@ -2,16 +2,18 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\ReadConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\Count; +use TypeError; class CountTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new Count($this->getDatabaseName(), $this->getCollectionName(), $filter); } diff --git a/tests/Operation/DatabaseCommandTest.php b/tests/Operation/DatabaseCommandTest.php index c592aa5e4..74b3d8343 100644 --- a/tests/Operation/DatabaseCommandTest.php +++ b/tests/Operation/DatabaseCommandTest.php @@ -2,15 +2,17 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\DatabaseCommand; +use TypeError; class DatabaseCommandTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorCommandArgumentTypeCheck($command): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($command instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new DatabaseCommand($this->getDatabaseName(), $command); } diff --git a/tests/Operation/DeleteTest.php b/tests/Operation/DeleteTest.php index 143e7bb16..25d3b5ccf 100644 --- a/tests/Operation/DeleteTest.php +++ b/tests/Operation/DeleteTest.php @@ -7,6 +7,7 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\Delete; @@ -17,7 +18,7 @@ class DeleteTest extends TestCase /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new Delete($this->getDatabaseName(), $this->getCollectionName(), $filter, 0); } diff --git a/tests/Operation/DistinctTest.php b/tests/Operation/DistinctTest.php index f04d244ca..77380f249 100644 --- a/tests/Operation/DistinctTest.php +++ b/tests/Operation/DistinctTest.php @@ -2,17 +2,19 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\ReadConcern; use MongoDB\Driver\ReadPreference; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\Distinct; +use TypeError; class DistinctTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new Distinct($this->getDatabaseName(), $this->getCollectionName(), 'x', $filter); } diff --git a/tests/Operation/FindOneAndDeleteTest.php b/tests/Operation/FindOneAndDeleteTest.php index 042c3a279..c4cbda6a8 100644 --- a/tests/Operation/FindOneAndDeleteTest.php +++ b/tests/Operation/FindOneAndDeleteTest.php @@ -2,16 +2,18 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\FindOneAndDelete; +use TypeError; class FindOneAndDeleteTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new FindOneAndDelete($this->getDatabaseName(), $this->getCollectionName(), $filter); } diff --git a/tests/Operation/FindOneAndReplaceTest.php b/tests/Operation/FindOneAndReplaceTest.php index 94075b89d..33681f7d4 100644 --- a/tests/Operation/FindOneAndReplaceTest.php +++ b/tests/Operation/FindOneAndReplaceTest.php @@ -2,23 +2,25 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\FindOneAndReplace; +use TypeError; class FindOneAndReplaceTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new FindOneAndReplace($this->getDatabaseName(), $this->getCollectionName(), $filter, []); } /** @dataProvider provideInvalidDocumentValues */ public function testConstructorReplacementArgumentTypeCheck($replacement): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($replacement instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new FindOneAndReplace($this->getDatabaseName(), $this->getCollectionName(), [], $replacement); } diff --git a/tests/Operation/FindOneAndUpdateTest.php b/tests/Operation/FindOneAndUpdateTest.php index 99d49128a..f0917a856 100644 --- a/tests/Operation/FindOneAndUpdateTest.php +++ b/tests/Operation/FindOneAndUpdateTest.php @@ -2,23 +2,25 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\FindOneAndUpdate; +use TypeError; class FindOneAndUpdateTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new FindOneAndUpdate($this->getDatabaseName(), $this->getCollectionName(), $filter, []); } /** @dataProvider provideInvalidDocumentValues */ public function testConstructorUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($update instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new FindOneAndUpdate($this->getDatabaseName(), $this->getCollectionName(), [], $update); } diff --git a/tests/Operation/FindTest.php b/tests/Operation/FindTest.php index 68341d2ac..806b883ce 100644 --- a/tests/Operation/FindTest.php +++ b/tests/Operation/FindTest.php @@ -2,17 +2,19 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\ReadConcern; use MongoDB\Driver\ReadPreference; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\Find; +use TypeError; class FindTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new Find($this->getDatabaseName(), $this->getCollectionName(), $filter); } diff --git a/tests/Operation/InsertOneTest.php b/tests/Operation/InsertOneTest.php index ad7212c7c..ad325cd0b 100644 --- a/tests/Operation/InsertOneTest.php +++ b/tests/Operation/InsertOneTest.php @@ -2,17 +2,19 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedValueException; use MongoDB\Operation\InsertOne; use MongoDB\Tests\Fixtures\Codec\TestDocumentCodec; +use TypeError; class InsertOneTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorDocumentArgumentTypeCheck($document): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($document instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new InsertOne($this->getDatabaseName(), $this->getCollectionName(), $document); } diff --git a/tests/Operation/MapReduceTest.php b/tests/Operation/MapReduceTest.php index 04b7a58d0..92e6881c1 100644 --- a/tests/Operation/MapReduceTest.php +++ b/tests/Operation/MapReduceTest.php @@ -1,5 +1,7 @@ expectException(InvalidArgumentException::class); + $this->expectException(TypeError::class); new MapReduce($this->getDatabaseName(), $this->getCollectionName(), $map, $reduce, $out); } diff --git a/tests/Operation/ReplaceOneTest.php b/tests/Operation/ReplaceOneTest.php index 404cdae78..73f659b85 100644 --- a/tests/Operation/ReplaceOneTest.php +++ b/tests/Operation/ReplaceOneTest.php @@ -2,24 +2,26 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Exception\UnsupportedValueException; use MongoDB\Operation\ReplaceOne; use MongoDB\Tests\Fixtures\Codec\TestDocumentCodec; +use TypeError; class ReplaceOneTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new ReplaceOne($this->getDatabaseName(), $this->getCollectionName(), $filter, ['y' => 1]); } /** @dataProvider provideInvalidDocumentValues */ public function testConstructorReplacementArgumentTypeCheck($replacement): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($replacement instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new ReplaceOne($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], $replacement); } diff --git a/tests/Operation/UpdateManyTest.php b/tests/Operation/UpdateManyTest.php index 7f12207c8..99acecf33 100644 --- a/tests/Operation/UpdateManyTest.php +++ b/tests/Operation/UpdateManyTest.php @@ -2,22 +2,24 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\UpdateMany; +use TypeError; class UpdateManyTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new UpdateMany($this->getDatabaseName(), $this->getCollectionName(), $filter, ['$set' => ['x' => 1]]); } /** @dataProvider provideInvalidDocumentValues */ public function testConstructorUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($update instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new UpdateMany($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], $update); } diff --git a/tests/Operation/UpdateOneTest.php b/tests/Operation/UpdateOneTest.php index 657f3d650..e0c4086a0 100644 --- a/tests/Operation/UpdateOneTest.php +++ b/tests/Operation/UpdateOneTest.php @@ -2,22 +2,24 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\UpdateOne; +use TypeError; class UpdateOneTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new UpdateOne($this->getDatabaseName(), $this->getCollectionName(), $filter, ['$set' => ['x' => 1]]); } /** @dataProvider provideInvalidDocumentValues */ public function testConstructorUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); + $this->expectException($update instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new UpdateOne($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], $update); } diff --git a/tests/Operation/UpdateSearchIndexTest.php b/tests/Operation/UpdateSearchIndexTest.php index 90c623fc3..befe07eb1 100644 --- a/tests/Operation/UpdateSearchIndexTest.php +++ b/tests/Operation/UpdateSearchIndexTest.php @@ -2,8 +2,10 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\UpdateSearchIndex; +use TypeError; class UpdateSearchIndexTest extends TestCase { @@ -16,8 +18,7 @@ public function testConstructorIndexNameMustNotBeEmpty(): void /** @dataProvider provideInvalidDocumentValues */ public function testConstructorIndexDefinitionMustBeADocument($definition): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessage('Expected $definition to have type "document"'); + $this->expectException($definition instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new UpdateSearchIndex($this->getDatabaseName(), $this->getCollectionName(), 'index name', $definition); } } diff --git a/tests/Operation/UpdateTest.php b/tests/Operation/UpdateTest.php index 85d00ef88..bf8d993ca 100644 --- a/tests/Operation/UpdateTest.php +++ b/tests/Operation/UpdateTest.php @@ -2,25 +2,25 @@ namespace MongoDB\Tests\Operation; +use MongoDB\BSON\PackedArray; use MongoDB\Driver\WriteConcern; use MongoDB\Exception\InvalidArgumentException; use MongoDB\Operation\Update; +use TypeError; class UpdateTest extends TestCase { /** @dataProvider provideInvalidDocumentValues */ public function testConstructorFilterArgumentTypeCheck($filter): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/Expected \$filter to have type "document" \(array or object\) but found ".+"/'); + $this->expectException($filter instanceof PackedArray ? InvalidArgumentException::class : TypeError::class); new Update($this->getDatabaseName(), $this->getCollectionName(), $filter, ['$set' => ['x' => 1]]); } /** @dataProvider provideInvalidUpdateValues */ public function testConstructorUpdateArgumentTypeCheck($update): void { - $this->expectException(InvalidArgumentException::class); - $this->expectExceptionMessageMatches('/Expected \$update to have type "array or object" but found "[\w ]+"/'); + $this->expectException(TypeError::class); new Update($this->getDatabaseName(), $this->getCollectionName(), ['x' => 1], $update); } diff --git a/tests/Operation/WatchFunctionalTest.php b/tests/Operation/WatchFunctionalTest.php index 58b8c844c..a7e0ae534 100644 --- a/tests/Operation/WatchFunctionalTest.php +++ b/tests/Operation/WatchFunctionalTest.php @@ -1135,9 +1135,9 @@ public function testResumeTokenNotFoundDoesNotAdvanceKey(): void try { $this->advanceCursorUntilValid($changeStream); $this->fail('Exception for missing resume token was not thrown'); - } catch (ResumeTokenException $e) { + } catch (ResumeTokenException) { /* On server versions < 4.1.8, a client-side error is thrown. */ - } catch (ServerException $e) { + } catch (ServerException) { /* On server versions >= 4.1.8, the error is thrown server-side. */ } @@ -1147,7 +1147,7 @@ public function testResumeTokenNotFoundDoesNotAdvanceKey(): void try { $changeStream->next(); $this->fail('Exception for missing resume token was not thrown'); - } catch (ResumeTokenException | ServerException $e) { + } catch (ResumeTokenException | ServerException) { } $this->assertFalse($changeStream->valid()); @@ -1365,7 +1365,7 @@ public function testOriginalReadPreferenceIsPreservedOnResume(): void try { $secondary = $this->manager->selectServer($readPreference); - } catch (ConnectionTimeoutException $e) { + } catch (ConnectionTimeoutException) { $this->markTestSkipped('Secondary is not available'); } diff --git a/tests/PHPUnit/Functions.php b/tests/PHPUnit/Functions.php index 64a4eee19..6f445f410 100644 --- a/tests/PHPUnit/Functions.php +++ b/tests/PHPUnit/Functions.php @@ -83,14 +83,11 @@ * * @see Assert::assertArrayHasKey * - * @param int|string $key - * @param array|ArrayAccess $array - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertArrayHasKey($key, $array, string $message = ''): void + function assertArrayHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { Assert::assertArrayHasKey(...func_get_args()); } @@ -102,14 +99,11 @@ function assertArrayHasKey($key, $array, string $message = ''): void * * @see Assert::assertArrayNotHasKey * - * @param int|string $key - * @param array|ArrayAccess $array - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertArrayNotHasKey($key, $array, string $message = ''): void + function assertArrayNotHasKey(int|string $key, array|ArrayAccess $array, string $message = ''): void { Assert::assertArrayNotHasKey(...func_get_args()); } @@ -212,13 +206,11 @@ function assertNotContainsOnly(string $type, $haystack, ?bool $isNativeType = nu * * @see Assert::assertCount * - * @param Countable|iterable $haystack - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertCount(int $expectedCount, $haystack, string $message = ''): void + function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { Assert::assertCount(...func_get_args()); } @@ -230,13 +222,11 @@ function assertCount(int $expectedCount, $haystack, string $message = ''): void * * @see Assert::assertNotCount * - * @param Countable|iterable $haystack - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertNotCount(int $expectedCount, $haystack, string $message = ''): void + function assertNotCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void { Assert::assertNotCount(...func_get_args()); } @@ -1834,14 +1824,11 @@ function assertNotRegExp(string $pattern, string $string, string $message = ''): * * @see Assert::assertSameSize * - * @param Countable|iterable $expected - * @param Countable|iterable $actual - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertSameSize($expected, $actual, string $message = ''): void + function assertSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { Assert::assertSameSize(...func_get_args()); } @@ -1854,14 +1841,11 @@ function assertSameSize($expected, $actual, string $message = ''): void * * @see Assert::assertNotSameSize * - * @param Countable|iterable $expected - * @param Countable|iterable $actual - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws Exception */ - function assertNotSameSize($expected, $actual, string $message = ''): void + function assertNotSameSize(Countable|iterable $expected, Countable|iterable $actual, string $message = ''): void { Assert::assertNotSameSize(...func_get_args()); } @@ -2077,13 +2061,11 @@ function assertXmlFileNotEqualsXmlFile(string $expectedFile, string $actualFile, * * @see Assert::assertXmlStringEqualsXmlFile * - * @param DOMDocument|string $actualXml - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws XmlException */ - function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + function assertXmlStringEqualsXmlFile(string $expectedFile, DOMDocument|string $actualXml, string $message = ''): void { Assert::assertXmlStringEqualsXmlFile(...func_get_args()); } @@ -2095,13 +2077,11 @@ function assertXmlStringEqualsXmlFile(string $expectedFile, $actualXml, string $ * * @see Assert::assertXmlStringNotEqualsXmlFile * - * @param DOMDocument|string $actualXml - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws XmlException */ - function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, string $message = ''): void + function assertXmlStringNotEqualsXmlFile(string $expectedFile, DOMDocument|string $actualXml, string $message = ''): void { Assert::assertXmlStringNotEqualsXmlFile(...func_get_args()); } @@ -2113,14 +2093,11 @@ function assertXmlStringNotEqualsXmlFile(string $expectedFile, $actualXml, strin * * @see Assert::assertXmlStringEqualsXmlString * - * @param DOMDocument|string $expectedXml - * @param DOMDocument|string $actualXml - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws XmlException */ - function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + function assertXmlStringEqualsXmlString(DOMDocument|string $expectedXml, DOMDocument|string $actualXml, string $message = ''): void { Assert::assertXmlStringEqualsXmlString(...func_get_args()); } @@ -2132,14 +2109,11 @@ function assertXmlStringEqualsXmlString($expectedXml, $actualXml, string $messag * * @see Assert::assertXmlStringNotEqualsXmlString * - * @param DOMDocument|string $expectedXml - * @param DOMDocument|string $actualXml - * * @throws ExpectationFailedException * @throws InvalidArgumentException * @throws XmlException */ - function assertXmlStringNotEqualsXmlString($expectedXml, $actualXml, string $message = ''): void + function assertXmlStringNotEqualsXmlString(DOMDocument|string $expectedXml, DOMDocument|string $actualXml, string $message = ''): void { Assert::assertXmlStringNotEqualsXmlString(...func_get_args()); } diff --git a/tests/SpecTests/ClientSideEncryptionSpecTest.php b/tests/SpecTests/ClientSideEncryptionSpecTest.php index 5f00cb553..574cf4f23 100644 --- a/tests/SpecTests/ClientSideEncryptionSpecTest.php +++ b/tests/SpecTests/ClientSideEncryptionSpecTest.php @@ -1698,7 +1698,7 @@ static function (self $test, Client $setupClient, ClientEncryption $clientEncryp try { $encryptedClient->selectCollection('db', 'decryption_events')->aggregate([]); $test->fail('Expected exception to be thrown'); - } catch (ConnectionTimeoutException $e) { + } catch (ConnectionTimeoutException) { $test->addToAssertionCount(1); } @@ -1942,7 +1942,7 @@ private function encryptCorpusValue(string $fieldName, stdClass $data, ClientEnc try { $clientEncryption->encrypt($data->value, $encryptionOptions); $this->fail('Expected exception to be thrown'); - } catch (RuntimeException $e) { + } catch (RuntimeException) { } return $data->value; diff --git a/tests/SpecTests/CommandExpectations.php b/tests/SpecTests/CommandExpectations.php index 76a3a0a0a..7c9a946f0 100644 --- a/tests/SpecTests/CommandExpectations.php +++ b/tests/SpecTests/CommandExpectations.php @@ -37,12 +37,8 @@ class CommandExpectations implements CommandSubscriber /** @var list */ private array $ignoredCommandNames = []; - private Client $observedClient; - - private function __construct(Client $observedClient, array $events) + private function __construct(private Client $observedClient, array $events) { - $this->observedClient = $observedClient; - foreach ($events as $event) { switch (key((array) $event)) { case 'command_failed_event': diff --git a/tests/SpecTests/Context.php b/tests/SpecTests/Context.php index 7731f65db..1341e65da 100644 --- a/tests/SpecTests/Context.php +++ b/tests/SpecTests/Context.php @@ -30,10 +30,6 @@ final class Context private ?Client $client = null; - public ?string $collectionName = null; - - public string $databaseName; - public array $defaultWriteOptions = []; public array $outcomeReadOptions = []; @@ -54,10 +50,8 @@ final class Context private ?Client $encryptedClient = null; - private function __construct(string $databaseName, ?string $collectionName) + private function __construct(public string $databaseName, public ?string $collectionName = null) { - $this->databaseName = $databaseName; - $this->collectionName = $collectionName; $this->outcomeCollectionName = $collectionName; $this->internalClient = FunctionalTestCase::createTestClient(); } diff --git a/tests/SpecTests/DocumentsMatchConstraint.php b/tests/SpecTests/DocumentsMatchConstraint.php index 1b3680d3f..16e7914a6 100644 --- a/tests/SpecTests/DocumentsMatchConstraint.php +++ b/tests/SpecTests/DocumentsMatchConstraint.php @@ -16,7 +16,6 @@ use Symfony\Bridge\PhpUnit\ConstraintTrait; use function array_values; -use function get_class; use function get_debug_type; use function is_array; use function is_float; @@ -39,10 +38,6 @@ class DocumentsMatchConstraint extends Constraint { use ConstraintTrait; - private bool $ignoreExtraKeysInRoot = false; - - private bool $ignoreExtraKeysInEmbedded = false; - /** * TODO: This is not currently used, but was preserved from the design of * TestCase::assertMatchesDocument(), which would sort keys and then compare @@ -52,8 +47,7 @@ class DocumentsMatchConstraint extends Constraint */ private bool $sortKeys = false; - /** @var BSONArray|BSONDocument */ - private $value; + private BSONArray|BSONDocument $value; private ?ComparisonFailure $lastFailure = null; @@ -62,15 +56,12 @@ class DocumentsMatchConstraint extends Constraint /** * Creates a new constraint. * - * @param array|object $value - * @param boolean $ignoreExtraKeysInRoot If true, ignore extra keys within the root document - * @param boolean $ignoreExtraKeysInEmbedded If true, ignore extra keys within embedded documents + * @param boolean $ignoreExtraKeysInRoot If true, ignore extra keys within the root document + * @param boolean $ignoreExtraKeysInEmbedded If true, ignore extra keys within embedded documents */ - public function __construct($value, bool $ignoreExtraKeysInRoot = false, bool $ignoreExtraKeysInEmbedded = false) + public function __construct(array|object $value, private bool $ignoreExtraKeysInRoot = false, private bool $ignoreExtraKeysInEmbedded = false) { $this->value = $this->prepareBSON($value, true, $this->sortKeys); - $this->ignoreExtraKeysInRoot = $ignoreExtraKeysInRoot; - $this->ignoreExtraKeysInEmbedded = $ignoreExtraKeysInEmbedded; $this->comparatorFactory = Factory::getInstance(); } @@ -111,11 +102,8 @@ private function doEvaluate($other, $description = '', $returnResult = false) } } - /** - * @param string|string[] $expectedType - * @param mixed $actualValue - */ - private function assertBSONType($expectedType, $actualValue): void + /** @param string|BSONArray[] $expectedType */ + private function assertBSONType(string|BSONArray $expectedType, mixed $actualValue): void { assertThat( $expectedType, @@ -133,11 +121,11 @@ private function assertBSONType($expectedType, $actualValue): void */ private function assertEquals(ArrayObject $expected, ArrayObject $actual, bool $ignoreExtraKeys, string $keyPrefix = ''): void { - if (get_class($expected) !== get_class($actual)) { + if ($expected::class !== $actual::class) { throw new RuntimeException(sprintf( '%s is not instance of expected class "%s"', $this->exporter()->shortenedExport($actual), - get_class($expected), + $expected::class, )); } @@ -237,7 +225,7 @@ private function doMatches($other) try { $this->assertEquals($this->value, $other, $this->ignoreExtraKeysInRoot); - } catch (RuntimeException $e) { + } catch (RuntimeException) { return false; } @@ -261,12 +249,10 @@ private static function isNumeric($value): bool * its type and keys. Keys within documents will optionally be sorted. Each * value within the array or document will then be prepared recursively. * - * @param array|object $bson - * @param boolean $isRoot If true, ensure an array value is converted to a document - * @return BSONDocument|BSONArray + * @param boolean $isRoot If true, ensure an array value is converted to a document * @throws InvalidArgumentException if $bson is not an array or object */ - private function prepareBSON($bson, bool $isRoot, bool $sortKeys = false) + private function prepareBSON(array|object $bson, bool $isRoot, bool $sortKeys = false): BSONDocument|BSONArray { if (! is_array($bson) && ! is_object($bson)) { throw new InvalidArgumentException('$bson is not an array or object'); diff --git a/tests/SpecTests/ErrorExpectation.php b/tests/SpecTests/ErrorExpectation.php index df13dcf2a..82511b4d6 100644 --- a/tests/SpecTests/ErrorExpectation.php +++ b/tests/SpecTests/ErrorExpectation.php @@ -12,7 +12,6 @@ use stdClass; use Throwable; -use function get_class; use function is_array; use function is_string; use function sprintf; @@ -105,7 +104,7 @@ public function assert(TestCase $test, ?Throwable $actual = null): void { if (! $this->isExpected) { if ($actual !== null) { - $test->fail(sprintf("Operation threw unexpected %s: %s\n%s", get_class($actual), $actual->getMessage(), $actual->getTraceAsString())); + $test->fail(sprintf("Operation threw unexpected %s: %s\n%s", $actual::class, $actual->getMessage(), $actual->getTraceAsString())); } $test->addToAssertionCount(1); diff --git a/tests/SpecTests/FunctionalTestCase.php b/tests/SpecTests/FunctionalTestCase.php index 16fc999db..cd02f5908 100644 --- a/tests/SpecTests/FunctionalTestCase.php +++ b/tests/SpecTests/FunctionalTestCase.php @@ -84,11 +84,8 @@ public static function assertCommandReplyMatches(stdClass $expected, stdClass $a * Asserts that two given documents match. * * Extra keys in the actual value's document(s) will be ignored. - * - * @param array|object $expectedDocument - * @param array|object $actualDocument */ - public static function assertDocumentsMatch($expectedDocument, $actualDocument, string $message = ''): void + public static function assertDocumentsMatch(array|object $expectedDocument, array|object $actualDocument, string $message = ''): void { $constraint = new DocumentsMatchConstraint($expectedDocument, true, true); @@ -173,10 +170,8 @@ protected function checkServerRequirements(array $runOn): void * * This decodes the file through the driver's extended JSON parser to ensure * proper handling of special types. - * - * @return array|object */ - protected function decodeJson(string $json) + protected function decodeJson(string $json): array|object { return Document::fromJSON($json)->toPHP(); } diff --git a/tests/SpecTests/Operation.php b/tests/SpecTests/Operation.php index f7d437542..3672314cf 100644 --- a/tests/SpecTests/Operation.php +++ b/tests/SpecTests/Operation.php @@ -213,10 +213,9 @@ public function assert(FunctionalTestCase $test, Context $context, bool $bubbleE /** * Executes the operation with a given context. * - * @return mixed * @throws LogicException if the operation is unsupported */ - private function execute(FunctionalTestCase $test, Context $context) + private function execute(FunctionalTestCase $test, Context $context): mixed { switch ($this->object) { case self::OBJECT_CLIENT: @@ -266,10 +265,9 @@ private function execute(FunctionalTestCase $test, Context $context) /** * Executes the client operation and return its result. * - * @return mixed * @throws LogicException if the collection operation is unsupported */ - private function executeForClient(Client $client, Context $context) + private function executeForClient(Client $client, Context $context): mixed { $args = $context->prepareOptions($this->arguments); $context->replaceArgumentSessionPlaceholder($args); @@ -295,10 +293,9 @@ private function executeForClient(Client $client, Context $context) /** * Executes the collection operation and return its result. * - * @return mixed * @throws LogicException if the collection operation is unsupported */ - private function executeForCollection(Collection $collection, Context $context) + private function executeForCollection(Collection $collection, Context $context): mixed { $args = $context->prepareOptions($this->arguments); $context->replaceArgumentSessionPlaceholder($args); @@ -435,10 +432,9 @@ private function executeForCollection(Collection $collection, Context $context) /** * Executes the database operation and return its result. * - * @return mixed * @throws LogicException if the database operation is unsupported */ - private function executeForDatabase(Database $database, Context $context) + private function executeForDatabase(Database $database, Context $context): mixed { $args = $context->prepareOptions($this->arguments); $context->replaceArgumentSessionPlaceholder($args); @@ -488,10 +484,9 @@ private function executeForDatabase(Database $database, Context $context) /** * Executes the GridFS bucket operation and return its result. * - * @return mixed * @throws LogicException if the database operation is unsupported */ - private function executeForGridFSBucket(Bucket $bucket, Context $context) + private function executeForGridFSBucket(Bucket $bucket, Context $context): mixed { $args = $context->prepareOptions($this->arguments); $context->replaceArgumentSessionPlaceholder($args); @@ -529,10 +524,9 @@ private function executeForGridFSBucket(Bucket $bucket, Context $context) /** * Executes the session operation and return its result. * - * @return mixed * @throws LogicException if the session operation is unsupported */ - private function executeForSession(Session $session, FunctionalTestCase $test, Context $context) + private function executeForSession(Session $session, FunctionalTestCase $test, Context $context): mixed { switch ($this->name) { case 'abortTransaction': diff --git a/tests/SpecTests/PrimaryStepDownSpecTest.php b/tests/SpecTests/PrimaryStepDownSpecTest.php index 7fd0be6e1..2de6d4c44 100644 --- a/tests/SpecTests/PrimaryStepDownSpecTest.php +++ b/tests/SpecTests/PrimaryStepDownSpecTest.php @@ -215,7 +215,7 @@ public function testGetMoreIteration(): void $attempts++; $primary->executeCommand('admin', new Command(['replSetStepDown' => 5, 'force' => true])); $success = true; - } catch (DriverException $e) { + } catch (DriverException) { if ($attempts == 10) { $this->fail(sprintf('Could not successfully execute replSetStepDown within %d attempts', $attempts)); } @@ -289,7 +289,7 @@ private function waitForPrimaryReelection(): void $this->insertDocuments(1); return; - } catch (DriverException $e) { + } catch (DriverException) { $this->client->getManager()->selectServer(); return; diff --git a/tests/SpecTests/ResultExpectation.php b/tests/SpecTests/ResultExpectation.php index 580bdfd0a..1a28ba123 100644 --- a/tests/SpecTests/ResultExpectation.php +++ b/tests/SpecTests/ResultExpectation.php @@ -36,15 +36,12 @@ final class ResultExpectation public const ASSERT_CALLABLE = 11; public const ASSERT_DOCUMENTS_MATCH = 12; - private int $assertionType = self::ASSERT_NOTHING; - - /** @var mixed */ - private $expectedValue; + private mixed $expectedValue; /** @var callable */ private $assertionCallable; - private function __construct(int $assertionType, $expectedValue) + private function __construct(private int $assertionType, $expectedValue) { switch ($assertionType) { case self::ASSERT_BULKWRITE: @@ -66,7 +63,6 @@ private function __construct(int $assertionType, $expectedValue) break; } - $this->assertionType = $assertionType; $this->expectedValue = $expectedValue; } @@ -333,9 +329,8 @@ private static function isArrayOfObjects($array) * Determines whether the result is actually an error expectation. * * @see https://github.com/mongodb/specifications/blob/master/source/transactions/tests/README.rst#test-format - * @param mixed $result */ - private static function isErrorResult($result): bool + private static function isErrorResult(mixed $result): bool { if (! is_object($result)) { return false; diff --git a/tests/SpecTests/RetryableWrites/Prose3_ReturnOriginalErrorTest.php b/tests/SpecTests/RetryableWrites/Prose3_ReturnOriginalErrorTest.php index 0b80b6af9..7e573fc8c 100644 --- a/tests/SpecTests/RetryableWrites/Prose3_ReturnOriginalErrorTest.php +++ b/tests/SpecTests/RetryableWrites/Prose3_ReturnOriginalErrorTest.php @@ -44,11 +44,8 @@ public function testNoWritesPerformedErrorReturnsOriginalError(): void ]); $subscriber = new class ($this) implements CommandSubscriber { - private FunctionalTestCase $testCase; - - public function __construct(FunctionalTestCase $testCase) + public function __construct(private FunctionalTestCase $testCase) { - $this->testCase = $testCase; } public function commandStarted(CommandStartedEvent $event): void diff --git a/tests/TestCase.php b/tests/TestCase.php index b037c2908..287dc0b59 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -91,11 +91,8 @@ protected static function getDatabaseName(): string * * Only fields in the expected document will be checked. The actual document * may contain additional fields. - * - * @param array|object $expectedDocument - * @param array|object $actualDocument */ - public function assertMatchesDocument($expectedDocument, $actualDocument): void + public function assertMatchesDocument(array|object $expectedDocument, array|object $actualDocument): void { (new DocumentsMatchConstraint($expectedDocument, true, true))->evaluate($actualDocument); } @@ -105,11 +102,8 @@ public function assertMatchesDocument($expectedDocument, $actualDocument): void * * The actual document will be compared directly with the expected document * and may not contain extra fields. - * - * @param array|object $expectedDocument - * @param array|object $actualDocument */ - public function assertSameDocument($expectedDocument, $actualDocument): void + public function assertSameDocument(array|object $expectedDocument, array|object $actualDocument): void { $this->assertEquals( Document::fromPHP($this->normalizeBSON($expectedDocument))->toRelaxedExtendedJSON(), @@ -369,11 +363,9 @@ protected function wrapValuesForDataProvider(array $values): array * its type and keys. Document fields will be sorted alphabetically. Each * value within the array or document will then be normalized recursively. * - * @param array|object $bson - * @return BSONDocument|BSONArray * @throws InvalidArgumentException if $bson is not an array or object */ - private function normalizeBSON($bson) + private function normalizeBSON(array|object $bson): BSONDocument|BSONArray { if (! is_array($bson) && ! is_object($bson)) { throw new InvalidArgumentException('$bson is not an array or object'); diff --git a/tests/UnifiedSpecTests/Constraint/IsBsonType.php b/tests/UnifiedSpecTests/Constraint/IsBsonType.php index da88aca39..e2f73e807 100644 --- a/tests/UnifiedSpecTests/Constraint/IsBsonType.php +++ b/tests/UnifiedSpecTests/Constraint/IsBsonType.php @@ -67,15 +67,11 @@ final class IsBsonType extends Constraint 'number', ]; - private string $type; - - public function __construct(string $type) + public function __construct(private string $type) { if (! in_array($type, self::$types)) { throw new RuntimeException(sprintf('Type specified for %s <%s> is not a valid type', self::class, $type)); } - - $this->type = $type; } public static function any(): LogicalOr diff --git a/tests/UnifiedSpecTests/Constraint/Matches.php b/tests/UnifiedSpecTests/Constraint/Matches.php index caf391f40..2a80357fd 100644 --- a/tests/UnifiedSpecTests/Constraint/Matches.php +++ b/tests/UnifiedSpecTests/Constraint/Matches.php @@ -51,10 +51,7 @@ class Matches extends Constraint { use ConstraintTrait; - private ?EntityMap $entityMap = null; - - /** @var mixed */ - private $value; + private mixed $value; private bool $allowExtraRootKeys; @@ -64,10 +61,9 @@ class Matches extends Constraint private Factory $comparatorFactory; - public function __construct($value, ?EntityMap $entityMap = null, $allowExtraRootKeys = true, $allowOperators = true) + public function __construct($value, private ?EntityMap $entityMap = null, $allowExtraRootKeys = true, $allowOperators = true) { $this->value = self::prepare($value); - $this->entityMap = $entityMap; $this->allowExtraRootKeys = $allowExtraRootKeys; $this->allowOperators = $allowOperators; $this->comparatorFactory = Factory::getInstance(); @@ -348,7 +344,7 @@ private function doMatches($other) try { $this->assertMatches($this->value, $other); - } catch (RuntimeException $e) { + } catch (RuntimeException) { return false; } @@ -408,11 +404,8 @@ private static function isOperator(BSONDocument $document): bool * converted to a BSONDocument; otherwise, it will be converted to a * BSONArray or BSONDocument based on its keys. Each value within an array * or document will then be prepared recursively. - * - * @param mixed $bson - * @return mixed */ - private static function prepare($bson) + private static function prepare(mixed $bson): mixed { if (! is_array($bson) && ! is_object($bson)) { return $bson; diff --git a/tests/UnifiedSpecTests/Context.php b/tests/UnifiedSpecTests/Context.php index 18e2c3a39..2210cad75 100644 --- a/tests/UnifiedSpecTests/Context.php +++ b/tests/UnifiedSpecTests/Context.php @@ -48,23 +48,17 @@ final class Context /** @var array */ private array $eventObserversByClient = []; - private Client $internalClient; - private bool $inLoop = false; - private string $uri; - private string $singleMongosUri; private string $multiMongosUri; private ?object $advanceClusterTime = null; - public function __construct(Client $internalClient, string $uri) + public function __construct(private Client $internalClient, private string $uri) { $this->entityMap = new EntityMap(); - $this->internalClient = $internalClient; - $this->uri = $uri; /* TODO: Consider leaving these unset, although that might require * redundant topology/serverless checks in Context::createClient(). */ @@ -232,8 +226,7 @@ public function stopEventCollectors(): void } } - /** @param string|array $readPreferenceTags */ - private function convertReadPreferenceTags($readPreferenceTags): array + private function convertReadPreferenceTags(string|array $readPreferenceTags): array { return array_map( static function (string $readPreferenceTagSet): array { diff --git a/tests/UnifiedSpecTests/EntityMap.php b/tests/UnifiedSpecTests/EntityMap.php index 00c7f9d3f..32b99ffd0 100644 --- a/tests/UnifiedSpecTests/EntityMap.php +++ b/tests/UnifiedSpecTests/EntityMap.php @@ -63,12 +63,9 @@ public function offsetExists($id): bool return array_key_exists($id, $this->map); } - /** - * @see https://php.net/arrayaccess.offsetget - * @return mixed - */ + /** @see https://php.net/arrayaccess.offsetget */ #[ReturnTypeWillChange] - public function offsetGet($id) + public function offsetGet($id): mixed { assertIsString($id); assertArrayHasKey($id, $this->map, sprintf('No entity is defined for "%s"', $id)); @@ -100,16 +97,11 @@ public function set(string $id, $value, ?string $parentId = null): void $parent = $parentId === null ? null : $this->map[$parentId]; $this->map[$id] = new class ($id, $value, $parent) { - public string $id; - /** @var mixed */ - public $value; - public ?self $parent; + public mixed $value; - public function __construct(string $id, $value, ?self $parent = null) + public function __construct(public string $id, $value, public ?self $parent = null) { - $this->id = $id; $this->value = $value; - $this->parent = $parent; } public function getRoot(): self diff --git a/tests/UnifiedSpecTests/EventCollector.php b/tests/UnifiedSpecTests/EventCollector.php index 0a688e41a..74a9284cc 100644 --- a/tests/UnifiedSpecTests/EventCollector.php +++ b/tests/UnifiedSpecTests/EventCollector.php @@ -10,7 +10,6 @@ use function array_filter; use function array_flip; -use function get_class; use function microtime; use function MongoDB\Driver\Monitoring\addSubscriber; use function MongoDB\Driver\Monitoring\removeSubscriber; @@ -46,15 +45,9 @@ final class EventCollector implements CommandSubscriber 'CommandFailedEvent' => CommandFailedEvent::class, ]; - private string $clientId; - - private Context $context; - private array $collectEvents = []; - private BSONArray $eventList; - - public function __construct(BSONArray $eventList, array $collectEvents, string $clientId, Context $context) + public function __construct(private BSONArray $eventList, array $collectEvents, private string $clientId, private Context $context) { assertNotEmpty($collectEvents); @@ -69,10 +62,6 @@ public function __construct(BSONArray $eventList, array $collectEvents, string $ $this->collectEvents[self::$supportedEvents[$event]] = 1; } } - - $this->clientId = $clientId; - $this->context = $context; - $this->eventList = $eventList; } /** @see https://php.net/manual/en/mongodb-driver-monitoring-commandsubscriber.commandfailed.php */ @@ -103,8 +92,7 @@ public function stop(): void removeSubscriber($this); } - /** @param CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event */ - private function handleCommandMonitoringEvent($event): void + private function handleCommandMonitoringEvent(CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event): void { assertIsObject($event); @@ -112,7 +100,7 @@ private function handleCommandMonitoringEvent($event): void return; } - if (! isset($this->collectEvents[get_class($event)])) { + if (! isset($this->collectEvents[$event::class])) { return; } @@ -144,8 +132,7 @@ private function handleCommandMonitoringEvent($event): void $this->eventList[] = $log; } - /** @param CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event */ - private static function getConnectionId($event): string + private static function getConnectionId(CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event): string { $server = $event->getServer(); @@ -160,6 +147,6 @@ private static function getEventName(object $event): string $eventNamesByClass = array_flip(array_filter(self::$supportedEvents)); } - return $eventNamesByClass[get_class($event)]; + return $eventNamesByClass[$event::class]; } } diff --git a/tests/UnifiedSpecTests/EventObserver.php b/tests/UnifiedSpecTests/EventObserver.php index 1f8af6648..cd2f44d24 100644 --- a/tests/UnifiedSpecTests/EventObserver.php +++ b/tests/UnifiedSpecTests/EventObserver.php @@ -15,7 +15,6 @@ use function array_reverse; use function count; use function current; -use function get_class; use function is_object; use function key; use function MongoDB\Driver\Monitoring\addSubscriber; @@ -95,10 +94,6 @@ final class EventObserver implements CommandSubscriber private array $actualEvents = []; - private string $clientId; - - private Context $context; - /** * The configureFailPoint command (used by failPoint and targetedFailPoint * operations) is always ignored. @@ -107,9 +102,7 @@ final class EventObserver implements CommandSubscriber private array $observeEvents = []; - private bool $observeSensitiveCommands; - - public function __construct(array $observeEvents, array $ignoreCommands, bool $observeSensitiveCommands, string $clientId, Context $context) + public function __construct(array $observeEvents, array $ignoreCommands, private bool $observeSensitiveCommands, private string $clientId, private Context $context) { assertNotEmpty($observeEvents); @@ -132,10 +125,6 @@ public function __construct(array $observeEvents, array $ignoreCommands, bool $o assertIsString($command); $this->ignoreCommands[$command] = 1; } - - $this->observeSensitiveCommands = $observeSensitiveCommands; - $this->clientId = $clientId; - $this->context = $context; } /** @see https://php.net/manual/en/mongodb-driver-monitoring-commandsubscriber.commandfailed.php */ @@ -223,23 +212,16 @@ public function assert(array $expectedEvents, bool $ignoreExtraEvents): void } } - private function assertEvent($actual, stdClass $expected, string $message) + private function assertEvent($actual, stdClass $expected, string $message): void { assertIsObject($actual); - switch (get_class($actual)) { - case CommandStartedEvent::class: - return $this->assertCommandStartedEvent($actual, $expected, $message); - - case CommandSucceededEvent::class: - return $this->assertCommandSucceededEvent($actual, $expected, $message); - - case CommandFailedEvent::class: - return $this->assertCommandFailedEvent($actual, $expected, $message); - - default: - Assert::fail($message . ': Unsupported event type: ' . get_class($actual)); - } + match ($actual::class) { + CommandStartedEvent::class => $this->assertCommandStartedEvent($actual, $expected, $message), + CommandSucceededEvent::class => $this->assertCommandSucceededEvent($actual, $expected, $message), + CommandFailedEvent::class => $this->assertCommandFailedEvent($actual, $expected, $message), + default => Assert::fail($message . ': Unsupported event type: ' . $actual::class) + }; } private function assertCommandStartedEvent(CommandStartedEvent $actual, stdClass $expected, string $message): void @@ -329,8 +311,7 @@ private function assertCommandFailedEvent(CommandFailedEvent $actual, stdClass $ } } - /** @param CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event */ - private function handleEvent($event): void + private function handleEvent(CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event): void { if (! $this->context->isActiveClient($this->clientId)) { return; @@ -340,7 +321,7 @@ private function handleEvent($event): void return; } - if (! isset($this->observeEvents[get_class($event)])) { + if (! isset($this->observeEvents[$event::class])) { return; } @@ -355,8 +336,7 @@ private function handleEvent($event): void $this->actualEvents[] = $event; } - /** @param CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event */ - private function isSensitiveCommand($event): bool + private function isSensitiveCommand(CommandStartedEvent|CommandSucceededEvent|CommandFailedEvent $event): bool { if (isset(self::$sensitiveCommands[$event->getCommandName()])) { return true; diff --git a/tests/UnifiedSpecTests/ExpectedError.php b/tests/UnifiedSpecTests/ExpectedError.php index af28b0ece..52fc1f91c 100644 --- a/tests/UnifiedSpecTests/ExpectedError.php +++ b/tests/UnifiedSpecTests/ExpectedError.php @@ -13,7 +13,6 @@ use stdClass; use Throwable; -use function get_class; use function PHPUnit\Framework\assertArrayHasKey; use function PHPUnit\Framework\assertContainsOnly; use function PHPUnit\Framework\assertCount; @@ -128,7 +127,7 @@ public function __construct(?stdClass $o, EntityMap $entityMap) public function assert(?Throwable $e = null): void { if (! $this->isError && $e !== null) { - Assert::fail(sprintf("Operation threw unexpected %s: %s\n%s", get_class($e), $e->getMessage(), $e->getTraceAsString())); + Assert::fail(sprintf("Operation threw unexpected %s: %s\n%s", $e::class, $e->getMessage(), $e->getTraceAsString())); } if (! $this->isError) { diff --git a/tests/UnifiedSpecTests/ExpectedResult.php b/tests/UnifiedSpecTests/ExpectedResult.php index 88166eea5..5edc6e3ce 100644 --- a/tests/UnifiedSpecTests/ExpectedResult.php +++ b/tests/UnifiedSpecTests/ExpectedResult.php @@ -19,21 +19,18 @@ final class ExpectedResult { private ?Matches $constraint = null; - private EntityMap $entityMap; - /** * ID of the entity yielding the result. This is mainly used to associate * entities with a root client for collation of observed events. */ private ?string $yieldingEntityId = null; - public function __construct(stdClass $o, EntityMap $entityMap, ?string $yieldingEntityId = null) + public function __construct(stdClass $o, private EntityMap $entityMap, ?string $yieldingEntityId = null) { if (property_exists($o, 'expectResult')) { $this->constraint = new Matches($o->expectResult, $entityMap); } - $this->entityMap = $entityMap; $this->yieldingEntityId = $yieldingEntityId; } diff --git a/tests/UnifiedSpecTests/Loop.php b/tests/UnifiedSpecTests/Loop.php index 69c0b9a79..62848596e 100644 --- a/tests/UnifiedSpecTests/Loop.php +++ b/tests/UnifiedSpecTests/Loop.php @@ -26,10 +26,6 @@ final class Loop private static int $sleepUsecBetweenIterations = 0; - private Context $context; - - private array $operations = []; - private ?BSONArray $errorList = null; private ?BSONArray $failureList = null; @@ -38,13 +34,10 @@ final class Loop private string $numIterationsEntityId; - public function __construct(array $operations, Context $context, array $options = []) + public function __construct(private array $operations, private Context $context, array $options = []) { assertContainsOnly(Operation::class, $operations); - $this->operations = $operations; - $this->context = $context; - foreach (['storeErrorsAsEntity', 'storeFailuresAsEntity', 'storeSuccessesAsEntity', 'storeIterationsAsEntity'] as $option) { if (array_key_exists($option, $options)) { assertIsString($options[$option]); diff --git a/tests/UnifiedSpecTests/Operation.php b/tests/UnifiedSpecTests/Operation.php index 83c6a4924..1287e56c2 100644 --- a/tests/UnifiedSpecTests/Operation.php +++ b/tests/UnifiedSpecTests/Operation.php @@ -32,7 +32,6 @@ use function current; use function fopen; use function fwrite; -use function get_class; use function hex2bin; use function iterator_to_array; use function key; @@ -75,8 +74,6 @@ final class Operation private array $arguments = []; - private Context $context; - private EntityMap $entityMap; private ExpectedError $expectError; @@ -87,9 +84,8 @@ final class Operation private ?string $saveResultAsEntity = null; - public function __construct(stdClass $o, Context $context) + public function __construct(stdClass $o, private Context $context) { - $this->context = $context; $this->entityMap = $context->getEntityMap(); assertIsString($o->name); @@ -173,7 +169,7 @@ private function execute() $this->context->setActiveClient($this->entityMap->getRootClientIdOf($this->object)); - switch (get_class($object)) { + switch ($object::class) { case Client::class: $result = $this->executeForClient($object); break; @@ -199,7 +195,7 @@ private function execute() $result = $this->executeForBucket($object); break; default: - Assert::fail('Unsupported entity type: ' . get_class($object)); + Assert::fail('Unsupported entity type: ' . $object::class); } return $result; diff --git a/tests/UnifiedSpecTests/ServerParameterHelper.php b/tests/UnifiedSpecTests/ServerParameterHelper.php index 8f716fa67..b0afd5684 100644 --- a/tests/UnifiedSpecTests/ServerParameterHelper.php +++ b/tests/UnifiedSpecTests/ServerParameterHelper.php @@ -10,8 +10,6 @@ final class ServerParameterHelper { - private Client $client; - /** @var array */ private array $parameters = []; @@ -19,13 +17,11 @@ final class ServerParameterHelper private bool $allParametersFetched = false; - public function __construct(Client $client) + public function __construct(private Client $client) { - $this->client = $client; } - /** @return mixed */ - public function __get(string $parameter) + public function __get(string $parameter): mixed { if (! array_key_exists($parameter, $this->parameters)) { $this->fetchParameter($parameter); @@ -68,7 +64,7 @@ private function fetchAllParameters(): void $this->parameters = $cursor->toArray()[0]; $this->allParametersFetched = true; - } catch (CommandException $e) { + } catch (CommandException) { $this->fetchAllParametersFailed = true; } } diff --git a/tests/UnifiedSpecTests/UnifiedTestCase.php b/tests/UnifiedSpecTests/UnifiedTestCase.php index 3df7e842e..435400fb5 100644 --- a/tests/UnifiedSpecTests/UnifiedTestCase.php +++ b/tests/UnifiedSpecTests/UnifiedTestCase.php @@ -24,23 +24,8 @@ */ final class UnifiedTestCase implements IteratorAggregate { - private stdClass $test; - - private string $schemaVersion; - - private ?array $runOnRequirements = null; - - private ?array $createEntities = null; - - private ?array $initialData = null; - - private function __construct(stdClass $test, string $schemaVersion, ?array $runOnRequirements = null, ?array $createEntities = null, ?array $initialData = null) + private function __construct(private stdClass $test, private string $schemaVersion, private ?array $runOnRequirements = null, private ?array $createEntities = null, private ?array $initialData = null) { - $this->test = $test; - $this->schemaVersion = $schemaVersion; - $this->runOnRequirements = $runOnRequirements; - $this->createEntities = $createEntities; - $this->initialData = $initialData; } /** diff --git a/tests/UnifiedSpecTests/UnifiedTestRunner.php b/tests/UnifiedSpecTests/UnifiedTestRunner.php index 644cbcaaa..605eb2cac 100644 --- a/tests/UnifiedSpecTests/UnifiedTestRunner.php +++ b/tests/UnifiedSpecTests/UnifiedTestRunner.php @@ -68,8 +68,6 @@ final class UnifiedTestRunner private Client $internalClient; - private string $internalClientUri; - private bool $allowKillAllSessions = true; private ?EntityMap $entityMap = null; @@ -81,10 +79,9 @@ final class UnifiedTestRunner private ServerParameterHelper $serverParameterHelper; - public function __construct(string $internalClientUri) + public function __construct(private string $internalClientUri) { $this->internalClient = FunctionalTestCase::createTestClient($internalClientUri); - $this->internalClientUri = $internalClientUri; /* Atlas prohibits killAllSessions. Inspect the connection string to * determine if we should avoid calling killAllSessions(). This does