Completed
Branch 0.1.x (de528d)
by f
03:18 queued 01:28
created

Zip::getFileResource()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
namespace wapmorgan\UnifiedArchive\Formats;
3
4
use Exception;
5
use wapmorgan\UnifiedArchive\ArchiveEntry;
6
use wapmorgan\UnifiedArchive\ArchiveInformation;
7
use wapmorgan\UnifiedArchive\PclzipZipInterface;
8
use ZipArchive;
9
10
/**
11
 * Class Zip
12
 *
13
 * @package wapmorgan\UnifiedArchive\Formats
14
 * @requires ext-zip
15
 */
16
class Zip extends BasicFormat
17
{
18
    /** @var ZipArchive */
19
    protected $zip;
20
21
    /**
22
     * BasicFormat constructor.
23
     *
24
     * @param string $archiveFileName
25
     * @throws \Exception
26
     */
27 4
    public function __construct($archiveFileName)
28
    {
29 4
        $this->open($archiveFileName);
30 4
    }
31
32
    /**
33
     * @param $archiveFileName
34
     *
35
     * @throws \Exception
36
     */
37 4
    protected function open($archiveFileName)
38
    {
39 4
        $this->zip = new ZipArchive();
40 4
        $open_result = $this->zip->open($archiveFileName);
41 4
        if ($open_result !== true) {
42
            throw new Exception('Could not open Zip archive: '.$open_result);
43
        }
44 4
    }
45
46
    /**
47
     * Zip format destructor
48
     */
49 4
    public function __destruct()
50
    {
51 4
        unset($this->zip);
52 4
    }
53
54
    /**
55
     * @return ArchiveInformation
56
     */
57 4
    public function getArchiveInformation()
58
    {
59 4
        $information = new ArchiveInformation();
60 4
        for ($i = 0; $i < $this->zip->numFiles; $i++) {
61 4
            $file = $this->zip->statIndex($i);
62
            // skip directories
63 4
            if (in_array(substr($file['name'], -1), ['/', '\\'], true))
64 4
                continue;
65 4
            $information->files[$i] = $file['name'];
66 4
            $information->compressedFilesSize += $file['comp_size'];
67 4
            $information->uncompressedFilesSize += $file['size'];
68
        }
69 4
        return $information;
70
    }
71
72
    /**
73
     * @return array
74
     */
75
    public function getFileNames()
76
    {
77
        $files = [];
78
        for ($i = 0; $i < $this->zip->numFiles; $i++) {
79
            $file_name = $this->zip->getNameIndex($i);
80
            // skip directories
81
            if (in_array(substr($file_name, -1), ['/', '\\'], true))
82
                continue;
83
            $files[] = $file_name;
84
        }
85
        return $files;
86
    }
87
88
    /**
89
     * @param string $fileName
90
     *
91
     * @return bool
92
     */
93
    public function isFileExists($fileName)
94
    {
95
        return $this->zip->statName($fileName) !== false;
96
    }
97
98
    /**
99
     * @param string $fileName
100
     *
101
     * @return ArchiveEntry
102
     */
103 1
    public function getFileData($fileName)
104
    {
105 1
        $stat = $this->zip->statName($fileName);
106 1
        return new ArchiveEntry($fileName, $stat['comp_size'], $stat['size'], $stat['mtime'],
107 1
            $stat['comp_method'] != 0);
108
    }
109
110
    /**
111
     * @param string $fileName
112
     *
113
     * @return string|false
114
     * @throws \Exception
115
     */
116 2
    public function getFileContent($fileName)
117
    {
118 2
        $result = $this->zip->getFromName($fileName);
119 2
        if ($result === false)
120
            throw new Exception('Could not get file information: '.$result);
121 2
        return $result;
122
    }
123
124
    /**
125
     * @param string $fileName
126
     *
127
     * @return bool|resource|string
128
     */
129 1
    public function getFileResource($fileName)
130
    {
131 1
        return $this->zip->getStream($fileName);
132
    }
133
134
    /**
135
     * @param string $outputFolder
136
     * @param array $files
137
     * @return false|resource
138
     * @throws \Exception
139
     */
140
    public function extractFiles($outputFolder, array $files)
141
    {
142
        if ($this->zip->extractTo($outputFolder, $files) === false)
143
            throw new Exception($this->zip->getStatusString(), $this->zip->status);
144
145
        return count($files);
0 ignored issues
show
Bug Best Practice introduced by
The expression return count($files) returns the type integer which is incompatible with the documented return type false|resource.
Loading history...
146
    }
147
148
    /**
149
     * @param string $outputFolder
150
     * @throws \Exception
151
     */
152
    public function extractArchive($outputFolder)
153
    {
154
        if ($this->zip->extractTo($outputFolder) === false)
155
            throw new Exception($this->zip->getStatusString(), $this->zip->status);
156
        return $this->zip->numFiles;
157
    }
158
159
    /**
160
     * @param array $files
161
     *
162
     * @return int
163
     * @throws \Exception
164
     */
165 1
    public function deleteFiles(array $files)
166
    {
167 1
        $count = 0;
168 1
        foreach ($files as $file) {
169 1
            if ($this->zip->deleteName($file) === false)
170
                throw new Exception($this->zip->getStatusString(), $this->zip->status);
171 1
            $count++;
172
        }
173
174
        // reopen archive to save changes
175 1
        $archive_filename = $this->zip->filename;
176 1
        $this->zip->close();
177 1
        $this->open($archive_filename);
178
179 1
        return $count;
180
    }
181
182
    /**
183
     * @param array $files
184
     *
185
     * @return int
186
     * @throws \Exception
187
     */
188 1
    public function addFiles(array $files)
189
    {
190 1
        $added_files = 0;
191 1
        foreach ($files as $localName => $fileName) {
192 1
            if (is_null($fileName)) {
193
                if ($this->zip->addEmptyDir($localName) === false)
194
                    throw new Exception($this->zip->getStatusString(), $this->zip->status);
195
            } else {
196 1
                if ($this->zip->addFile($fileName, $localName) === false)
197
                    throw new Exception($this->zip->getStatusString(), $this->zip->status);
198 1
                $added_files++;
199
            }
200
        }
201
202
        // reopen archive to save changes
203 1
        $archive_filename = $this->zip->filename;
204 1
        $this->zip->close();
205 1
        $this->open($archive_filename);
206
207 1
        return $added_files;
208
    }
209
210
    /**
211
     * @param array  $files
212
     * @param string $archiveFileName
213
     *
214
     * @return false|int
215
     * @throws \Exception
216
     */
217 1
    public static function createArchive(array $files, $archiveFileName){
218 1
        $zip = new ZipArchive();
219 1
        $result = $zip->open($archiveFileName, ZipArchive::CREATE);
220 1
        if ($result !== true)
221
            throw new Exception('ZipArchive error: '.$result);
222 1
        foreach ($files as $localName => $fileName) {
223 1
            if ($fileName === null) {
224 1
                if ($zip->addEmptyDir($localName) === false)
225 1
                    return false;
226
            } else {
227 1
                if ($zip->addFile($fileName, $localName) === false)
228 1
                    return false;
229
            }
230
        }
231 1
        $zip->close();
232
233 1
        return count($files);
234
    }
235
236
    /**
237
     * @return \wapmorgan\UnifiedArchive\PclzipZipInterface
238
     */
239
    public function getPclZip()
240
    {
241
        return new PclzipZipInterface($this->zip);
242
    }
243
244
    /**
245
     * @return bool
246
     */
247 1
    public static function canCreateArchive()
248
    {
249 1
        return true;
250
    }
251
252
    /**
253
     * @return bool
254
     */
255 1
    public static function canAddFiles()
256
    {
257 1
        return true;
258
    }
259
260
    /**
261
     * @return bool
262
     */
263 1
    public static function canDeleteFiles()
264
    {
265 1
        return true;
266
    }
267
}