Passed
Push — master ( ee136d...e867c3 )
by f
21:14 queued 06:17
created

TarByPear::checkFormatSupport()   B

Complexity

Conditions 10
Paths 10

Size

Total Lines 18
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 10
eloc 12
c 1
b 0
f 0
nc 10
nop 1
dl 0
loc 18
rs 7.6666

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

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

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