Completed
Push — master ( 9f78cc...1a8c72 )
by Marco
14:57
created

ZipManager   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 331
Duplicated Lines 12.08 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 36
lcom 1
cbo 4
dl 40
loc 331
rs 9.52
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A count() 0 3 1
A addZip() 0 7 1
A removeZip() 0 11 2
A removeZipById() 0 9 2
A listZips() 9 9 1
A getZip() 0 8 2
A setPath() 0 12 3
A getPath() 9 9 1
A setMask() 0 12 3
A getMask() 9 9 1
A listFiles() 13 13 2
A extract() 0 22 5
A merge() 0 20 3
A add() 0 14 3
A delete() 0 14 3
A close() 0 12 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php namespace Comodojo\Zip;
2
3
use \Comodojo\Foundation\Utils\UniqueId;
4
use \Comodojo\Exception\ZipException;
5
use \Countable;
6
use \Exception;
7
8
/**
9
 * Multiple Comodojo\Zip\Zip manager
10
 *
11
 * @package     Comodojo Spare Parts
12
 * @author      Marco Giovinazzi <[email protected]>
13
 * @license     MIT
14
 *
15
 * LICENSE:
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
26
class ZipManager implements Countable {
27
28
    /**
29
     * Array of managed zip files
30
     *
31
     * @var array
32
     */
33
    private $zip_archives = [];
34
35
    /**
36
     * Count the number of Zip objects registered to the manager
37
     *
38
     * @return int
39
     */
40
    public function count(): int {
41
        return count($this->zip_archives);
42
    }
43
44
    /**
45
     * Add a Zip object to manager and return its id
46
     *
47
     * @param Zip $zip
48
     *
49
     * @return string
50
     */
51
    public function addZip(Zip $zip): string {
52
53
        $id = UniqueId::generate(32);
54
        $this->zip_archives[$id] = $zip;
55
        return $id;
56
57
    }
58
59
    /**
60
     * Remove a Zip object from manager
61
     *
62
     * @param Zip $zip
63
     *
64
     * @return bool
65
     * @throws ZipException
66
     */
67
    public function removeZip(Zip $zip): bool {
68
69
        $archive_key = array_search($zip, $this->zip_archives, true);
70
        if ( $archive_key === false ) {
71
            throw new ZipException("Archive not found");
72
        }
73
74
        unset($this->zip_archives[$archive_key]);
75
        return true;
76
77
    }
78
79
    /**
80
     * Remove a Zip object from manager by Zip id
81
     *
82
     * @param string $id
83
     *
84
     * @return bool
85
     * @throws ZipException
86
     */
87
    public function removeZipById(string $id): bool {
88
89
        if ( isset($this->zip_archives[$id]) === false ) {
90
            throw new ZipException("Archive: $id not found");
91
        }
92
        unset($this->zip_archives[$id]);
93
        return true;
94
95
    }
96
97
    /**
98
     * Get a list of all registered Zips filenames as an array
99
     *
100
     * @return array
101
     */
102 View Code Duplication
    public function listZips(): array {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
103
104
        return array_column(
105
            array_map(function($key, $archive) {
106
                return [ "key" => $key, "file" => $archive->getZipFile() ];
107
            }, array_keys($this->zip_archives), $this->zip_archives),
108
        "file", "key");
109
110
    }
111
112
    /**
113
     * Get a Zip object by Id
114
     *
115
     * @param string $id The zip id
116
     *
117
     * @return Zip
118
     * @throws ZipException
119
     */
120
    public function getZip(string $id): Zip {
121
122
        if ( array_key_exists($id, $this->zip_archives) === false ) {
123
            throw new ZipException("Archive id $id not found");
124
        }
125
        return $this->zip_archives[$id];
126
127
    }
128
129
    /**
130
     * Set current base path (to add relative files to zip archive)
131
     * for all Zips
132
     *
133
     * @param string $path
134
     *
135
     * @return ZipManager
136
     * @throws ZipException
137
     */
138
    public function setPath(string $path): ZipManager {
139
140
        try {
141
            foreach ( $this->zip_archives as $archive ) {
142
                $archive->setPath($path);
143
            }
144
            return $this;
145
        } catch (ZipException $ze) {
146
            throw $ze;
147
        }
148
149
    }
150
151
    /**
152
     * Get a list of paths used by Zips
153
     *
154
     * @return  array
155
     */
156 View Code Duplication
    public function getPath(): array {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
157
158
        return array_column(
159
            array_map(function($key, $archive) {
160
                return [ "key" => $key, "path" => $archive->getPath() ];
161
            }, array_keys($this->zip_archives), $this->zip_archives),
162
        "path", "key");
163
164
    }
165
166
    /**
167
     * Set default file mask for all Zips
168
     *
169
     * @param int $mask
170
     *
171
     * @return ZipManager
172
     * @throws ZipException
173
     */
174
    public function setMask(int $mask): ZipManager {
175
176
        try {
177
            foreach ( $this->zip_archives as $archive ) {
178
                $archive->setMask($mask);
179
            }
180
            return $this;
181
        } catch (ZipException $ze) {
182
            throw $ze;
183
        }
184
185
    }
186
187
    /**
188
     * Get a list of masks from Zips
189
     *
190
     * @return array
191
     */
192 View Code Duplication
    public function getMask(): array {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
194
        return array_column(
195
            array_map(function($key, $archive) {
196
                return [ "key" => $key, "mask" => $archive->getMask() ];
197
            }, array_keys($this->zip_archives), $this->zip_archives),
198
        "mask", "key");
199
200
    }
201
202
    /**
203
     * Get a list of files in Zips
204
     *
205
     * @return array
206
     * @throws ZipException
207
     */
208 View Code Duplication
    public function listFiles(): array {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
210
        try {
211
            return array_column(
212
                array_map(function($key, $archive) {
213
                    return [ "key" => $key, "files" => $archive->listFiles() ];
214
                }, array_keys($this->zip_archives), $this->zip_archives),
215
            "files", "key");
216
        } catch (ZipException $ze) {
217
            throw $ze;
218
        }
219
220
    }
221
222
    /**
223
     * Extract Zips to common destination
224
     *
225
     * @param string $destination Destination path
226
     * @param bool $separate (optional) If true (default), files will be placed in different directories
227
     * @param mixed $files (optional) a filename or an array of filenames
228
     *
229
     * @return bool
230
     * @throws ZipException
231
     */
232
    public function extract(
233
        string $destination,
234
        bool $separate = true,
235
        $files = null
236
    ): bool {
237
238
        try {
239
            foreach ( $this->zip_archives as $archive ) {
240
241
                $local_path = substr($destination, -1) == '/' ? $destination : $destination.'/';
242
                $local_file = pathinfo($archive->getZipFile());
243
                $local_destination = $separate ? ($local_path.$local_file['filename']) : $destination;
244
245
                $archive->extract($local_destination, $files);
246
247
            }
248
            return true;
249
        } catch (ZipException $ze) {
250
            throw $ze;
251
        }
252
253
    }
254
255
    /**
256
     * Merge multiple Zips into one
257
     *
258
     * @param string $output_zip_file
259
     *  Destination zip
260
     * @param bool $separate (optional)
261
     *  If true (default), files will be placed in different directories
262
     *
263
     * @return bool
264
     * @throws ZipException
265
     */
266
    public function merge(string $output_zip_file, bool $separate = true): bool {
267
268
        $pathinfo = pathinfo($output_zip_file);
269
        $temporary_folder = $pathinfo['dirname']."/".ManagerTools::getTemporaryFolder();
270
271
        try {
272
273
            $this->extract($temporary_folder, $separate);
274
            $zip = Zip::create($output_zip_file);
275
            $zip->add($temporary_folder, true)->close();
276
            ManagerTools::recursiveUnlink($temporary_folder);
277
            return true;
278
279
        } catch (ZipException $ze) {
280
            throw $ze;
281
        } catch (Exception $e) {
282
            throw $e;
283
        }
284
285
    }
286
287
    /**
288
     * Add a file to all registered Zips
289
     *
290
     * @param mixed $file_name_or_array
291
     *  The filename to add or an array of filenames
292
     * @param bool $flatten_root_folder
293
     *  (optional) If true, the Zip root folder will be flattened (default: false)
294
     *
295
     * @return ZipManager
296
     * @throws ZipException
297
     */
298
    public function add($file_name_or_array, bool $flatten_root_folder = false): ZipManager {
299
300
        try {
301
302
            foreach ( $this->zip_archives as $archive ) {
303
                $archive->add($file_name_or_array, $flatten_root_folder);
304
            }
305
            return $this;
306
307
        } catch (ZipException $ze) {
308
            throw $ze;
309
        }
310
311
    }
312
313
    /**
314
     * Delete a file from any registered Zip
315
     *
316
     * @param mixed $file_name_or_array
317
     *  The filename to add or an array of filenames
318
     *
319
     * @return ZipManager
320
     * @throws ZipException
321
     */
322
    public function delete($file_name_or_array): ZipManager {
323
324
        try {
325
326
            foreach ( $this->zip_archives as $archive ) {
327
                $archive->delete($file_name_or_array);
328
            }
329
            return $this;
330
331
        } catch (ZipException $ze) {
332
            throw $ze;
333
        }
334
335
    }
336
337
    /**
338
     * Close all Zips
339
     *
340
     * @return bool
341
     * @throws ZipException
342
     */
343
    public function close(): bool {
344
345
        try {
346
            foreach ( $this->zip_archives as $archive ) {
347
                $archive->close();
348
            }
349
            return true;
350
        } catch (ZipException $ze) {
351
            throw $ze;
352
        }
353
354
    }
355
356
}
357