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

TarByPear::checkFormatSupport()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 10.4632

Importance

Changes 0
Metric Value
eloc 12
c 0
b 0
f 0
dl 0
loc 18
ccs 10
cts 12
cp 0.8333
rs 7.6666
cc 10
nc 10
nop 1
crap 10.4632

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
namespace wapmorgan\UnifiedArchive\Drivers;
3
4
use Archive_Tar;
0 ignored issues
show
Bug introduced by
The type Archive_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...
5
use wapmorgan\UnifiedArchive\ArchiveEntry;
6
use wapmorgan\UnifiedArchive\ArchiveInformation;
7
use wapmorgan\UnifiedArchive\Drivers\BasicDriver;
8
use wapmorgan\UnifiedArchive\Exceptions\ArchiveCreationException;
9
use wapmorgan\UnifiedArchive\Exceptions\ArchiveExtractionException;
10
use wapmorgan\UnifiedArchive\Exceptions\ArchiveModificationException;
11
use wapmorgan\UnifiedArchive\Exceptions\NonExistentArchiveFileException;
12
use wapmorgan\UnifiedArchive\Exceptions\UnsupportedOperationException;
13
use wapmorgan\UnifiedArchive\Formats;
14
use wapmorgan\UnifiedArchive\LzwStreamWrapper;
15
16
class TarByPear extends BasicDriver
17
{
18
    /**
19
     * @var string Full path to archive
20
     */
21
    protected $archiveFileName;
22
23
    /**
24
     * @var Archive_Tar
25
     */
26
    protected $tar;
27
28
    /**
29
     * @var float Overall compression ratio of Tar archive when Archive_Tar is used
30
     */
31
    protected $pearCompressionRatio;
32
33
    /**
34
     * @var array<string, integer> List of files and their index in listContent() result
35
     */
36
    protected $pearFilesIndex;
37
38
    /**
39
     * @return array
40
     */
41 1
    public static function getSupportedFormats()
42
    {
43
        return [
44 1
            Formats::TAR,
45
            Formats::TAR_GZIP,
46
            Formats::TAR_BZIP,
47
            Formats::TAR_LZMA,
48
            Formats::TAR_LZW,
49
        ];
50
    }
51
52
    /**
53
     * @param $format
54
     * @return bool
55
     * @throws \Exception
56
     */
57 4
    public static function checkFormatSupport($format)
58
    {
59 4
        $availability = class_exists('\Archive_Tar');
60
        switch ($format) {
61 4
            case Formats::TAR:
62 1
                return $availability;
63
64 3
            case Formats::TAR_GZIP:
65 1
                return $availability && extension_loaded('zlib');
66
67 2
            case Formats::TAR_BZIP:
68 1
                return $availability && extension_loaded('bz2');
69
70 1
            case Formats::TAR_LZMA:
71 1
                return $availability && extension_loaded('xz');
72
73
            case Formats::TAR_LZW:
74
                return $availability && LzwStreamWrapper::isBinaryAvailable();
75
        }
76
    }
77
78
    /**
79
     * @inheritDoc
80
     */
81
    public static function getDescription()
82
    {
83
        return 'php-library for tar';
84
    }
85
86
    /**
87
     * @inheritDoc
88
     */
89
    public static function getInstallationInstruction()
90
    {
91
        return 'install library `pear/archive_tar` and optionally php-extensions (zlib, bzip2)';
92
    }
93
94
    /**
95
     * @param array $files
96
     * @param string $archiveFileName
97
     * @param int $compressionLevel
98
     * @param null $password
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $password is correct as it would always require null to be passed?
Loading history...
99
     * @return int
100
     * @throws ArchiveCreationException
101
     * @throws UnsupportedOperationException
102
     */
103
    public static function createArchive(array $files, $archiveFileName, $compressionLevel = self::COMPRESSION_AVERAGE, $password = null)
104
    {
105
        if ($password !== null) {
0 ignored issues
show
introduced by
The condition $password !== null is always false.
Loading history...
106
            throw new UnsupportedOperationException('One-file format ('.__CLASS__.') could not encrypt an archive');
107
        }
108
109
        $compression = null;
110
        switch (strtolower(pathinfo($archiveFileName, PATHINFO_EXTENSION))) {
0 ignored issues
show
Bug introduced by
It seems like pathinfo($archiveFileNam...ers\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

110
        switch (strtolower(/** @scrutinizer ignore-type */ pathinfo($archiveFileName, PATHINFO_EXTENSION))) {
Loading history...
111
            case 'gz':
112
            case 'tgz':
113
                $compression = 'gz';
114
                break;
115
            case 'bz2':
116
            case 'tbz2':
117
                $compression = 'bz2';
118
                break;
119
            case 'xz':
120
                $compression = 'lzma2';
121
                break;
122
            case 'z':
123
                $tar_aname = 'compress.lzw://' . $archiveFileName;
124
                break;
125
        }
126
127
        if (isset($tar_aname))
128
            $tar = new Archive_Tar($tar_aname, $compression);
129
        else
130
            $tar = new Archive_Tar($archiveFileName, $compression);
131
132
        foreach ($files  as $localName => $filename) {
133
            $remove_dir = dirname($filename);
134
            $add_dir = dirname($localName);
135
136
            if (is_null($filename)) {
137
                if ($tar->addString($localName, '') === false)
138
                    throw new ArchiveCreationException('Error when adding directory '.$localName.' to archive');
139
            } else {
140
                if ($tar->addModify($filename, $add_dir, $remove_dir) === false)
141
                    throw new ArchiveCreationException('Error when adding file '.$filename.' to archive');
142
            }
143
        }
144
        $tar = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $tar is dead and can be removed.
Loading history...
145
146
        return count($files);
147
    }
148
149
    /**
150
     * @inheritDoc
151
     */
152 3
    public function __construct($archiveFileName, $format, $password = null)
153
    {
154 3
        $this->archiveFileName = realpath($archiveFileName);
155 3
        $this->open($format);
156 3
    }
157
158 3
    protected function open($archiveType)
159
    {
160
        switch ($archiveType) {
161 3
            case Formats::TAR_GZIP:
162
                $this->tar = new Archive_Tar($this->archiveFileName, 'gz');
163
                break;
164
165 3
            case Formats::TAR_BZIP:
166
                $this->tar = new Archive_Tar($this->archiveFileName, 'bz2');
167
                break;
168
169 3
            case Formats::TAR_LZMA:
170 3
                $this->tar = new Archive_Tar($this->archiveFileName, 'lzma2');
171 3
                break;
172
173
            case Formats::TAR_LZW:
174
                LzwStreamWrapper::registerWrapper();
175
                $this->tar = new Archive_Tar('compress.lzw://' . $this->archiveFileName);
176
                break;
177
178
            default:
179
                $this->tar = new Archive_Tar($this->archiveFileName);
180
                break;
181
        }
182 3
    }
183
184
    /**
185
     * @inheritDoc
186
     */
187 3
    public function getArchiveInformation()
188
    {
189 3
        $information = new ArchiveInformation();
190 3
        $this->pearFilesIndex = [];
191
192 3
        foreach ($this->tar->listContent() as $i => $file) {
193
            // BUG workaround: http://pear.php.net/bugs/bug.php?id=20275
194 3
            if ($file['filename'] === 'pax_global_header') {
195
                continue;
196
            }
197
            // skip directories
198 3
            if ($file['typeflag'] == '5' || substr($file['filename'], -1) === '/')
199 3
                continue;
200 3
            $information->files[] = $file['filename'];
201 3
            $information->uncompressedFilesSize += $file['size'];
202 3
            $this->pearFilesIndex[$file['filename']] = $i;
203
        }
204
205 3
        $information->compressedFilesSize = filesize($this->archiveFileName);
206 3
        $this->pearCompressionRatio = $information->uncompressedFilesSize != 0
207 3
            ? ceil($information->compressedFilesSize / $information->uncompressedFilesSize)
208
            : 1;
209 3
        return $information;
210
    }
211
212
    /**
213
     * @inheritDoc
214
     */
215
    public function getFileNames()
216
    {
217
        $files = [];
218
219
        $Content = $this->tar->listContent();
220
        foreach ($Content as $i => $file) {
221
            // BUG workaround: http://pear.php.net/bugs/bug.php?id=20275
222
            if ($file['filename'] === 'pax_global_header') {
223
                continue;
224
            }
225
            $files[] = $file['filename'];
226
        }
227
228
        return $files;
229
    }
230
231
    /**
232
     * @inheritDoc
233
     */
234
    public function isFileExists($fileName)
235
    {
236
        return isset($this->pearFilesIndex[$fileName]);
237
    }
238
239
    /**
240
     * @inheritDoc
241
     */
242 1
    public function getFileData($fileName)
243
    {
244 1
        if (!isset($this->pearFilesIndex[$fileName]))
245
            throw new NonExistentArchiveFileException('File '.$fileName.' is not found in archive files list');
246
247 1
        $index = $this->pearFilesIndex[$fileName];
248
249 1
        $files_list = $this->tar->listContent();
250 1
        if (!isset($files_list[$index]))
251
            throw new NonExistentArchiveFileException('File '.$fileName.' is not found in Tar archive');
252
253 1
        $data = $files_list[$index];
254 1
        unset($files_list);
255
256 1
        return new ArchiveEntry($fileName, $data['size'] / $this->pearCompressionRatio,
257 1
            $data['size'], $data['mtime'], in_array(strtolower(pathinfo($this->archiveFileName,
0 ignored issues
show
Bug introduced by
It seems like pathinfo($this->archiveF...ers\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

257
            $data['size'], $data['mtime'], in_array(strtolower(/** @scrutinizer ignore-type */ pathinfo($this->archiveFileName,
Loading history...
258 1
                PATHINFO_EXTENSION)), ['gz', 'bz2', 'xz', 'Z']));
259
    }
260
261
    /**
262
     * @inheritDoc
263
     */
264 1
    public function getFileContent($fileName)
265
    {
266 1
        if (!isset($this->pearFilesIndex[$fileName]))
267
            throw new NonExistentArchiveFileException('File '.$fileName.' is not found in archive files list');
268
269 1
        return $this->tar->extractInString($fileName);
270
    }
271
272
    /**
273
     * @inheritDoc
274
     */
275 1
    public function getFileStream($fileName)
276
    {
277 1
        if (!isset($this->pearFilesIndex[$fileName]))
278
            throw new NonExistentArchiveFileException('File '.$fileName.' is not found in archive files list');
279
280 1
        return self::wrapStringInStream($this->tar->extractInString($fileName));
281
    }
282
283
    /**
284
     * @inheritDoc
285
     */
286
    public function extractFiles($outputFolder, array $files)
287
    {
288
        $result = $this->tar->extractList($files, $outputFolder);
289
        if ($result === false) {
290
            throw new ArchiveExtractionException('Error when extracting from '.$this->archiveFileName);
291
        }
292
293
        return count($files);
294
    }
295
296
    /**
297
     * @inheritDoc
298
     */
299
    public function extractArchive($outputFolder)
300
    {
301
        $result = $this->tar->extract($outputFolder);
302
        if ($result === false) {
303
            throw new ArchiveExtractionException('Error when extracting from '.$this->archiveFileName);
304
        }
305
306
        return 1;
307
    }
308
309
    /**
310
     * @inheritDoc
311
     */
312
    public function addFiles(array $files)
313
    {
314
        $added = 0;
315
        foreach ($files as $localName => $filename) {
316
            $remove_dir = dirname($filename);
317
            $add_dir = dirname($localName);
318
            if (is_null($filename)) {
319
                if ($this->tar->addString($localName, "") === false) {
320
                    throw new ArchiveModificationException('Could not add directory "'.$filename.'": '.$this->tar->error_object->message, $this->tar->error_object->code);
321
                }
322
            } else {
323
                if ($this->tar->addModify($filename, $add_dir, $remove_dir) === false) {
324
                    throw new ArchiveModificationException('Could not add file "'.$filename.'": '.$this->tar->error_object->message, $this->tar->error_object->code);
325
                }
326
                $added++;
327
            }
328
        }
329
        return $added;
330
    }
331
332
    public static function canCreateArchive($format)
333
    {
334
        return true;
335
    }
336
337
    /**
338
     * @param $format
339
     * @return bool
340
     */
341
    public static function canAddFiles($format)
342
    {
343
        return true;
344
    }
345
346
    /**
347
     * @param string $inArchiveName
348
     * @param string $content
349
     * @return bool|true
350
     */
351
    public function addFileFromString($inArchiveName, $content)
352
    {
353
        return $this->tar->addString($inArchiveName, $content);
354
    }
355
}