Passed
Push — spaghetti ( 8fd548...8fd548 )
by simpletoimplement
02:20
created

Archive::getErrorMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types = 1);
2
3
namespace Spaghetti\XLSXParser;
4
5
use FilesystemIterator as FI;
6
use RecursiveDirectoryIterator as RDI;
7
use RecursiveIteratorIterator as RII;
8
use Spaghetti\XLSXParser\Exception\InvalidArchiveException;
9
use ZipArchive;
10
11
use function file_exists;
12
use function rmdir;
13
use function sprintf;
14
use function sys_get_temp_dir;
15
use function tempnam;
16
use function unlink;
17
18
/**
19
 * @internal
20
 */
21
final class Archive
22
{
23
    private string $tmpPath;
24
    private ?ZipArchive $zip = null;
25
26
    public function __construct(private readonly string $archivePath)
27
    {
28
        $this->tmpPath = tempnam(directory: sys_get_temp_dir(), prefix: 'spaghetti_xlsx_parser_archive');
29
        unlink(filename: $this->tmpPath);
30
    }
31
32
    public function __destruct()
33
    {
34
        $this->deleteTmp();
35
        $this->closeArchive();
36
    }
37
38
    public function extract(string $filePath): string
39
    {
40
        $tmpPath = sprintf('%s/%s', $this->tmpPath, $filePath);
41
42
        if (!file_exists(filename: $tmpPath)) {
43
            $this->getArchive()->extractTo(pathto: $this->tmpPath, files: $filePath);
44
        }
45
46
        return $tmpPath;
47
    }
48
49
    private function getArchive(): ZipArchive
50
    {
51
        if (null === $this->zip) {
52
            $this->zip = new ZipArchive();
53
            $error = $this->zip->open(filename: $this->archivePath);
54
55
            if (true !== $error) {
56
                $this->zip = null;
57
                throw new InvalidArchiveException(code: $error);
58
            }
59
        }
60
61
        return $this->zip;
62
    }
63
64
    private function closeArchive(): void
65
    {
66
        $this->zip?->close();
67
        $this->zip = null;
68
    }
69
70
    private function deleteTmp(): void
71
    {
72
        if (!file_exists(filename: $this->tmpPath)) {
73
            return;
74
        }
75
76
        $files = new RII(iterator: new RDI(directory: $this->tmpPath, flags: FI::SKIP_DOTS), mode: RII::CHILD_FIRST, );
77
78
        foreach ($files as $file) {
79
            if ($file->isDir()) {
80
                rmdir(directory: $file->getRealPath());
81
                continue;
82
            }
83
84
            unlink(filename: $file->getRealPath());
85
        }
86
87
        rmdir(directory: $this->tmpPath);
88
    }
89
}
90