diff --git a/src/GridFS/Bucket.php b/src/GridFS/Bucket.php index 234af8954..8eee0b356 100644 --- a/src/GridFS/Bucket.php +++ b/src/GridFS/Bucket.php @@ -219,6 +219,23 @@ public function delete(mixed $id): void } } + /** + * Delete all the revisions of a file name from the GridFS bucket. + * + * @param string $filename Filename + * + * @throws FileNotFoundException if no file could be selected + * @throws DriverRuntimeException for other driver errors (e.g. connection errors) + */ + public function deleteByName(string $filename): void + { + $count = $this->collectionWrapper->deleteFileAndChunksByFilename($filename); + + if ($count === 0) { + throw FileNotFoundException::byFilename($filename); + } + } + /** * Writes the contents of a GridFS file to a writable stream. * @@ -590,6 +607,24 @@ public function rename(mixed $id, string $newFilename): void } } + /** + * Renames all the revisions of a file name in the GridFS bucket. + * + * @param string $filename Filename + * @param string $newFilename New filename + * + * @throws FileNotFoundException if no file could be selected + * @throws DriverRuntimeException for other driver errors (e.g. connection errors) + */ + public function renameByName(string $filename, string $newFilename): void + { + $count = $this->collectionWrapper->updateFilenameForFilename($filename, $newFilename); + + if ($count === 0) { + throw FileNotFoundException::byFilename($filename); + } + } + /** * Writes the contents of a readable stream to a GridFS file. * diff --git a/src/GridFS/CollectionWrapper.php b/src/GridFS/CollectionWrapper.php index 5941992ef..62be77fc0 100644 --- a/src/GridFS/CollectionWrapper.php +++ b/src/GridFS/CollectionWrapper.php @@ -148,9 +148,6 @@ public function findChunksByFileId(mixed $id, int $fromChunk = 0): CursorInterfa */ public function findFileByFilenameAndRevision(string $filename, int $revision): ?object { - $filename = $filename; - $revision = $revision; - if ($revision < 0) { $skip = abs($revision) - 1; $sortOrder = -1; diff --git a/tests/GridFS/BucketFunctionalTest.php b/tests/GridFS/BucketFunctionalTest.php index 5abc7187f..8c347c5cd 100644 --- a/tests/GridFS/BucketFunctionalTest.php +++ b/tests/GridFS/BucketFunctionalTest.php @@ -158,6 +158,34 @@ public function testDeleteStillRemovesChunksIfFileDoesNotExist($input, $expected $this->assertCollectionCount($this->chunksCollection, 0); } + public function testDeleteByName(): void + { + $this->bucket->uploadFromStream('filename', self::createStream('foobar1')); + $this->bucket->uploadFromStream('filename', self::createStream('foobar2')); + $this->bucket->uploadFromStream('filename', self::createStream('foobar3')); + + $this->bucket->uploadFromStream('other', self::createStream('foobar')); + + $this->assertCollectionCount($this->filesCollection, 4); + $this->assertCollectionCount($this->chunksCollection, 4); + + $this->bucket->deleteByName('filename'); + + $this->assertCollectionCount($this->filesCollection, 1); + $this->assertCollectionCount($this->chunksCollection, 1); + + $this->bucket->deleteByName('other'); + + $this->assertCollectionCount($this->filesCollection, 0); + $this->assertCollectionCount($this->chunksCollection, 0); + } + + public function testDeleteByNameShouldRequireFileToExist(): void + { + $this->expectException(FileNotFoundException::class); + $this->bucket->deleteByName('nonexistent-name'); + } + public function testDownloadingFileWithMissingChunk(): void { $id = $this->bucket->uploadFromStream('filename', self::createStream('foobar')); @@ -721,6 +749,24 @@ public function testRenameShouldRequireFileToExist(): void $this->bucket->rename('nonexistent-id', 'b'); } + public function testRenameByName(): void + { + $this->bucket->uploadFromStream('filename', self::createStream('foo')); + $this->bucket->uploadFromStream('filename', self::createStream('foo')); + $this->bucket->uploadFromStream('filename', self::createStream('foo')); + + $this->bucket->renameByName('filename', 'newname'); + + $this->assertNull($this->bucket->findOne(['filename' => 'filename']), 'No file has the old name'); + $this->assertStreamContents('foo', $this->bucket->openDownloadStreamByName('newname')); + } + + public function testRenameByNameShouldRequireFileToExist(): void + { + $this->expectException(FileNotFoundException::class); + $this->bucket->renameByName('nonexistent-name', 'b'); + } + public function testUploadFromStream(): void { $options = [ diff --git a/tests/UnifiedSpecTests/Operation.php b/tests/UnifiedSpecTests/Operation.php index 858438a0a..96e1703ce 100644 --- a/tests/UnifiedSpecTests/Operation.php +++ b/tests/UnifiedSpecTests/Operation.php @@ -777,6 +777,12 @@ private function executeForBucket(Bucket $bucket) return $bucket->delete($args['id']); + case 'deleteByName': + assertArrayHasKey('filename', $args); + assertIsString($args['filename']); + + return $bucket->deleteByName($args['filename']); + case 'downloadByName': assertArrayHasKey('filename', $args); assertIsString($args['filename']); @@ -800,6 +806,14 @@ private function executeForBucket(Bucket $bucket) return null; + case 'renameByName': + assertArrayHasKey('filename', $args); + assertArrayHasKey('newFilename', $args); + assertIsString($args['filename']); + assertIsString($args['newFilename']); + + return $bucket->renameByName($args['filename'], $args['newFilename']); + case 'uploadWithId': assertArrayHasKey('id', $args); $args['_id'] = $args['id']; diff --git a/tests/UnifiedSpecTests/Util.php b/tests/UnifiedSpecTests/Util.php index 54b73e5d0..b812b0091 100644 --- a/tests/UnifiedSpecTests/Util.php +++ b/tests/UnifiedSpecTests/Util.php @@ -132,9 +132,11 @@ final class Util ], Bucket::class => [ 'delete' => ['id'], + 'deleteByName' => ['filename'], 'downloadByName' => ['filename', 'revision'], 'download' => ['id'], 'rename' => ['id', 'newFilename'], + 'renameByName' => ['filename', 'newFilename'], 'uploadWithId' => ['id', 'filename', 'source', 'chunkSizeBytes', 'metadata'], 'upload' => ['filename', 'source', 'chunkSizeBytes', 'metadata'], ],