Passed
Push — master ( ae0184...ccf027 )
by f
13:17
created

Formats::detectArchiveFormat()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 26.0012

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 8
eloc 16
nc 12
nop 2
dl 0
loc 29
ccs 10
cts 29
cp 0.3448
crap 26.0012
rs 8.4444
c 3
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\NelexaZip;
9
use wapmorgan\UnifiedArchive\Drivers\OneFile\Bzip;
10
use wapmorgan\UnifiedArchive\Drivers\OneFile\Gzip;
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\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
        TarByPhar::class,
59
        SevenZip::class,
60
        AlchemyZippy::class,
61
        NelexaZip::class,
62
        TarByPear::class,
63
        Iso::class,
64
        Cab::class,
65
    ];
66
67
    /** @var array<string, array<string>> List of all available types with their drivers */
68
    protected static $declaredDriversFormats;
69
70
    /** @var array List of all drivers with formats and support-state */
71
    protected static $supportedDriversFormats;
72
73
    protected static $oneLevelExtensions = [
74
        'zip' => Formats::ZIP,
75
        'jar' => Formats::ZIP,
76
        '7z' => Formats::SEVEN_ZIP,
77
        'rar' => Formats::RAR,
78
        'gz' => Formats::GZIP,
79
        'bz2' => Formats::BZIP,
80
        'xz' => Formats::LZMA,
81
        'iso' => Formats::ISO,
82
        'cab' => Formats::CAB,
83
        'tar' => Formats::TAR,
84
        'tgz' => Formats::TAR_GZIP,
85
        'tbz2' => Formats::TAR_BZIP,
86
        'txz' => Formats::TAR_LZMA,
87
        'arj' => Formats::ARJ,
88
        'efi' => Formats::UEFI,
89
        'gpt' => Formats::GPT,
90
        'mbr' => Formats::MBR,
91
        'msi' => Formats::MSI,
92
        'dmg' => Formats::DMG,
93
        'rpm' => Formats::RPM,
94 36
        'deb' => Formats::DEB,
95
        'udf' => Formats::UDF,
96
    ];
97 36
98
    protected static $twoLevelExtensions = [
99 36
        'tar.gz' => Formats::TAR_GZIP,
100 12
        'tar.bz2' => Formats::TAR_BZIP,
101 12
        'tar.xz' => Formats::TAR_LZMA,
102 4
        'tar.z' => Formats::TAR_LZW,
103 8
    ];
104 4
105 4
    protected static $mimeTypes = [
106 4
        'application/zip' => Formats::ZIP,
107
        'application/x-7z-compressed' => Formats::SEVEN_ZIP,
108
        'application/x-rar' => Formats::RAR,
109
        'application/zlib' => Formats::GZIP,
110
        'application/gzip'  => Formats::GZIP,
111
        'application/x-gzip' => Formats::GZIP,
112
        'application/x-bzip2' => Formats::BZIP,
113 24
        'application/x-lzma' => Formats::LZMA,
114 18
        'application/x-iso9660-image' => Formats::ISO,
115 6
        'application/vnd.ms-cab-compressed' => Formats::CAB,
116 18
        'application/x-tar' => Formats::TAR,
117 4
        'application/x-gtar' => Formats::TAR_GZIP,
118 14
    ];
119 1
120 13
    /**
121
     * Detect archive type by its filename or content
122 13
     *
123
     * @param string $fileName Archive filename
124 13
     * @param bool $contentCheck Whether archive type can be detected by content
125
     * @return string|bool One of UnifiedArchive type constants OR false if type is not detected
126 13
     */
127 4
    public static function detectArchiveFormat($fileName, $contentCheck = true)
128 9
    {
129
        $fileName = strtolower($fileName);
130 9
131 6
        // by file name
132 3
        $ld_offset = strrpos($fileName, '.');
133 1
        if ($ld_offset !== false) {
134 2
            $ext = substr($fileName, $ld_offset + 1);
135 1
            $sld_offset = strrpos($fileName, '.', - (strlen($ext) + 1));
136 1
            if ($sld_offset !== false) {
137 1
                $complex_ext = substr($fileName, $sld_offset + 1);
138
                if (isset(static::$twoLevelExtensions[$complex_ext])) {
139
                    return static::$twoLevelExtensions[$complex_ext];
140
                }
141
            }
142
            if (isset(static::$oneLevelExtensions[$ext])) {
143
                return static::$oneLevelExtensions[$ext];
144
            }
145
        }
146
147
        // by file content
148
        if ($contentCheck && function_exists('mime_content_type')) {
149
            $mime_type = mime_content_type($fileName);
150
            if (isset(static::$mimeTypes[$mime_type])) {
151
                return static::$mimeTypes[$mime_type];
152
            }
153
        }
154
155
        return false;
156
    }
157
158
    /**
159
     * Checks whether specific archive type can be opened with current system configuration
160
     *
161
     * @param string $format One of predefined archive types (class constants)
162
     * @return bool
163
     */
164
    public static function canOpen($format)
165
    {
166
        return static::checkFormatSupportAbility($format, BasicDriver::OPEN);
167
    }
168
169
    /**
170
     * Checks whether specified archive can be streamed
171
     *
172
     * @param string $format One of predefined archive types (class constants)
173
     * @return bool
174 25
     */
175
    public static function canStream($format)
176 25
    {
177
        return static::checkFormatSupportAbility($format, BasicDriver::STREAM_CONTENT);
178 25
    }
179 6
180
    /**
181 6
     * Checks whether specified archive can be created
182 6
     *
183
     * @param string $format One of predefined archive types (class constants)
184 6
     * @return bool
185
     */
186
    public static function canCreate($format)
187
    {
188 25
        return static::checkFormatSupportAbility($format, BasicDriver::CREATE);
189
    }
190
191
    /**
192
     * Checks whether specified archive can be created
193
     *
194
     * @param string $format One of predefined archive types (class constants)
195
     * @return bool
196
     */
197
    public static function canAppend($format)
198
    {
199
        return static::checkFormatSupportAbility($format, BasicDriver::APPEND);
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 canUpdate($format)
209
    {
210 2
        return static::checkFormatSupportAbility($format, BasicDriver::DELETE);
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 canEncrypt($format)
220
    {
221 2
        return static::checkFormatSupportAbility($format, BasicDriver::CREATE_ENCRYPTED);
222
    }
223
224
    /**
225
     * @param $format
226
     * @return void
227
     */
228
    protected static function getFormatSupportStatus($format)
229
    {
230 2
        static::getAllPossibleFormatsAndDrivers();
231
232 2
        if (!isset(static::$supportedDriversFormats[$format])) {
233
            static::$supportedDriversFormats[$format] = [];
234
235
            if (!isset(static::$declaredDriversFormats[$format])) {
236
                return;
237
            }
238
            /** @var BasicDriver $format_driver */
239
            foreach (static::$declaredDriversFormats[$format] as $format_driver) {
240
                static::$supportedDriversFormats[$format][$format_driver] = $format_driver::checkFormatSupport($format);
241
            }
242
        }
243
    }
244
245
    /**
246
     * @param string $format
247
     * @param string $ability
248
     * @return bool
249
     */
250
    public static function checkFormatSupportAbility($format, $ability)
251 4
    {
252
        self::getFormatSupportStatus($format);
253 4
        foreach (static::$supportedDriversFormats[$format] as $driver => $driver_abilities) {
254 4
            if (in_array($ability, $driver_abilities, true)) {
255
                return true;
256
            }
257 4
        }
258 4
259 4
        return false;
260
    }
261
262
    /**
263
     * @param string $format
264
     * @param int[] $abilities
265
     * @return int|string|null
266
     */
267
    public static function getFormatDriver($format, array $abilities = [])
268
    {
269
        self::getFormatSupportStatus($format);
270 25
        foreach (static::$supportedDriversFormats[$format] as $driver => $driver_abilities) {
271
            if (count(array_intersect($driver_abilities, $abilities)) === count($abilities)) {
272 25
                return $driver;
273
            }
274 25
        }
275
276
        return null;
277 25
    }
278 23
279
    /**
280 2
     * @param string $archiveFormat
281 2
     * @return int|string|null
282 2
     */
283
    public static function getFormatExtension($archiveFormat)
284
    {
285
        $complex_ext = array_search($archiveFormat, static::$twoLevelExtensions);
286
        if ($complex_ext !== false) {
287
            return $complex_ext;
288
        }
289
        $ext = array_search($archiveFormat, static::$oneLevelExtensions);
290
        if ($ext !== false) {
291
            return $ext;
292
        }
293
        return null;
294
    }
295
296
    /**
297
     * @param $format
298
     * @return false|int|string
299
     */
300
    public static function getFormatMimeType($format)
301
    {
302
        return array_search($format, static::$mimeTypes, true);
303
    }
304
305
    public static function getDeclaredDriverFormats()
306
    {
307
        static::getAllPossibleFormatsAndDrivers();
308
        return static::$declaredDriversFormats;
309
    }
310
311
    public static function getSupportedDriverFormats()
312
    {
313
        foreach (self::getDeclaredDriverFormats() as $format => $formatDrivers) {
314
            self::getFormatSupportStatus($format);
315
        }
316
        return static::$supportedDriversFormats;
317
    }
318
319
    /**
320
     * Tests system configuration
321
     */
322
    protected static function getAllPossibleFormatsAndDrivers()
323 25
    {
324
        if (static::$declaredDriversFormats === null) {
0 ignored issues
show
introduced by
The condition static::declaredDriversFormats === null is always false.
Loading history...
325 25
            static::$declaredDriversFormats = [];
326 1
            foreach (static::$drivers as $handlerClass)
327 1
            {
328
                $handler_formats = $handlerClass::getSupportedFormats();
329 1
                foreach ($handler_formats as $handler_format)
330 1
                {
331
                    static::$declaredDriversFormats[$handler_format][] = $handlerClass;
332 1
                }
333
            }
334
        }
335
    }
336
}
337