Passed
Push — 0.1.x ( 9bc492...223229 )
by f
02:59
created

Zip::canAddFiles()   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 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
    public function __construct($archiveFileName)
28
    {
29
        $this->open($archiveFileName);
30
    }
31
32
    /**
33
     * @param $archiveFileName
34
     *
35
     * @throws \Exception
36
     */
37
    protected function open($archiveFileName)
38
    {
39
        $this->zip = new ZipArchive();
40
        $open_result = $this->zip->open($archiveFileName);
41
        if ($open_result !== true) {
42
            throw new Exception('Could not open Zip archive: '.$open_result);
43
        }
44
    }
45
46
    /**
47
     * Zip format destructor
48
     */
49
    public function __destruct()
50
    {
51
        unset($this->zip);
52
    }
53
54
    /**
55
     * @return ArchiveInformation
56
     */
57
    public function getArchiveInformation()
58
    {
59
        $information = new ArchiveInformation();
60
        for ($i = 0; $i < $this->zip->numFiles; $i++) {
61
            $file = $this->zip->statIndex($i);
62
            // skip directories
63
            if (in_array(substr($file['name'], -1), ['/', '\\'], true))
64
                continue;
65
            $information->files[$i] = $file['name'];
66
            $information->compressedFilesSize += $file['comp_size'];
67
            $information->uncompressedFilesSize += $file['size'];
68
        }
69
        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
    public function getFileData($fileName)
104
    {
105
        $stat = $this->zip->statName($fileName);
106
        return new ArchiveEntry($fileName, $stat['comp_size'], $stat['size'], $stat['mtime'],
107
            $stat['comp_method'] != 0);
108
    }
109
110
    /**
111
     * @param string $fileName
112
     *
113
     * @return string|false
114
     * @throws \Exception
115
     */
116
    public function getFileContent($fileName)
117
    {
118
        $result = $this->zip->getFromName($fileName);
119
        if ($result === false)
120
            throw new Exception('Could not get file information: '.$result);
121
        return $result;
122
    }
123
124
    /**
125
     * @param string $fileName
126
     *
127
     * @return bool|resource|string
128
     */
129
    public function getFileResource($fileName)
130
    {
131
        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
    public function deleteFiles(array $files)
166
    {
167
        $count = 0;
168
        foreach ($files as $file) {
169
            if ($this->zip->deleteName($file) === false)
170
                throw new Exception($this->zip->getStatusString(), $this->zip->status);
171
            $count++;
172
        }
173
174
        // reopen archive to save changes
175
        $archive_filename = $this->zip->filename;
176
        $this->zip->close();
177
        $this->open($archive_filename);
178
179
        return $count;
180
    }
181
182
    /**
183
     * @param array $files
184
     *
185
     * @return int
186
     * @throws \Exception
187
     */
188
    public function addFiles(array $files)
189
    {
190
        $added_files = 0;
191
        foreach ($files as $localName => $fileName) {
192
            if (is_null($fileName)) {
193
                if ($this->zip->addEmptyDir($localName) === false)
194
                    throw new Exception($this->zip->getStatusString(), $this->zip->status);
195
            } else {
196
                if ($this->zip->addFile($fileName, $localName) === false)
197
                    throw new Exception($this->zip->getStatusString(), $this->zip->status);
198
                $added_files++;
199
            }
200
        }
201
202
        // reopen archive to save changes
203
        $archive_filename = $this->zip->filename;
204
        $this->zip->close();
205
        $this->open($archive_filename);
206
207
        return $added_files;
208
    }
209
210
    /**
211
     * @param array  $files
212
     * @param string $archiveFileName
213
     *
214
     * @return false|int
215
     * @throws \Exception
216
     */
217
    public static function createArchive(array $files, $archiveFileName){
218
        $zip = new ZipArchive();
219
        $result = $zip->open($archiveFileName, ZipArchive::CREATE);
220
        if ($result !== true)
221
            throw new Exception('ZipArchive error: '.$result);
222
        foreach ($files as $localName => $fileName) {
223
            if ($fileName === null) {
224
                if ($zip->addEmptyDir($localName) === false)
225
                    return false;
226
            } else {
227
                if ($zip->addFile($fileName, $localName) === false)
228
                    return false;
229
            }
230
        }
231
        $zip->close();
232
233
        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
    public static function canAddFiles()
248
    {
249
        return true;
250
    }
251
252
    /**
253
     * @return bool
254
     */
255
    public static function canDeleteFiles()
256
    {
257
        return true;
258
    }
259
}