Passed
Push — 1.1.x ( 3d3019...6d4a67 )
by f
02:55 queued 01:04
created

Formats::getFormatDriver()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 5.2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 5
nop 2
dl 0
loc 15
ccs 8
cts 10
cp 0.8
crap 5.2
rs 9.6111
1
<?php
2
namespace wapmorgan\UnifiedArchive;
3
4
use wapmorgan\UnifiedArchive\Drivers\AlchemyZippy;
5
use wapmorgan\UnifiedArchive\Drivers\BasicDriver;
6
use wapmorgan\UnifiedArchive\Drivers\Cab;
7
use wapmorgan\UnifiedArchive\Drivers\Iso;
8
use wapmorgan\UnifiedArchive\Drivers\OneFile\Bzip;
9
use wapmorgan\UnifiedArchive\Drivers\OneFile\Gzip;
0 ignored issues
show
Bug introduced by
The type wapmorgan\UnifiedArchive\Drivers\OneFile\Gzip was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use wapmorgan\UnifiedArchive\Drivers\OneFile\Lzma;
11
use wapmorgan\UnifiedArchive\Drivers\Rar;
12
use wapmorgan\UnifiedArchive\Drivers\SevenZip;
13
use wapmorgan\UnifiedArchive\Drivers\TarByPear;
14
use wapmorgan\UnifiedArchive\Drivers\TarByPhar;
15
use wapmorgan\UnifiedArchive\Drivers\Zip;
16
use wapmorgan\UnifiedArchive\Exceptions\UnsupportedArchiveException;
17
use wapmorgan\UnifiedArchive\Formats\Tar;
0 ignored issues
show
Bug introduced by
The type wapmorgan\UnifiedArchive\Formats\Tar was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
19
class Formats
20
{
21
    // archived and compressed
22
    const ZIP = 'zip';
23
    const SEVEN_ZIP = '7z';
24
    const RAR = 'rar';
25
    const CAB = 'cab';
26
    const TAR = 'tar';
27
    const TAR_GZIP = 'tgz';
28
    const TAR_BZIP = 'tbz2';
29
    const TAR_LZMA = 'txz';
30
    const TAR_LZW = 'tar.z';
31
    const ARJ = 'arj';
32
33
    // compressed
34
    const GZIP = 'gz';
35
    const BZIP = 'bz2';
36
    const LZMA = 'xz';
37
38
    // non-usual archives
39
    const UEFI = 'uefi';
40
    const GPT = 'gpt';
41
    const MBR = 'mbr';
42
    const MSI = 'msi';
43
    const ISO = 'iso';
44
    const DMG = 'dmg';
45
    const UDF = 'udf';
46
    const RPM = 'rpm';
47
    const DEB = 'deb';
48
49
    /**
50
     * @var string[] List of archive format drivers
51
     */
52
    public static $drivers = [
53
        Zip::class,
54
        Rar::class,
55
        Gzip::class,
56
        Bzip::class,
57
        Lzma::class,
58
        Iso::class,
59
        Cab::class,
60
        TarByPhar::class,
61
        SevenZip::class,
62
        AlchemyZippy::class,
63
        TarByPear::class,
64
    ];
65
66
    /** @var array<string, array<string>> List of all available types with their drivers */
67
    protected static $availableFormats;
68
69
    /** @var array List of all drivers with formats and support-state */
70
    protected static $formatsSupport;
71
72
    protected static $mimeTypes = [
73
        'application/zip' => Formats::ZIP,
74
        'application/x-7z-compressed' => Formats::SEVEN_ZIP,
75
        'application/x-rar' => Formats::RAR,
76
        'application/zlib' => Formats::GZIP,
77
        'application/gzip'  => Formats::GZIP,
78
        'application/x-gzip' => Formats::GZIP,
79
        'application/x-bzip2' => Formats::BZIP,
80
        'application/x-lzma' => Formats::LZMA,
81
        'application/x-iso9660-image' => Formats::ISO,
82
        'application/vnd.ms-cab-compressed' => Formats::CAB,
83
        'application/x-tar' => Formats::TAR,
84
        'application/x-gtar' => Formats::TAR_GZIP,
85
    ];
86
87
    /**
88
     * Detect archive type by its filename or content
89
     *
90
     * @param string $fileName Archive filename
91
     * @param bool $contentCheck Whether archive type can be detected by content
92
     * @return string|bool One of UnifiedArchive type constants OR false if type is not detected
93
     */
94 36
    public static function detectArchiveFormat($fileName, $contentCheck = true)
95
    {
96
        // by file name
97 36
        $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
0 ignored issues
show
Bug introduced by
It seems like pathinfo($fileName, wapm...ive\PATHINFO_EXTENSION) can also be of type array; however, parameter $string of strtolower() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

97
        $ext = strtolower(/** @scrutinizer ignore-type */ pathinfo($fileName, PATHINFO_EXTENSION));
Loading history...
98
99 36
        if (stripos($fileName, '.tar.') !== false && preg_match('~\.(?<ext>tar\.(gz|bz2|xz|z))$~', strtolower($fileName), $match)) {
100 12
            switch ($match['ext']) {
101 12
                case 'tar.gz':
102 4
                    return Formats::TAR_GZIP;
103 8
                case 'tar.bz2':
104 4
                    return Formats::TAR_BZIP;
105 4
                case 'tar.xz':
106 4
                    return Formats::TAR_LZMA;
107
                case 'tar.z':
108
                    return Formats::TAR_LZW;
109
            }
110
        }
111
112
        switch ($ext) {
113 24
            case 'zip':
114 18
            case 'jar':
115 6
                return Formats::ZIP;
116 18
            case '7z':
117 4
                return Formats::SEVEN_ZIP;
118 14
            case 'rar':
119 1
                return Formats::RAR;
120 13
            case 'gz':
121
                return Formats::GZIP;
122 13
            case 'bz2':
123
                return Formats::BZIP;
124 13
            case 'xz':
125
                return Formats::LZMA;
126 13
            case 'iso':
127 4
                return Formats::ISO;
128 9
            case 'cab':
129
                return Formats::CAB;
130 9
            case 'tar':
131 6
                return Formats::TAR;
132 3
            case 'tgz':
133 1
                return Formats::TAR_GZIP;
134 2
            case 'tbz2':
135 1
                return Formats::TAR_BZIP;
136 1
            case 'txz':
137 1
                return Formats::TAR_LZMA;
138
            case 'arj':
139
                return Formats::ARJ;
140
            case 'efi':
141
                return Formats::UEFI;
142
            case 'gpt':
143
                return Formats::GPT;
144
            case 'mbr':
145
                return Formats::MBR;
146
            case 'msi':
147
                return Formats::MSI;
148
            case 'dmg':
149
                return Formats::DMG;
150
            case 'rpm':
151
                return Formats::RPM;
152
            case 'deb':
153
                return Formats::DEB;
154
            case 'udf':
155
                return Formats::UDF;
156
        }
157
158
        // by file content
159
        if ($contentCheck) {
160
            $mime_type = mime_content_type($fileName);
161
            if (isset(static::$mimeTypes[$mime_type]))
162
                return static::$mimeTypes[$mime_type];
163
        }
164
165
        return false;
166
    }
167
168
    /**
169
     * Checks whether specific archive type can be opened with current system configuration
170
     *
171
     * @param string $format One of predefined archive types (class constants)
172
     * @return bool
173
     */
174 25
    public static function canOpen($format)
175
    {
176 25
        static::retrieveAllFormats();
177
178 25
        if (!isset(static::$formatsSupport[$format])) {
179 6
            static::$formatsSupport[$format] = [];
180
            /** @var BasicDriver $format_driver */
181 6
            foreach (static::$availableFormats[$format] as $format_driver) {
182 6
                if ($format_driver::checkFormatSupport($format))
183
                {
184 6
                    static::$formatsSupport[$format][] = $format_driver;
185
                }
186
            }
187
        }
188 25
        return !empty(static::$formatsSupport[$format]);
189
    }
190
191
    /**
192
     * Checks whether specified archive can be streamed
193
     *
194
     * @param string $format One of predefined archive types (class constants)
195
     * @return bool
196
     */
197
    public static function canStream($format)
198
    {
199
        return static::checkFormatSupport($format, 'canStream');
200
    }
201
202
    /**
203
     * Checks whether specified archive can be created
204
     *
205
     * @param string $format One of predefined archive types (class constants)
206
     * @return bool
207
     */
208 2
    public static function canCreate($format)
209
    {
210 2
        return static::checkFormatSupport($format, 'canCreateArchive');
211
    }
212
213
    /**
214
     * Checks whether specified archive can be created
215
     *
216
     * @param string $format One of predefined archive types (class constants)
217
     * @return bool
218
     */
219 2
    public static function canAppend($format)
220
    {
221 2
        return static::checkFormatSupport($format, 'canAddFiles');
222
    }
223
224
    /**
225
     * Checks whether specified archive can be created
226
     *
227
     * @param string $format One of predefined archive types (class constants)
228
     * @return bool
229
     */
230 2
    public static function canUpdate($format)
231
    {
232 2
        return static::checkFormatSupport($format, 'canDeleteFiles');
233
    }
234
235
    /**
236
     * Checks whether specified archive can be created
237
     *
238
     * @param string $format One of predefined archive types (class constants)
239
     * @return bool
240
     */
241
    public static function canEncrypt($format)
242
    {
243
        return static::checkFormatSupport($format, 'canEncrypt');
244
    }
245
246
    /**
247
     * @param string $format
248
     * @param string $function
249
     * @return bool
250
     */
251 4
    protected static function checkFormatSupport($format, $function)
252
    {
253 4
        static::retrieveAllFormats();
254 4
        if (!static::canOpen($format))
255
            return false;
256
257 4
        foreach (static::$formatsSupport[$format] as $driver) {
258 4
            if ($driver::$function($format))
259 4
                return true;
260
        }
261
262
        return false;
263
    }
264
265
    /**
266
     * @param string $format
267
     * @param bool $createAbility
268
     * @return mixed
269
     */
270 25
    public static function getFormatDriver($format, $createAbility = false)
271
    {
272 25
        static::retrieveAllFormats();
273
274 25
        if (!static::canOpen($format))
275
            throw new UnsupportedArchiveException('Unsupported archive type: '.$format.' of archive ');
276
277 25
        if (!$createAbility)
278 23
            return current(static::$formatsSupport[$format]);
279
280 2
        foreach (static::$formatsSupport[$format] as $driver) {
281 2
            if ($driver::canCreateArchive($format))
282 2
                return $driver;
283
        }
284
        return false;
285
    }
286
287
    /**
288
     * @param $format
289
     * @return false|int|string
290
     */
291
    public static function getFormatMimeType($format)
292
    {
293
        return array_search($format, static::$mimeTypes, true);
294
    }
295
296
    /**
297
     * @return array
298
     */
299
    public static function getFormatsReport()
300
    {
301
        static::retrieveAllFormats();
302
        $result = [];
303
304
        foreach (static::$availableFormats as $format => $formatDrivers) {
305
            $result[$format] = [
306
                'open' => static::canOpen($format),
307
                'stream' => static::canStream($format),
308
                'create' => static::canCreate($format),
309
                'append' => static::canAppend($format),
310
                'update' => static::canUpdate($format),
311
                'encrypt' => static::canEncrypt($format),
312
                'drivers' => static::$formatsSupport[$format],
313
            ];
314
        }
315
316
        return $result;
317
    }
318
319
    /**
320
     * Tests system configuration
321
     */
322 25
    protected static function retrieveAllFormats()
323
    {
324 25
        if (static::$availableFormats === null) {
0 ignored issues
show
introduced by
The condition static::availableFormats === null is always false.
Loading history...
325 1
            static::$availableFormats = [];
326 1
            foreach (Formats::$drivers as $handlerClass)
327
            {
328 1
                $handler_formats = $handlerClass::getSupportedFormats();
329 1
                foreach ($handler_formats as $handler_format)
330
                {
331 1
                    static::$availableFormats[$handler_format][] = $handlerClass;
332
                }
333
            }
334
        }
335
    }
336
}