Skip to content

Commit a7f503a

Browse files
committed
1 parent c408130 commit a7f503a

File tree

6 files changed

+87
-0
lines changed

6 files changed

+87
-0
lines changed

docs/reference/method/MongoDBGridFSBucket-registerGlobalStreamWrapperAlias.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Supported stream functions:
4848
- :php:`filesize() <filesize>`
4949
- :php:`file() <file>`
5050
- :php:`fopen() <fopen>` (with "r", "rb", "w", and "wb" modes)
51+
- :php:`rename() <rename>`
5152

5253
In read mode, the stream context can contain the option ``gridfs['revision']``
5354
to specify the revision number of the file to read. If omitted, the most recent

phpcs.xml.dist

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,11 @@
162162
<rule ref="PSR1.Classes.ClassDeclaration.MissingNamespace">
163163
<exclude-pattern>/docs/examples/codecs/</exclude-pattern>
164164
</rule>
165+
166+
<!-- **************************************** -->
167+
<!-- Exclude certain rules for stream wrapper -->
168+
<!-- **************************************** -->
169+
<rule ref="Squiz.NamingConventions.ValidVariableName.NotCamelCaps">
170+
<exclude-pattern>/src/GridFS/StreamWrapper.php</exclude-pattern>
171+
</rule>
165172
</ruleset>

src/GridFS/Exception/LogicException.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,9 @@ public static function openModeNotSupported(string $mode): self
6767
{
6868
return new self(sprintf('Mode "%s" is not supported by "gridfs://" files. Use one of "r", "rb", "w", or "wb".', $mode));
6969
}
70+
71+
public static function renamePathMismatch(string $from, string $to): self
72+
{
73+
return new self(sprintf('Cannot rename "%s" to "%s" because they are not in the same GridFS bucket.', $from, $to));
74+
}
7075
}

src/GridFS/ReadableStream.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
use Iterator;
2121
use MongoDB\BSON\Binary;
22+
use MongoDB\BSON\Document;
2223
use MongoDB\Driver\CursorInterface;
2324
use MongoDB\Exception\InvalidArgumentException;
2425
use MongoDB\GridFS\Exception\CorruptFileException;
@@ -176,6 +177,28 @@ public function readBytes(int $length): string
176177
return $data;
177178
}
178179

180+
/**
181+
* Rename all revisions of the file.
182+
*
183+
* @return int The number of revisions renamed
184+
*/
185+
public function rename(string $newFilename): int
186+
{
187+
/** @var Document[] $revisions */
188+
$revisions = $this->collectionWrapper->findFiles(
189+
['filename' => $this->file->filename],
190+
['typeMap' => ['root' => 'bson'], 'projection' => ['_id' => 1]],
191+
);
192+
$count = 0;
193+
194+
foreach ($revisions as $revision) {
195+
$this->collectionWrapper->updateFilenameForId($revision->get('_id'), $newFilename);
196+
$count++;
197+
}
198+
199+
return $count;
200+
}
201+
179202
/**
180203
* Seeks the chunk and buffer offsets for the next read operation.
181204
*

src/GridFS/StreamWrapper.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@
2222
use MongoDB\GridFS\Exception\FileNotFoundException;
2323
use MongoDB\GridFS\Exception\LogicException;
2424

25+
use function array_slice;
2526
use function assert;
2627
use function explode;
28+
use function implode;
2729
use function in_array;
2830
use function is_array;
2931
use function is_integer;
3032
use function is_resource;
33+
use function str_starts_with;
3134
use function stream_context_get_options;
3235
use function stream_get_wrappers;
3336
use function stream_wrapper_register;
@@ -90,6 +93,30 @@ public static function register(string $protocol = 'gridfs'): void
9093
stream_wrapper_register($protocol, static::class, STREAM_IS_URL);
9194
}
9295

96+
/**
97+
* Rename all revisions of a filename.
98+
*
99+
* @return int Number of revisions updated
100+
*/
101+
public function rename(string $path_from, string $path_to): int
102+
{
103+
$prefix = implode('/', array_slice(explode('/', $path_from, 4), 0, 3)) . '/';
104+
if (! str_starts_with($path_to, $prefix)) {
105+
throw LogicException::renamePathMismatch($path_from, $path_to);
106+
}
107+
108+
try {
109+
$this->stream_open($path_from, 'r', 0, $openedPath);
110+
} catch (FileNotFoundException $e) {
111+
return false;
112+
}
113+
114+
$newName = explode('/', $path_to, 4)[3] ?? '';
115+
assert($this->stream instanceof ReadableStream);
116+
117+
return $this->stream->rename($newName) > 0;
118+
}
119+
93120
/**
94121
* @see Bucket::resolveStreamContext()
95122
*

tests/GridFS/StreamWrapperFunctionalTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use function is_dir;
2626
use function is_file;
2727
use function is_link;
28+
use function rename;
2829
use function stream_context_create;
2930
use function stream_get_contents;
3031
use function time;
@@ -363,4 +364,27 @@ public function testCopy(): void
363364
$this->assertSame('foobar', file_get_contents($path . '.copy'));
364365
$this->assertSame('foobar', file_get_contents($path));
365366
}
367+
368+
public function testRenameAllRevisions(): void
369+
{
370+
$this->bucket->registerGlobalStreamWrapperAlias('bucket');
371+
$path = 'gridfs://bucket/filename';
372+
373+
$this->assertSame(6, file_put_contents($path, 'foobar'));
374+
$this->assertSame(6, file_put_contents($path, 'foobar'));
375+
$this->assertSame(6, file_put_contents($path, 'foobar'));
376+
377+
$this->assertTrue(rename($path, $path . '.renamed'));
378+
$this->assertTrue(file_exists($path . '.renamed'));
379+
$this->assertFalse(file_exists($path));
380+
$this->assertSame('foobar', file_get_contents($path . '.renamed'));
381+
}
382+
383+
public function testRenamePathMismatch(): void
384+
{
385+
$this->expectException(LogicException::class);
386+
$this->expectExceptionMessage('Cannot rename "gridfs://bucket/filename" to "gridfs://other/other" because they are not in the same GridFS bucket.');
387+
388+
rename('gridfs://bucket/filename', 'gridfs://other/other');
389+
}
366390
}

0 commit comments

Comments
 (0)