Archive::__destruct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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