Skip to content

Commit

Permalink
Merge pull request #29 from chrisnharvey/pseudo-directories
Browse files Browse the repository at this point in the history
Add support for pseudo-directories
  • Loading branch information
mzur authored Apr 1, 2022
2 parents 34c4255 + 623e9d3 commit 47f6283
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 17 deletions.
24 changes: 16 additions & 8 deletions src/SwiftAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use GuzzleHttp\Psr7\Stream;
use InvalidArgumentException;
use League\Flysystem\Config;
use League\Flysystem\DirectoryAttributes;
use League\Flysystem\FileAttributes;
use League\Flysystem\FilesystemAdapter;
use League\Flysystem\PathPrefixer;
Expand Down Expand Up @@ -233,10 +234,13 @@ public function readStream(string $path)
*/
public function listContents(string $path, bool $deep): iterable
{
$location = $this->prefixer->prefixPath($path);
$location = $this->prefixer->prefixDirectoryPath($path);

// Fetch objects with preudo-directory support. See:
// https://docs.openstack.org/swift/latest/api/pseudo-hierarchical-folders-directories.html
$objectList = $this->container->listObjects([
'prefix' => $location,
'delimiter' => '/',
]);

foreach ($objectList as $object) {
Expand Down Expand Up @@ -319,25 +323,29 @@ protected function getObject(string $path): StorageObject
return $object;
}

protected function normalizeObject(StorageObject $object): FileAttributes
protected function normalizeObject(StorageObject $object): FileAttributes|DirectoryAttributes
{
$name = $this->prefixer->stripPrefix($object->name);
$name = $this->prefixer->stripDirectoryPrefix($object->name);

if ($object->lastModified instanceof DateTimeInterface) {
$timestamp = $object->lastModified->getTimestamp();
} else {
} elseif (is_string($object->lastModified)) {
$timestamp = strtotime($object->lastModified);
} else {
$timestamp = null;
}

// Check if the object name ends with a slash. This is a pseudo-directory.
if (substr_compare($object->name, '/', -1) === 0) {
return new DirectoryAttributes($name);
}

return new FileAttributes(
$name,
(int) $object->contentLength,
null,
$timestamp,
$object->contentType,
[
'type' => 'file',
]
$object->contentType
);
}

Expand Down
45 changes: 36 additions & 9 deletions tests/SwiftAdapterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ public function testDirectoryExists()
$this->container->shouldReceive('listObjects')
->once()
->with([
'prefix' => 'hello',
'prefix' => 'hello/',
'delimiter' => '/',
])
->andReturn($objects);

Expand All @@ -138,7 +139,8 @@ public function testDirectoryExists()
$this->container->shouldReceive('listObjects')
->once()
->with([
'prefix' => 'world',
'prefix' => 'world/',
'delimiter' => '/',
])
->andReturn($objects);

Expand All @@ -161,7 +163,8 @@ public function testListContents()
$this->container->shouldReceive('listObjects')
->once()
->with([
'prefix' => 'hello',
'prefix' => 'hello/',
'delimiter' => '/',
])
->andReturn($objects);

Expand All @@ -172,9 +175,7 @@ public function testListContents()
'mime_type' => 'text/html; charset=UTF-8',
'visibility' => null,
'file_size' => 0,
'extra_metadata' => [
'type' => 'file',
],
'extra_metadata' => [],
];

$contents = $this->adapter->listContents('hello', false);
Expand All @@ -188,6 +189,34 @@ public function testListContents()
$this->assertEquals($times, $count);
}

public function testListContentsPseudoDirectory()
{
$object = Mockery::mock(StorageObject::class);
$object->name = 'name/';
$generator = function () use ($object) {
yield $object;
};
$objects = $generator();
$this->container->shouldReceive('listObjects')
->once()
->with([
'prefix' => 'hello/',
'delimiter' => '/',
])
->andReturn($objects);

$expect = [
'path' => 'name',
'type' => 'dir',
'visibility' => null,
'extra_metadata' => [],
'last_modified' => null,
];

$contents = iterator_to_array($this->adapter->listContents('hello', false));
$this->assertEquals($expect, $contents[0]->jsonSerialize());
}

public function testMove()
{
$this->object->shouldReceive('copy')->once()->with([
Expand Down Expand Up @@ -358,9 +387,7 @@ public function testMetadataMethods()
'mime_type' => 'text/html; charset=UTF-8',
'visibility' => null,
'file_size' => 0,
'extra_metadata' => [
'type' => 'file',
],
'extra_metadata' => [],
];

foreach ($methods as $method) {
Expand Down

0 comments on commit 47f6283

Please sign in to comment.