Skip to content

Commit 7781e75

Browse files
authored
PHPLIB-1568 Add GridFS\Bucket::deleteByName(filename) and renameByName(filename, newFilename) (#1504)
1 parent a6396a4 commit 7781e75

File tree

6 files changed

+110
-5
lines changed

6 files changed

+110
-5
lines changed

psalm-baseline.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,9 +284,20 @@
284284
</MixedArgumentTypeCoercion>
285285
</file>
286286
<file src="src/GridFS/CollectionWrapper.php">
287+
<InvalidNullableReturnType>
288+
<code><![CDATA[int]]></code>
289+
<code><![CDATA[int]]></code>
290+
</InvalidNullableReturnType>
287291
<MixedAssignment>
288292
<code><![CDATA[$ids[]]]></code>
289293
</MixedAssignment>
294+
<NullableReturnStatement>
295+
<code><![CDATA[$count]]></code>
296+
<code><![CDATA[$this->filesCollection->updateMany(
297+
['filename' => $filename],
298+
['$set' => ['filename' => $newFilename]],
299+
)->getMatchedCount()]]></code>
300+
</NullableReturnStatement>
290301
</file>
291302
<file src="src/GridFS/ReadableStream.php">
292303
<MixedArgument>

src/GridFS/Bucket.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,23 @@ public function delete(mixed $id)
242242
}
243243
}
244244

245+
/**
246+
* Delete all the revisions of a file name from the GridFS bucket.
247+
*
248+
* @param string $filename Filename
249+
*
250+
* @throws FileNotFoundException if no file could be selected
251+
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
252+
*/
253+
public function deleteByName(string $filename): void
254+
{
255+
$count = $this->collectionWrapper->deleteFileAndChunksByFilename($filename);
256+
257+
if ($count === 0) {
258+
throw FileNotFoundException::byFilename($filename);
259+
}
260+
}
261+
245262
/**
246263
* Writes the contents of a GridFS file to a writable stream.
247264
*
@@ -648,6 +665,24 @@ public function rename(mixed $id, string $newFilename)
648665
}
649666
}
650667

668+
/**
669+
* Renames all the revisions of a file name in the GridFS bucket.
670+
*
671+
* @param string $filename Filename
672+
* @param string $newFilename New filename
673+
*
674+
* @throws FileNotFoundException if no file could be selected
675+
* @throws DriverRuntimeException for other driver errors (e.g. connection errors)
676+
*/
677+
public function renameByName(string $filename, string $newFilename): void
678+
{
679+
$count = $this->collectionWrapper->updateFilenameForFilename($filename, $newFilename);
680+
681+
if ($count === 0) {
682+
throw FileNotFoundException::byFilename($filename);
683+
}
684+
}
685+
651686
/**
652687
* Writes the contents of a readable stream to a GridFS file.
653688
*

src/GridFS/CollectionWrapper.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public function deleteChunksByFilesId(mixed $id): void
7474
/**
7575
* Delete all GridFS files and chunks for a given filename.
7676
*/
77-
public function deleteFileAndChunksByFilename(string $filename): ?int
77+
public function deleteFileAndChunksByFilename(string $filename): int
7878
{
7979
/** @var iterable<array{_id: mixed}> $files */
8080
$files = $this->findFiles(['filename' => $filename], [
@@ -150,9 +150,6 @@ public function findChunksByFileId(mixed $id, int $fromChunk = 0)
150150
*/
151151
public function findFileByFilenameAndRevision(string $filename, int $revision): ?object
152152
{
153-
$filename = $filename;
154-
$revision = $revision;
155-
156153
if ($revision < 0) {
157154
$skip = abs($revision) - 1;
158155
$sortOrder = -1;
@@ -266,7 +263,7 @@ public function insertFile(array|object $file): void
266263
/**
267264
* Updates the filename field in the file document for all the files with a given filename.
268265
*/
269-
public function updateFilenameForFilename(string $filename, string $newFilename): ?int
266+
public function updateFilenameForFilename(string $filename, string $newFilename): int
270267
{
271268
return $this->filesCollection->updateMany(
272269
['filename' => $filename],

tests/GridFS/BucketFunctionalTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,34 @@ public function testDeleteStillRemovesChunksIfFileDoesNotExist($input, $expected
160160
$this->assertCollectionCount($this->chunksCollection, 0);
161161
}
162162

163+
public function testDeleteByName(): void
164+
{
165+
$this->bucket->uploadFromStream('filename', self::createStream('foobar1'));
166+
$this->bucket->uploadFromStream('filename', self::createStream('foobar2'));
167+
$this->bucket->uploadFromStream('filename', self::createStream('foobar3'));
168+
169+
$this->bucket->uploadFromStream('other', self::createStream('foobar'));
170+
171+
$this->assertCollectionCount($this->filesCollection, 4);
172+
$this->assertCollectionCount($this->chunksCollection, 4);
173+
174+
$this->bucket->deleteByName('filename');
175+
176+
$this->assertCollectionCount($this->filesCollection, 1);
177+
$this->assertCollectionCount($this->chunksCollection, 1);
178+
179+
$this->bucket->deleteByName('other');
180+
181+
$this->assertCollectionCount($this->filesCollection, 0);
182+
$this->assertCollectionCount($this->chunksCollection, 0);
183+
}
184+
185+
public function testDeleteByNameShouldRequireFileToExist(): void
186+
{
187+
$this->expectException(FileNotFoundException::class);
188+
$this->bucket->deleteByName('nonexistent-name');
189+
}
190+
163191
public function testDownloadingFileWithMissingChunk(): void
164192
{
165193
$id = $this->bucket->uploadFromStream('filename', self::createStream('foobar'));
@@ -723,6 +751,24 @@ public function testRenameShouldRequireFileToExist(): void
723751
$this->bucket->rename('nonexistent-id', 'b');
724752
}
725753

754+
public function testRenameByName(): void
755+
{
756+
$this->bucket->uploadFromStream('filename', self::createStream('foo'));
757+
$this->bucket->uploadFromStream('filename', self::createStream('foo'));
758+
$this->bucket->uploadFromStream('filename', self::createStream('foo'));
759+
760+
$this->bucket->renameByName('filename', 'newname');
761+
762+
$this->assertNull($this->bucket->findOne(['filename' => 'filename']), 'No file has the old name');
763+
$this->assertStreamContents('foo', $this->bucket->openDownloadStreamByName('newname'));
764+
}
765+
766+
public function testRenameByNameShouldRequireFileToExist(): void
767+
{
768+
$this->expectException(FileNotFoundException::class);
769+
$this->bucket->renameByName('nonexistent-name', 'b');
770+
}
771+
726772
public function testUploadFromStream(): void
727773
{
728774
$options = [

tests/UnifiedSpecTests/Operation.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,12 @@ private function executeForBucket(Bucket $bucket)
789789

790790
return $bucket->delete($args['id']);
791791

792+
case 'deleteByName':
793+
assertArrayHasKey('filename', $args);
794+
assertIsString($args['filename']);
795+
796+
return $bucket->deleteByName($args['filename']);
797+
792798
case 'downloadByName':
793799
assertArrayHasKey('filename', $args);
794800
assertIsString($args['filename']);
@@ -812,6 +818,14 @@ private function executeForBucket(Bucket $bucket)
812818

813819
return null;
814820

821+
case 'renameByName':
822+
assertArrayHasKey('filename', $args);
823+
assertArrayHasKey('newFilename', $args);
824+
assertIsString($args['filename']);
825+
assertIsString($args['newFilename']);
826+
827+
return $bucket->renameByName($args['filename'], $args['newFilename']);
828+
815829
case 'uploadWithId':
816830
assertArrayHasKey('id', $args);
817831
$args['_id'] = $args['id'];

tests/UnifiedSpecTests/Util.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,11 @@ final class Util
132132
],
133133
Bucket::class => [
134134
'delete' => ['id'],
135+
'deleteByName' => ['filename'],
135136
'downloadByName' => ['filename', 'revision'],
136137
'download' => ['id'],
137138
'rename' => ['id', 'newFilename'],
139+
'renameByName' => ['filename', 'newFilename'],
138140
'uploadWithId' => ['id', 'filename', 'source', 'chunkSizeBytes', 'disableMD5', 'contentType', 'metadata'],
139141
'upload' => ['filename', 'source', 'chunkSizeBytes', 'disableMD5', 'contentType', 'metadata'],
140142
],

0 commit comments

Comments
 (0)