diff --git a/src/AzureBlobStorageAdapter.php b/src/AzureBlobStorageAdapter.php index d877623..0a3e89b 100644 --- a/src/AzureBlobStorageAdapter.php +++ b/src/AzureBlobStorageAdapter.php @@ -230,17 +230,20 @@ public function listContents(string $path, bool $deep): iterable { try { $prefix = $this->prefixer->prefixDirectoryPath($path); + $directories = [$prefix]; - if ($deep) { - foreach ($this->containerClient->getBlobs($prefix) as $item) { - yield $this->normalizeBlob($this->prefixer->stripPrefix($item->name), $item->properties); - } - } else { - foreach ($this->containerClient->getBlobsByHierarchy($prefix) as $item) { + while (!empty($directories)) { + $currentPrefix = array_shift($directories); + + foreach ($this->containerClient->getBlobsByHierarchy($currentPrefix) as $item) { if ($item instanceof Blob) { yield $this->normalizeBlob($this->prefixer->stripPrefix($item->name), $item->properties); } else { yield new DirectoryAttributes($this->prefixer->stripPrefix($item->name)); + + if ($deep) { + $directories[] = $item->name; + } } } } diff --git a/tests/AzureBlobStorageTest.php b/tests/AzureBlobStorageTest.php index 6797fa8..0c0128f 100644 --- a/tests/AzureBlobStorageTest.php +++ b/tests/AzureBlobStorageTest.php @@ -190,4 +190,28 @@ public function setting_visibility_causes_errors(): void $adapter->setVisibility('some-file.md', 'public'); } + + #[Test] + public function listing_contents_deep(): void + { + $this->runScenario(function () { + $adapter = $this->adapter(); + + $adapter->write('dir1/file1.txt', 'content1', new Config()); + $adapter->write('dir1/dir2/file2.txt', 'content2', new Config()); + $adapter->write('dir1/dir2/dir3/file3.txt', 'content3', new Config()); + /** @phpstan-ignore-next-line */ + $contents = iterator_to_array($adapter->listContents('', true)); + + $this->assertCount(6, $contents); // 3 files + 3 directories + + $paths = array_map(fn($item) => $item->path(), $contents); + $this->assertContains('dir1', $paths); + $this->assertContains('dir1/file1.txt', $paths); + $this->assertContains('dir1/dir2', $paths); + $this->assertContains('dir1/dir2/file2.txt', $paths); + $this->assertContains('dir1/dir2/dir3', $paths); + $this->assertContains('dir1/dir2/dir3/file3.txt', $paths); + }); + } }