Passed
Push — master ( 3fb6e3...48681f )
by f
41:38 queued 26:41
created

Formats   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 320
Duplicated Lines 0 %

Test Coverage

Coverage 56.29%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 150
dl 0
loc 320
ccs 67
cts 119
cp 0.5629
rs 5.04
c 4
b 1
f 0
wmc 57

15 Methods

Rating   Name   Duplication   Size   Complexity  
A canEncrypt() 0 3 1
A canStream() 0 3 1
A canOpen() 0 3 1
A canCreate() 0 3 1
A canUpdate() 0 3 1
A canAppend() 0 3 1
D detectArchiveFormat() 0 72 31
A getAllPossibleFormatsAndDrivers() 0 10 4
A checkFormatSupportAbility() 0 10 3
A getDeclaredDriverFormats() 0 4 1
A flatArrayToInt() 0 7 2
A getFormatDriver() 0 10 3
A getFormatMimeType() 0 3 1
A getFormatSupportStatus() 0 13 4
A getSupportedDriverFormats() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like Formats often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Formats, and based on these observations, apply Extract Interface, too.

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\NelexaZip;
9
use wapmorgan\UnifiedArchive\Drivers\OneFile\Bzip;
10
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...
11
use wapmorgan\UnifiedArchive\Drivers\OneFile\Lzma;
12
use wapmorgan\UnifiedArchive\Drivers\Rar;
13
use wapmorgan\UnifiedArchive\Drivers\SevenZip;
14
use wapmorgan\UnifiedArchive\Drivers\TarByPear;
15
use wapmorgan\UnifiedArchive\Drivers\TarByPhar;
16
use wapmorgan\UnifiedArchive\Drivers\Zip;
17
use wapmorgan\UnifiedArchive\Exceptions\UnsupportedArchiveException;
18
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...
19
20
class Formats
21
{
22
    // archived and compressed
23
    const ZIP = 'zip';
24
    const SEVEN_ZIP = '7z';
25
    const RAR = 'rar';
26
    const CAB = 'cab';
27
    const TAR = 'tar';
28
    const TAR_GZIP = 'tgz';
29
    const TAR_BZIP = 'tbz2';
30
    const TAR_LZMA = 'txz';
31
    const TAR_LZW = 'tar.z';
32
    const ARJ = 'arj';
33
34
    // compressed
35
    const GZIP = 'gz';
36
    const BZIP = 'bz2';
37
    const LZMA = 'xz';
38
39
    // non-usual archives
40
    const UEFI = 'uefi';
41
    const GPT = 'gpt';
42
    const MBR = 'mbr';
43
    const MSI = 'msi';
44
    const ISO = 'iso';
45
    const DMG = 'dmg';
46
    const UDF = 'udf';
47
    const RPM = 'rpm';
48
    const DEB = 'deb';
49
50
    /**
51
     * @var string[] List of archive format drivers
52
     */
53
    public static $drivers = [
54
        Zip::class,
55
        Rar::class,
56
        Gzip::class,
57
        Bzip::class,
58
        Lzma::class,
59
        TarByPhar::class,
60
        SevenZip::class,
61
        AlchemyZippy::class,
62
        NelexaZip::class,
63
        TarByPear::class,
64
        Iso::class,
65
        Cab::class,
66
    ];
67
68
    /** @var array<string, array<string>> List of all available types with their drivers */
69
    protected static $declaredDriversFormats;
70
71
    /** @var array List of all drivers with formats and support-state */
72
    protected static $supportedDriversFormats;
73
74
    protected static $mimeTypes = [
75
        'application/zip' => Formats::ZIP,
76
        'application/x-7z-compressed' => Formats::SEVEN_ZIP,
77
        'application/x-rar' => Formats::RAR,
78
        'application/zlib' => Formats::GZIP,
79
        'application/gzip'  => Formats::GZIP,
80
        'application/x-gzip' => Formats::GZIP,
81
        'application/x-bzip2' => Formats::BZIP,
82
        'application/x-lzma' => Formats::LZMA,
83
        'application/x-iso9660-image' => Formats::ISO,
84
        'application/vnd.ms-cab-compressed' => Formats::CAB,
85
        'application/x-tar' => Formats::TAR,
86
        'application/x-gtar' => Formats::TAR_GZIP,
87
    ];
88
89
    /**
90
     * Detect archive type by its filename or content
91
     *
92
     * @param string $fileName Archive filename
93
     * @param bool $contentCheck Whether archive type can be detected by content
94 36
     * @return string|bool One of UnifiedArchive type constants OR false if type is not detected
95
     */
96
    public static function detectArchiveFormat($fileName, $contentCheck = true)
97 36
    {
98
        // by file name
99 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

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