Archive::extract()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Akeneo\Component\SpreadsheetParser\Xlsx;
4
5
/**
6
 * Represents an XLSX Archive
7
 *
8
 * @author    Antoine Guigan <[email protected]>
9
 * @copyright 2014 Akeneo SAS (http://www.akeneo.com)
10
 * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
11
 */
12
class Archive
13
{
14
    /**
15
     *
16
     * @var string
17
     */
18
    protected $tempPath;
19
20
    /**
21
     *
22
     * @var string
23
     */
24
    protected $archivePath;
25
26
    /**
27
     * @var \ZipArchive
28
     */
29
    private $zip;
30
31
    /**
32
     * Constructor
33
     *
34
     * @param string $archivePath
35
     */
36
    public function __construct($archivePath)
37
    {
38
        $this->archivePath = $archivePath;
39
        $this->tempPath = tempnam(sys_get_temp_dir(), 'xls_parser_archive');
40
        unlink($this->tempPath);
41
    }
42
43
    /**
44
     * Extracts the specified file to a temp path, and return the temp path
45
     *
46
     * Files are only extracted once for the given archive
47
     *
48
     * @param string $filePath
49
     *
50
     * @return string
51
     */
52
    public function extract($filePath)
53
    {
54
        $tempPath = sprintf('%s/%s', $this->tempPath, $filePath);
55
        if (!file_exists($tempPath)) {
56
            $this->getArchive()->extractTo($this->tempPath, $filePath);
57
        }
58
59
        return $tempPath;
60
    }
61
62
    /**
63
     * Clears all extracted files
64
     */
65
    public function __destruct()
66
    {
67
        $this->deleteTemp();
68
        $this->closeArchive();
69
    }
70
71
    /**
72
     * Returns the archive
73
     *
74
     * @return \ZipArchive
75
     */
76
    protected function getArchive()
77
    {
78
        if (!$this->zip) {
79
            $this->zip = new \ZipArchive();
80
            if (true !== $errorCode = $this->zip->open($this->archivePath)) {
81
                $this->zip = null;
82
                throw new \RuntimeException('Error opening file: '.$this->getErrorMessage($errorCode));
83
            }
84
        }
85
86
        return $this->zip;
87
    }
88
89
    /**
90
     * Closes the archive
91
     */
92
    protected function closeArchive()
93
    {
94
        if ($this->zip) {
95
            $this->zip->close();
96
            $this->zip = null;
97
        }
98
    }
99
100
    /**
101
     * Deletes temporary files
102
     *
103
     * @return null
104
     */
105
    protected function deleteTemp()
106
    {
107
        if (!file_exists($this->tempPath)) {
108
            return;
109
        }
110
111
        $files = new \RecursiveIteratorIterator(
112
            new \RecursiveDirectoryIterator($this->tempPath, \RecursiveDirectoryIterator::SKIP_DOTS),
113
            \RecursiveIteratorIterator::CHILD_FIRST
114
        );
115
        foreach ($files as $file) {
116
            if ($file->isDir()) {
117
                rmdir($file->getRealPath());
118
            } else {
119
                unlink($file->getRealPath());
120
            }
121
        }
122
        rmdir($this->tempPath);
123
    }
124
125
    /**
126
     * Gets an error message from the error code
127
     *
128
     * @param string $errorCode
129
     *
130
     * @return string
131
     */
132
    protected function getErrorMessage($errorCode)
133
    {
134
        switch ($errorCode) {
135
            case \ZipArchive::ER_MULTIDISK:
136
                return 'Multi-disk zip archives not supported';
137
138
            case \ZipArchive::ER_RENAME:
139
                return 'Renaming temporary file failed';
140
141
            case \ZipArchive::ER_CLOSE:
142
                return 'Closing zip archive failed';
143
144
            case \ZipArchive::ER_SEEK:
145
                return 'Seek error';
146
147
            case \ZipArchive::ER_READ:
148
                return 'Read error';
149
150
            case \ZipArchive::ER_WRITE:
151
                return 'Write error';
152
153
            case \ZipArchive::ER_CRC:
154
                return 'CRC error';
155
156
            case \ZipArchive::ER_ZIPCLOSED:
157
                return 'Containing zip archive was closed';
158
159
            case \ZipArchive::ER_NOENT:
160
                return 'No such file';
161
162
            case \ZipArchive::ER_EXISTS:
163
                return 'File already exists';
164
165
            case \ZipArchive::ER_OPEN:
166
                return 'Can\'t open file';
167
168
            case \ZipArchive::ER_TMPOPEN:
169
                return 'Failure to create temporary file';
170
171
            case \ZipArchive::ER_ZLIB:
172
                return 'Zlib error';
173
174
            case \ZipArchive::ER_MEMORY:
175
                return 'Malloc failure';
176
177
            case \ZipArchive::ER_CHANGED:
178
                return 'Entry has been changed';
179
180
            case \ZipArchive::ER_COMPNOTSUPP:
181
                return 'Compression method not supported';
182
183
            case \ZipArchive::ER_EOF:
184
                return 'Premature EOF';
185
186
            case \ZipArchive::ER_INVAL:
187
                return 'Invalid argument';
188
189
            case \ZipArchive::ER_NOZIP:
190
                return 'Not a zip archive';
191
192
            case \ZipArchive::ER_INTERNAL:
193
                return 'Internal error';
194
195
            case \ZipArchive::ER_INCONS:
196
                return 'Zip archive inconsistent';
197
198
            case \ZipArchive::ER_REMOVE:
199
                return 'Can\'t remove file';
200
201
            case \ZipArchive::ER_DELETED:
202
                return 'Entry has been deleted';
203
204
            default:
205
                return 'An unknown error has occurred('.intval($errorCode).')';
206
        }
207
    }
208
}
209