diff --git a/psalm.xml.dist b/psalm.xml.dist index d9640583b..9aa4d0a7e 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -23,6 +23,7 @@ + diff --git a/src/BulkWriteResult.php b/src/BulkWriteResult.php index 548acc9a7..43c60ea2d 100644 --- a/src/BulkWriteResult.php +++ b/src/BulkWriteResult.php @@ -17,19 +17,16 @@ namespace MongoDB; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteResult; -use MongoDB\Exception\BadMethodCallException; /** * Result class for a bulk write operation. */ class BulkWriteResult { - private bool $isAcknowledged; - public function __construct(private WriteResult $writeResult, private array $insertedIds) { - $this->isAcknowledged = $writeResult->isAcknowledged(); } /** @@ -38,15 +35,11 @@ public function __construct(private WriteResult $writeResult, private array $ins * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getDeletedCount(): ?int + public function getDeletedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getDeletedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getDeletedCount(); } /** @@ -55,15 +48,11 @@ public function getDeletedCount(): ?int * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getInsertedCount(): ?int + public function getInsertedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getInsertedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getInsertedCount(); } /** @@ -86,15 +75,11 @@ public function getInsertedIds(): array * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getMatchedCount(): ?int + public function getMatchedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getMatchedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getMatchedCount(); } /** @@ -106,15 +91,11 @@ public function getMatchedCount(): ?int * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getModifiedCount(): ?int + public function getModifiedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getModifiedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getModifiedCount(); } /** @@ -123,15 +104,11 @@ public function getModifiedCount(): ?int * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getUpsertedCount(): ?int + public function getUpsertedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getUpsertedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getUpsertedCount(); } /** @@ -145,15 +122,11 @@ public function getUpsertedCount(): ?int * This method should only be called if the write was acknowledged. * * @see BulkWriteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ public function getUpsertedIds(): array { - if ($this->isAcknowledged) { - return $this->writeResult->getUpsertedIds(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getUpsertedIds(); } /** @@ -164,6 +137,6 @@ public function getUpsertedIds(): array */ public function isAcknowledged(): bool { - return $this->isAcknowledged; + return $this->writeResult->isAcknowledged(); } } diff --git a/src/DeleteResult.php b/src/DeleteResult.php index b58d3650d..23b416d0a 100644 --- a/src/DeleteResult.php +++ b/src/DeleteResult.php @@ -17,19 +17,16 @@ namespace MongoDB; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteResult; -use MongoDB\Exception\BadMethodCallException; /** * Result class for a delete operation. */ class DeleteResult { - private bool $isAcknowledged; - public function __construct(private WriteResult $writeResult) { - $this->isAcknowledged = $writeResult->isAcknowledged(); } /** @@ -38,15 +35,11 @@ public function __construct(private WriteResult $writeResult) * This method should only be called if the write was acknowledged. * * @see DeleteResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getDeletedCount(): ?int + public function getDeletedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getDeletedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getDeletedCount(); } /** @@ -57,6 +50,6 @@ public function getDeletedCount(): ?int */ public function isAcknowledged(): bool { - return $this->isAcknowledged; + return $this->writeResult->isAcknowledged(); } } diff --git a/src/Exception/BadMethodCallException.php b/src/Exception/BadMethodCallException.php index e165b95ac..00cece346 100644 --- a/src/Exception/BadMethodCallException.php +++ b/src/Exception/BadMethodCallException.php @@ -33,15 +33,4 @@ public static function classIsImmutable(string $class): self { return new self(sprintf('%s is immutable', $class)); } - - /** - * Thrown when accessing a result field on an unacknowledged write result. - * - * @param string $method Method name - * @internal - */ - public static function unacknowledgedWriteResultAccess(string $method): self - { - return new self(sprintf('%s should not be called for an unacknowledged write result', $method)); - } } diff --git a/src/GridFS/Bucket.php b/src/GridFS/Bucket.php index e054450cf..234af8954 100644 --- a/src/GridFS/Bucket.php +++ b/src/GridFS/Bucket.php @@ -583,16 +583,9 @@ public function rename(mixed $id, string $newFilename): void return; } - /* If the update resulted in no modification, it's possible that the - * file did not exist, in which case we must raise an error. Checking - * the write result's matched count will be most efficient, but fall - * back to a findOne operation if necessary (i.e. legacy writes). - */ - $found = $updateResult->getMatchedCount() !== null - ? $updateResult->getMatchedCount() === 1 - : $this->collectionWrapper->findFileById($id) !== null; - - if (! $found) { + // If the update resulted in no modification, it's possible that the + // file did not exist, in which case we must raise an error. + if ($updateResult->getMatchedCount() !== 1) { throw FileNotFoundException::byId($id, $this->getFilesNamespace()); } } diff --git a/src/GridFS/CollectionWrapper.php b/src/GridFS/CollectionWrapper.php index 30923ccde..5941992ef 100644 --- a/src/GridFS/CollectionWrapper.php +++ b/src/GridFS/CollectionWrapper.php @@ -73,7 +73,7 @@ public function deleteChunksByFilesId(mixed $id): void /** * Delete all GridFS files and chunks for a given filename. */ - public function deleteFileAndChunksByFilename(string $filename): ?int + public function deleteFileAndChunksByFilename(string $filename): int { /** @var iterable $files */ $files = $this->findFiles(['filename' => $filename], [ @@ -262,7 +262,7 @@ public function insertFile(array|object $file): void /** * Updates the filename field in the file document for all the files with a given filename. */ - public function updateFilenameForFilename(string $filename, string $newFilename): ?int + public function updateFilenameForFilename(string $filename, string $newFilename): int { return $this->filesCollection->updateMany( ['filename' => $filename], diff --git a/src/InsertManyResult.php b/src/InsertManyResult.php index 3d2176e58..2f27bd24e 100644 --- a/src/InsertManyResult.php +++ b/src/InsertManyResult.php @@ -17,19 +17,16 @@ namespace MongoDB; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteResult; -use MongoDB\Exception\BadMethodCallException; /** * Result class for a multi-document insert operation. */ class InsertManyResult { - private bool $isAcknowledged; - public function __construct(private WriteResult $writeResult, private array $insertedIds) { - $this->isAcknowledged = $writeResult->isAcknowledged(); } /** @@ -38,15 +35,11 @@ public function __construct(private WriteResult $writeResult, private array $ins * This method should only be called if the write was acknowledged. * * @see InsertManyResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getInsertedCount(): ?int + public function getInsertedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getInsertedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getInsertedCount(); } /** diff --git a/src/InsertOneResult.php b/src/InsertOneResult.php index 8e3d4b3ab..47e1d26bc 100644 --- a/src/InsertOneResult.php +++ b/src/InsertOneResult.php @@ -17,19 +17,16 @@ namespace MongoDB; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteResult; -use MongoDB\Exception\BadMethodCallException; /** * Result class for a single-document insert operation. */ class InsertOneResult { - private bool $isAcknowledged; - public function __construct(private WriteResult $writeResult, private mixed $insertedId) { - $this->isAcknowledged = $writeResult->isAcknowledged(); } /** @@ -38,15 +35,11 @@ public function __construct(private WriteResult $writeResult, private mixed $ins * This method should only be called if the write was acknowledged. * * @see InsertOneResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getInsertedCount(): ?int + public function getInsertedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getInsertedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getInsertedCount(); } /** diff --git a/src/UpdateResult.php b/src/UpdateResult.php index 9e8ef487f..a9d50b751 100644 --- a/src/UpdateResult.php +++ b/src/UpdateResult.php @@ -17,19 +17,16 @@ namespace MongoDB; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteResult; -use MongoDB\Exception\BadMethodCallException; /** * Result class for an update operation. */ class UpdateResult { - private bool $isAcknowledged; - public function __construct(private WriteResult $writeResult) { - $this->isAcknowledged = $writeResult->isAcknowledged(); } /** @@ -38,15 +35,11 @@ public function __construct(private WriteResult $writeResult) * This method should only be called if the write was acknowledged. * * @see UpdateResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getMatchedCount(): ?int + public function getMatchedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getMatchedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getMatchedCount(); } /** @@ -58,15 +51,11 @@ public function getMatchedCount(): ?int * This method should only be called if the write was acknowledged. * * @see UpdateResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getModifiedCount(): ?int + public function getModifiedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getModifiedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getModifiedCount(); } /** @@ -75,15 +64,11 @@ public function getModifiedCount(): ?int * This method should only be called if the write was acknowledged. * * @see UpdateResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ - public function getUpsertedCount(): ?int + public function getUpsertedCount(): int { - if ($this->isAcknowledged) { - return $this->writeResult->getUpsertedCount(); - } - - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return $this->writeResult->getUpsertedCount(); } /** @@ -98,19 +83,15 @@ public function getUpsertedCount(): ?int * This method should only be called if the write was acknowledged. * * @see UpdateResult::isAcknowledged() - * @throws BadMethodCallException if the write result is unacknowledged + * @throws LogicException if the write result is unacknowledged */ public function getUpsertedId(): mixed { - if ($this->isAcknowledged) { - foreach ($this->writeResult->getUpsertedIds() as $id) { - return $id; - } - - return null; + foreach ($this->writeResult->getUpsertedIds() as $id) { + return $id; } - throw BadMethodCallException::unacknowledgedWriteResultAccess(__METHOD__); + return null; } /** @@ -122,6 +103,6 @@ public function getUpsertedId(): mixed */ public function isAcknowledged(): bool { - return $this->isAcknowledged; + return $this->writeResult->isAcknowledged(); } } diff --git a/stubs/Driver/WriteResult.stub.php b/stubs/Driver/WriteResult.stub.php new file mode 100644 index 000000000..daa2f4eb1 --- /dev/null +++ b/stubs/Driver/WriteResult.stub.php @@ -0,0 +1,32 @@ +expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getDeletedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesInsertCount(BulkWriteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getInsertedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesMatchedCount(BulkWriteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getMatchedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesModifiedCount(BulkWriteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getModifiedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesUpsertedCount(BulkWriteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getUpsertedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesUpsertedIds(BulkWriteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getUpsertedIds(); } diff --git a/tests/Operation/DeleteFunctionalTest.php b/tests/Operation/DeleteFunctionalTest.php index 7ff002f97..b112bcc2a 100644 --- a/tests/Operation/DeleteFunctionalTest.php +++ b/tests/Operation/DeleteFunctionalTest.php @@ -5,8 +5,8 @@ use MongoDB\Collection; use MongoDB\DeleteResult; use MongoDB\Driver\BulkWrite; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteConcern; -use MongoDB\Exception\BadMethodCallException; use MongoDB\Exception\UnsupportedException; use MongoDB\Operation\Delete; use MongoDB\Tests\CommandObserver; @@ -136,8 +136,8 @@ public function testUnacknowledgedWriteConcern() /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesDeletedCount(DeleteResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getDeletedCount(); } diff --git a/tests/Operation/InsertManyFunctionalTest.php b/tests/Operation/InsertManyFunctionalTest.php index d4a786e71..1499aca8b 100644 --- a/tests/Operation/InsertManyFunctionalTest.php +++ b/tests/Operation/InsertManyFunctionalTest.php @@ -5,8 +5,8 @@ use MongoDB\BSON\Document; use MongoDB\BSON\ObjectId; use MongoDB\Collection; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteConcern; -use MongoDB\Exception\BadMethodCallException; use MongoDB\InsertManyResult; use MongoDB\Model\BSONDocument; use MongoDB\Operation\InsertMany; @@ -192,8 +192,8 @@ public function testUnacknowledgedWriteConcern() /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesInsertedCount(InsertManyResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getInsertedCount(); } diff --git a/tests/Operation/InsertOneFunctionalTest.php b/tests/Operation/InsertOneFunctionalTest.php index 218a8853c..054406798 100644 --- a/tests/Operation/InsertOneFunctionalTest.php +++ b/tests/Operation/InsertOneFunctionalTest.php @@ -5,8 +5,8 @@ use MongoDB\BSON\Document; use MongoDB\BSON\ObjectId; use MongoDB\Collection; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteConcern; -use MongoDB\Exception\BadMethodCallException; use MongoDB\InsertOneResult; use MongoDB\Model\BSONDocument; use MongoDB\Operation\InsertOne; @@ -183,8 +183,8 @@ public function testUnacknowledgedWriteConcern() /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesInsertedCount(InsertOneResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getInsertedCount(); } diff --git a/tests/Operation/UpdateFunctionalTest.php b/tests/Operation/UpdateFunctionalTest.php index 2a18f13aa..3f3db19c5 100644 --- a/tests/Operation/UpdateFunctionalTest.php +++ b/tests/Operation/UpdateFunctionalTest.php @@ -5,8 +5,8 @@ use MongoDB\BSON\ObjectId; use MongoDB\Collection; use MongoDB\Driver\BulkWrite; +use MongoDB\Driver\Exception\LogicException; use MongoDB\Driver\WriteConcern; -use MongoDB\Exception\BadMethodCallException; use MongoDB\Exception\UnsupportedException; use MongoDB\Operation\Update; use MongoDB\Tests\CommandObserver; @@ -287,32 +287,32 @@ public function testUnacknowledgedWriteConcern() /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesMatchedCount(UpdateResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getMatchedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesModifiedCount(UpdateResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getModifiedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesUpsertedCount(UpdateResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getUpsertedCount(); } /** @depends testUnacknowledgedWriteConcern */ public function testUnacknowledgedWriteConcernAccessesUpsertedId(UpdateResult $result): void { - $this->expectException(BadMethodCallException::class); - $this->expectExceptionMessageMatches('/[\w:\\\\]+ should not be called for an unacknowledged write result/'); + $this->expectException(LogicException::class); + $this->expectExceptionMessageMatches('/[\w:\\\\\(\)]+ should not be called for an unacknowledged write result/'); $result->getUpsertedId(); }