Passed
Push — master ( bf29cf...6612ae )
by f
15:14
created

Formats::getFormatSupportStatus()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3.0416

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
nc 3
nop 1
dl 0
loc 9
ccs 5
cts 6
cp 0.8333
crap 3.0416
rs 10
c 1
b 0
f 0
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
    const OPEN = 1,
50
        OPEN_ENCRYPTED = 2,
51
        OPEN_VOLUMED = 4,
52
53
        GET_COMMENT = 64,
54
55
        EXTRACT_CONTENT = 128,
56
        STREAM_CONTENT = 256,
57
58
        APPEND = 4096,
59
        DELETE = 8192,
60
        SET_COMMENT = 16384,
61
62
        CREATE = 1048576,
63
        CREATE_ENCRYPTED = 2097152;
64
65
    /**
66
     * @var string[] List of archive format drivers
67
     */
68
    public static $drivers = [
69
        Zip::class,
70
        Rar::class,
71
        Gzip::class,
72
        Bzip::class,
73
        Lzma::class,
74
        TarByPhar::class,
75
        SevenZip::class,
76
        AlchemyZippy::class,
77
        TarByPear::class,
78
        Iso::class,
79
        Cab::class,
80
    ];
81
82
    /** @var array<string, array<string>> List of all available types with their drivers */
83
    protected static $declaredDriversFormats;
84
85
    /** @var array List of all drivers with formats and support-state */
86
    protected static $supportedDriversFormats;
87
88
    protected static $mimeTypes = [
89
        'application/zip' => Formats::ZIP,
90
        'application/x-7z-compressed' => Formats::SEVEN_ZIP,
91
        'application/x-rar' => Formats::RAR,
92
        'application/zlib' => Formats::GZIP,
93
        'application/gzip'  => Formats::GZIP,
94 36
        'application/x-gzip' => Formats::GZIP,
95
        'application/x-bzip2' => Formats::BZIP,
96
        'application/x-lzma' => Formats::LZMA,
97 36
        'application/x-iso9660-image' => Formats::ISO,
98
        'application/vnd.ms-cab-compressed' => Formats::CAB,
99 36
        'application/x-tar' => Formats::TAR,
100 12
        'application/x-gtar' => Formats::TAR_GZIP,
101 12
    ];
102 4
103 8
    /**
104 4
     * Detect archive type by its filename or content
105 4
     *
106 4
     * @param string $fileName Archive filename
107
     * @param bool $contentCheck Whether archive type can be detected by content
108
     * @return string|bool One of UnifiedArchive type constants OR false if type is not detected
109
     */
110
    public static function detectArchiveFormat($fileName, $contentCheck = true)
111
    {
112
        // by file name
113 24
        $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

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