Skip to content
This repository was archived by the owner on Jul 28, 2024. It is now read-only.

Commit 4627423

Browse files
authored
Merge pull request #6 from wavevision/fix/zip-directory
Fix zip archive with directories and subdirectories
2 parents e7489d3 + a485ad1 commit 4627423

File tree

4 files changed

+58
-21
lines changed

4 files changed

+58
-21
lines changed

src/Utils/Zip/ZipArchive.php

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
use Nette\FileNotFoundException;
66
use Nette\SmartObject;
7+
use SplFileInfo;
78
use Wavevision\Utils\FileInfo;
9+
use Wavevision\Utils\Finder;
810
use Wavevision\Utils\Path;
911
use ZipArchive as Zip;
1012

@@ -13,25 +15,27 @@ class ZipArchive
1315

1416
use SmartObject;
1517

18+
private const INITIAL_DEPTH = 1;
19+
1620
/**
17-
* @var ZipArchiveFile[]
21+
* @var ZipArchiveItem[]
1822
*/
19-
private array $files;
23+
private array $items;
2024

2125
private string $path;
2226

2327
private Zip $zip;
2428

25-
public function __construct(string $path, ZipArchiveFile ...$files)
29+
public function __construct(string $path, ZipArchiveItem ...$items)
2630
{
27-
$this->files = $files;
31+
$this->items = $items;
2832
$this->path = $path;
2933
$this->zip = new Zip();
3034
}
3135

32-
public function addFile(ZipArchiveFile $file): self
36+
public function addItem(ZipArchiveItem $item): self
3337
{
34-
$this->files[] = $file;
38+
$this->items[] = $item;
3539
return $this;
3640
}
3741

@@ -43,8 +47,13 @@ public function close(): self
4347

4448
public function compress(): self
4549
{
46-
foreach ($this->files as $file) {
47-
$this->zip->addFile($this->getFilePath($file), $file->getName());
50+
foreach ($this->items as $item) {
51+
$path = $this->getItemPath($item);
52+
if (is_dir($path)) {
53+
$this->addDir($item, self::INITIAL_DEPTH);
54+
} else {
55+
$this->zip->addFile($path, $item->getName());
56+
}
4857
}
4958
return $this->close();
5059
}
@@ -78,17 +87,40 @@ public function write(): self
7887
return $this;
7988
}
8089

90+
/**
91+
* @param string[] $parents
92+
*/
93+
private function addDir(ZipArchiveItem $item, int $depth, array $parents = []): void
94+
{
95+
$deep = $depth > self::INITIAL_DEPTH;
96+
$dir = $item->getName();
97+
if ($deep) {
98+
$parents = [...$parents, $dir];
99+
$this->zip->addEmptyDir(Path::join(...$parents));
100+
}
101+
/** @var SplFileInfo $subItem */
102+
foreach (Finder::find('*')->in($item->getPath()) as $subItem) {
103+
$path = $subItem->getPathname();
104+
if ($subItem->isDir()) {
105+
$this->addDir(new ZipArchiveItem($path), $depth + 1, $parents);
106+
} else {
107+
$name = $subItem->getFilename();
108+
$this->zip->addFile($path, $deep ? Path::join(...[...$parents, $name]) : $name);
109+
}
110+
}
111+
}
112+
81113
private function getExtractDir(): string
82114
{
83115
$fileInfo = new FileInfo($this->getPath());
84116
return Path::join($fileInfo->getDirName(), $fileInfo->getBaseName(true));
85117
}
86118

87-
private function getFilePath(ZipArchiveFile $file): string
119+
private function getItemPath(ZipArchiveItem $item): string
88120
{
89-
$path = $file->getPath();
121+
$path = $item->getPath();
90122
if (!file_exists($path)) {
91-
throw new FileNotFoundException("Zip archive file '$path' not found.");
123+
throw new FileNotFoundException("Zip archive item '$path' not found.");
92124
}
93125
return $path;
94126
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Nette\SmartObject;
66

7-
final class ZipArchiveFile
7+
final class ZipArchiveItem
88
{
99

1010
use SmartObject;
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
test
2-
test.zip
1+
input
2+
output
3+
output.zip

tests/UtilsTests/ZipArchive/ZipArchiveTest.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,26 @@
55
use Nette\FileNotFoundException;
66
use PHPUnit\Framework\TestCase;
77
use Wavevision\Utils\Zip\ZipArchive;
8-
use Wavevision\Utils\Zip\ZipArchiveFile;
8+
use Wavevision\Utils\Zip\ZipArchiveItem;
99

1010
class ZipArchiveTest extends TestCase
1111
{
1212

1313
public function testZipArchive(): void
1414
{
15-
$path = __DIR__ . '/test.zip';
16-
$zip = new ZipArchive($path, new ZipArchiveFile(__DIR__ . '/../file.txt'));
17-
$this->assertEquals('test.zip', $zip->getName());
15+
$path = __DIR__ . '/output.zip';
16+
$zip = new ZipArchive(
17+
$path,
18+
new ZipArchiveItem(__DIR__ . '/input/dir'),
19+
new ZipArchiveItem(__DIR__ . '/input/file.txt')
20+
);
21+
$this->assertEquals('output.zip', $zip->getName());
1822
$zip->write()->compress();
1923
$this->assertFileExists($path);
2024
$zip->read()->extract();
21-
$this->assertDirectoryExists(__DIR__ . '/test');
22-
$zip->addFile(new ZipArchiveFile(''));
23-
$this->expectExceptionObject(new FileNotFoundException("Zip archive file '' not found."));
25+
$this->assertDirectoryExists(__DIR__ . '/output');
26+
$zip->addItem(new ZipArchiveItem(''));
27+
$this->expectExceptionObject(new FileNotFoundException("Zip archive item '' not found."));
2428
$zip->write()->compress();
2529
}
2630

0 commit comments

Comments
 (0)