Skip to content

Commit b25d2c0

Browse files
committed
feat: add prefixPath
1 parent 2ed5193 commit b25d2c0

File tree

2 files changed

+185
-4
lines changed

2 files changed

+185
-4
lines changed

src/BunnyCDNAdapter.php

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,21 @@ class BunnyCDNAdapter implements FilesystemAdapter
3939
*/
4040
private BunnyCDNClient $client;
4141

42+
/**
43+
* @var string
44+
*/
45+
private string $prefixPath;
46+
4247
/**
4348
* @param BunnyCDNClient $client
4449
* @param string $pullzone_url
50+
* @param string $prefixPath
4551
*/
46-
public function __construct(BunnyCDNClient $client, string $pullzone_url = '')
52+
public function __construct(BunnyCDNClient $client, string $pullzone_url = '', string $prefixPath = '')
4753
{
4854
$this->client = $client;
4955
$this->pullzone_url = $pullzone_url;
56+
$this->prefixPath = rtrim($prefixPath, '/');
5057
}
5158

5259
/**
@@ -57,6 +64,9 @@ public function __construct(BunnyCDNClient $client, string $pullzone_url = '')
5764
*/
5865
public function copy($source, $destination, Config $config): void
5966
{
67+
$this->prependPrefix($source);
68+
$this->prependPrefix($destination);
69+
6070
try {
6171
$this->write($destination, $this->read($source), new Config());
6272
// @codeCoverageIgnoreStart
@@ -73,6 +83,8 @@ public function copy($source, $destination, Config $config): void
7383
*/
7484
public function write($path, $contents, Config $config): void
7585
{
86+
$this->prependPrefix($path);
87+
7688
try {
7789
$this->client->upload($path, $contents);
7890
// @codeCoverageIgnoreStart
@@ -88,6 +100,8 @@ public function write($path, $contents, Config $config): void
88100
*/
89101
public function read($path): string
90102
{
103+
$this->prependPrefix($path);
104+
91105
try {
92106
return $this->client->download($path);
93107
// @codeCoverageIgnoreStart
@@ -104,6 +118,8 @@ public function read($path): string
104118
*/
105119
public function listContents(string $path = '', bool $deep = false): iterable
106120
{
121+
$this->prependPrefix($path);
122+
107123
try {
108124
$entries = $this->client->list($path);
109125
// @codeCoverageIgnoreStart
@@ -190,6 +206,8 @@ private function extractExtraMetadata(array $bunny_file_array): array
190206
*/
191207
public function detectMimeType(string $path): string
192208
{
209+
$this->prependPrefix($path);
210+
193211
try {
194212
$detector = new FinfoMimeTypeDetector();
195213
$mimeType = $detector->detectMimeTypeFromPath($path);
@@ -212,6 +230,8 @@ public function detectMimeType(string $path): string
212230
*/
213231
public function writeStream($path, $contents, Config $config): void
214232
{
233+
$this->prependPrefix($path);
234+
215235
$this->write($path, stream_get_contents($contents), $config);
216236
}
217237

@@ -233,6 +253,8 @@ public function readStream($path)
233253
*/
234254
public function deleteDirectory(string $path): void
235255
{
256+
$this->prependPrefix($path);
257+
236258
try {
237259
$this->client->delete(
238260
rtrim($path, '/').'/'
@@ -250,6 +272,8 @@ public function deleteDirectory(string $path): void
250272
*/
251273
public function createDirectory(string $path, Config $config): void
252274
{
275+
$this->prependPrefix($path);
276+
253277
try {
254278
$this->client->make_directory($path);
255279
// @codeCoverageIgnoreStart
@@ -269,6 +293,8 @@ public function createDirectory(string $path, Config $config): void
269293
*/
270294
public function setVisibility(string $path, string $visibility): void
271295
{
296+
$this->prependPrefix($path);
297+
272298
throw UnableToSetVisibility::atLocation($path, 'BunnyCDN does not support visibility');
273299
}
274300

@@ -277,6 +303,8 @@ public function setVisibility(string $path, string $visibility): void
277303
*/
278304
public function visibility(string $path): FileAttributes
279305
{
306+
$this->prependPrefix($path);
307+
280308
try {
281309
return new FileAttributes($this->getObject($path)->path(), null, $this->pullzone_url ? 'public' : 'private');
282310
} catch (UnableToReadFile $e) {
@@ -296,6 +324,8 @@ public function visibility(string $path): FileAttributes
296324
*/
297325
public function mimeType(string $path): FileAttributes
298326
{
327+
$this->prependPrefix($path);
328+
299329
try {
300330
$object = $this->getObject($path);
301331

@@ -334,6 +364,8 @@ public function mimeType(string $path): FileAttributes
334364
*/
335365
protected function getObject(string $path = ''): StorageAttributes
336366
{
367+
$this->prependPrefix($path);
368+
337369
$directory = pathinfo($path, PATHINFO_DIRNAME);
338370
$list = (new DirectoryListing($this->listContents($directory)))
339371
->filter(function (StorageAttributes $item) use ($path) {
@@ -357,6 +389,8 @@ protected function getObject(string $path = ''): StorageAttributes
357389
*/
358390
public function lastModified(string $path): FileAttributes
359391
{
392+
$this->prependPrefix($path);
393+
360394
try {
361395
return $this->getObject($path);
362396
} catch (UnableToReadFile $e) {
@@ -372,6 +406,8 @@ public function lastModified(string $path): FileAttributes
372406
*/
373407
public function fileSize(string $path): FileAttributes
374408
{
409+
$this->prependPrefix($path);
410+
375411
try {
376412
return $this->getObject($path);
377413
} catch (UnableToReadFile $e) {
@@ -387,6 +423,9 @@ public function fileSize(string $path): FileAttributes
387423
*/
388424
public function move(string $source, string $destination, Config $config): void
389425
{
426+
$this->prependPrefix($source);
427+
$this->prependPrefix($destination);
428+
390429
try {
391430
$this->write($destination, $this->read($source), new Config());
392431
$this->delete($source);
@@ -401,6 +440,8 @@ public function move(string $source, string $destination, Config $config): void
401440
*/
402441
public function delete($path): void
403442
{
443+
$this->prependPrefix($path);
444+
404445
try {
405446
$this->client->delete($path);
406447
// @codeCoverageIgnoreStart
@@ -426,6 +467,8 @@ public function directoryExists(string $path): bool
426467
*/
427468
public function fileExists(string $path): bool
428469
{
470+
$this->prependPrefix($path);
471+
429472
$list = new DirectoryListing($this->listContents(
430473
Util::splitPathIntoDirectoryAndFile($path)['dir']
431474
));
@@ -457,4 +500,21 @@ private static function parse_bunny_timestamp(string $timestamp): int
457500
{
458501
return (date_create_from_format('Y-m-d\TH:i:s.u', $timestamp) ?: date_create_from_format('Y-m-d\TH:i:s', $timestamp))->getTimestamp();
459502
}
503+
504+
private function prependPrefix(string &$path): void
505+
{
506+
if ($this->prefixPath === '') {
507+
return;
508+
}
509+
510+
if ($path === $this->prefixPath) {
511+
return;
512+
}
513+
514+
if (\str_starts_with($path, $this->prefixPath.'/')) {
515+
return;
516+
}
517+
518+
$path = $this->prefixPath.'/'.$path;
519+
}
460520
}

tests/FlysystemTestSuite.php

Lines changed: 124 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@ class FlysystemTestSuite extends FilesystemAdapterTestCase
2323
{
2424
const STORAGE_ZONE = 'testing_storage_zone';
2525

26+
/**
27+
* @var FilesystemAdapter|null
28+
*/
29+
protected static ?FilesystemAdapter $prefixAdapter = null;
30+
31+
/**
32+
* @var BunnyCDNClient|null
33+
*/
34+
protected static ?BunnyCDNClient $bunnyCDNClient = null;
35+
36+
/**
37+
* @var string|null
38+
*/
39+
protected static ?string $prefixPath = null;
40+
2641
/**
2742
* Used for testing protected methods
2843
*
@@ -37,8 +52,26 @@ public static function callMethod($obj, $name, array $args)
3752
return $method->invokeArgs($obj, $args);
3853
}
3954

40-
public static function createFilesystemAdapter(): FilesystemAdapter
55+
public static function setUpBeforeClass(): void
56+
{
57+
static::$prefixPath = 'test'.bin2hex(random_bytes(10));
58+
}
59+
60+
public function prefixAdapter(): FilesystemAdapter
4161
{
62+
if (! static::$prefixAdapter instanceof FilesystemAdapter) {
63+
static::$prefixAdapter = static::createFilesystemAdapter(static::$prefixPath);
64+
}
65+
66+
return static::$prefixAdapter;
67+
}
68+
69+
private static function bunnyCDNClient(): BunnyCDNClient
70+
{
71+
if (static::$bunnyCDNClient instanceof BunnyCDNClient) {
72+
return static::$bunnyCDNClient;
73+
}
74+
4275
$filesystem = new Filesystem(new InMemoryFilesystemAdapter());
4376

4477
$mock_client = Mockery::mock(new BunnyCDNClient(self::STORAGE_ZONE, 'api-key'));
@@ -68,15 +101,103 @@ public static function createFilesystemAdapter(): FilesystemAdapter
68101
});
69102

70103
$mock_client->shouldReceive('make_directory')->andReturnUsing(function ($path) use ($filesystem) {
71-
return $filesystem->createDirectory($path);
104+
$filesystem->createDirectory($path);
72105
});
73106

74107
$mock_client->shouldReceive('delete')->andReturnUsing(function ($path) use ($filesystem) {
75108
$filesystem->deleteDirectory($path);
76109
$filesystem->delete($path);
77110
});
78111

79-
return new BunnyCDNAdapter($mock_client);
112+
static::$bunnyCDNClient = $mock_client;
113+
114+
return static::$bunnyCDNClient;
115+
}
116+
117+
public static function createFilesystemAdapter(string $prefixPath = ''): FilesystemAdapter
118+
{
119+
return new BunnyCDNAdapter(static::bunnyCDNClient(), '', $prefixPath);
120+
}
121+
122+
/**
123+
* @test
124+
*/
125+
public function prefix_path(): void
126+
{
127+
$this->runScenario(function () {
128+
$adapter = $this->adapter();
129+
$prefixPathAdapter = $this->prefixAdapter();
130+
131+
self::assertNotEmpty(
132+
static::$prefixPath
133+
);
134+
135+
self::assertIsString(
136+
static::$prefixPath
137+
);
138+
139+
$content = 'this is test';
140+
$prefixPathAdapter->write(
141+
'source.file.svg',
142+
$content,
143+
new Config([Config::OPTION_VISIBILITY => Visibility::PUBLIC])
144+
);
145+
146+
self::assertTrue($prefixPathAdapter->fileExists(
147+
'source.file.svg'
148+
));
149+
150+
self::assertTrue($adapter->directoryExists(
151+
static::$prefixPath
152+
));
153+
154+
self::assertTrue($adapter->fileExists(
155+
static::$prefixPath.'/source.file.svg'
156+
));
157+
158+
$prefixPathAdapter->copy(
159+
'source.file.svg',
160+
'source.copy.file.svg',
161+
new Config([Config::OPTION_VISIBILITY => Visibility::PUBLIC])
162+
);
163+
164+
self::assertTrue($adapter->fileExists(
165+
static::$prefixPath.'/source.copy.file.svg'
166+
));
167+
168+
self::assertTrue($prefixPathAdapter->fileExists(
169+
'source.copy.file.svg'
170+
));
171+
172+
$prefixPathAdapter->delete(
173+
'source.copy.file.svg'
174+
);
175+
176+
$this->assertEquals($content, $prefixPathAdapter->read('source.file.svg'));
177+
178+
$this->assertEquals(
179+
$prefixPathAdapter->read('source.file.svg'),
180+
$adapter->read(static::$prefixPath.'/source.file.svg')
181+
);
182+
183+
$this->assertSame(
184+
'image/svg+xml',
185+
$prefixPathAdapter->mimeType('source.file.svg')->mimeType()
186+
);
187+
188+
$this->assertEquals(
189+
$prefixPathAdapter->mimeType('source.file.svg')->mimeType(),
190+
$adapter->mimeType(static::$prefixPath.'/source.file.svg')->mimeType()
191+
);
192+
193+
$prefixPathAdapter->delete(
194+
'source.file.svg'
195+
);
196+
197+
self::assertFalse($prefixPathAdapter->fileExists(
198+
'source.file.svg'
199+
));
200+
});
80201
}
81202

82203
/**

0 commit comments

Comments
 (0)