Passed
Push — master ( 77631b...eb0eba )
by f
01:48
created

CamApplication::getTerminalWidth()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 17
rs 9.2222
c 0
b 0
f 0
cc 6
nc 5
nop 0
1
<?php
2
namespace wapmorgan\UnifiedArchive;
3
4
use Exception;
5
use wapmorgan\UnifiedArchive\Drivers\BasicDriver;
6
use wapmorgan\UnifiedArchive\UnifiedArchive;
7
8
class CamApplication {
9
    /**
10
     * @param $file
11
     * @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...
12
     * @return UnifiedArchive
13
     * @throws Exceptions\UnsupportedOperationException
14
     * @throws Exception
15
     */
16
    protected function open($file, $password = null)
17
    {
18
        if (!UnifiedArchive::canOpen($file))
19
            throw new Exception('Could not open archive '.$file.'. Try installing suggested packages or run `cam -f` to see formats support.');
20
21
        $archive = UnifiedArchive::open($file, $password);
22
        if ($archive === null)
23
            throw new Exception('Could not open archive '.$file);
24
25
        return $archive;
26
    }
27
28
    /**
29
     *
30
     */
31
    public function checkFormats()
32
    {
33
        echo "format\topen\tstream\tcreate\tappend\tupdate\tencrypt\tdrivers".PHP_EOL;
34
        foreach(Formats::getFormatsReport() as $format => $config) {
35
            echo $format."\t"
36
                .($config['open'] ? '+' : '-')."\t"
37
                .($config['stream'] ? '+' : '-')."\t"
38
                .($config['create'] ? '+' : '-')."\t"
39
                .($config['append'] ? '+' : '-')."\t"
40
                .($config['update'] ? '+' : '-')."\t"
41
                .($config['encrypt'] ? '+' : '-')."\t"
42
                .implode(', ', array_map(function($val) { return substr($val, strrpos($val, '\\') + 1); }, $config['drivers'])).PHP_EOL;
43
        }
44
    }
45
46
    public function checkDrivers()
47
    {
48
        $notInstalled = [];
49
50
        /** @var BasicDriver $driverClass */
51
        $i = 1;
52
        foreach (Formats::$drivers as $driverClass) {
53
            $description = $driverClass::getDescription();
54
            $install = $driverClass::getInstallationInstruction();
55
            if (!empty($install)) {
56
                $notInstalled[] = [$driverClass, $description, $install];
57
            } else {
58
                echo ($i++) . '. ' . $driverClass . ' - ' . $description . PHP_EOL;
59
            }
60
        }
61
62
        if (!empty($notInstalled)) {
63
            echo PHP_EOL.'Not installed:'.PHP_EOL;
64
            $i = 1;
65
            foreach ($notInstalled as $data) {
66
                echo ($i++) . '. ' . $data[0] . ' - ' . $data[1] . PHP_EOL
67
                    . '- ' . $data[2] . PHP_EOL.PHP_EOL;
68
            }
69
        }
70
    }
71
72
    /**
73
     * @param $args
74
     * @throws Exception
75
     * @throws \Archive7z\Exception
76
     */
77
    public function listArray($args)
78
    {
79
        $filter = isset($args['FILTER']) ? $args['FILTER'] : null;
80
        $archive = $this->open($args['ARCHIVE']);
81
        foreach ($archive->getFileNames($filter) as $file) {
82
            echo $file.PHP_EOL;
83
        }
84
    }
85
86
    /**
87
     * @param $args
88
     * @throws Exception
89
     * @throws \Archive7z\Exception
90
     */
91
    public function table($args)
92
    {
93
        $archive = $this->open($args['ARCHIVE']);
94
        $filter = isset($args['FILTER']) ? $args['FILTER'] : null;
95
96
        $width = $this->getTerminalWidth();
97
        $name_width = $width - 44;
98
99
        echo sprintf('%'.$name_width.'s | %8s | %8s | %-18s'.PHP_EOL, 'File name', '#Size', 'Size', 'Date');
100
        echo str_repeat('-', $width).PHP_EOL;
0 ignored issues
show
Bug introduced by
It seems like $width can also be of type string; however, parameter $times of str_repeat() does only seem to accept integer, 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

100
        echo str_repeat('-', /** @scrutinizer ignore-type */ $width).PHP_EOL;
Loading history...
101
        foreach ($archive->getFileNames($filter) as $file) {
102
            $info = $archive->getFileData($file);
103
            $file_name = strlen($file) > $name_width ? substr($file, 0, $name_width-2).'..' : $file;
104
            echo sprintf('%-'.$name_width.'s | %8s | %8s | %18s'.PHP_EOL,
105
                $file_name,
106
                implode(null, $this->formatSize($info->compressedSize, 3)),
0 ignored issues
show
Bug introduced by
null of type null is incompatible with the type string expected by parameter $glue of implode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

106
                implode(/** @scrutinizer ignore-type */ null, $this->formatSize($info->compressedSize, 3)),
Loading history...
107
                implode(null, $this->formatSize($info->uncompressedSize, 3)),
108
                $this->formatDate($info->modificationTime)
109
                );
110
        }
111
        $size = $this->formatSize($archive->getOriginalSize());
112
        $packed_size = $this->formatSize($archive->getCompressedSize());
113
        echo str_repeat('-', $width).PHP_EOL;
114
        echo sprintf('%'.$name_width.'s | %8s | %8s'.PHP_EOL, 'Total '.$archive->countFiles().' file(s)', $packed_size[0].$packed_size[1], $size[0].$size[1]);
115
116
    }
117
118
    /**
119
     * @param $bytes
120
     * @param int $precision
121
     * @return array
122
     */
123
    public function formatSize($bytes, $precision = 2)
124
    {
125
        $units = ['b', 'k', 'm', 'g', 't'];
126
127
        $bytes = max($bytes, 0);
128
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
129
        $pow = min($pow, count($units) - 1);
130
        $bytes /= pow(1024, $pow);
131
        $i = round($bytes, $precision);
132
        if ($precision == 1 && $i >= 10) {
133
            $i = round($i / 1024, 1);
134
            $pow++;
135
        }
136
137
        return [$i, $units[$pow]];
138
    }
139
140
    /**
141
     * @param $unixtime
142
     *
143
     * @return string
144
     * @throws \Exception
145
     */
146
    public function formatDate($unixtime)
147
    {
148
        if (strtotime('today') < $unixtime)
149
            return 'Today, '.date('G:m', $unixtime);
150
        else if (strtotime('yesterday') < $unixtime)
151
            return 'Yesterday, '.date('G:m', $unixtime);
152
        else {
153
            $datetime = new \DateTime();
154
            $datetime->setTimestamp($unixtime);
155
            if ($datetime->format('Y') == date('Y'))
156
                return $datetime->format('d M, G:m');
157
            else
158
                return $datetime->format('d M Y, G:m');
159
        }
160
    }
161
162
    /**
163
     * @param $args
164
     * @throws Exception
165
     * @throws \Archive7z\Exception
166
     */
167
    public function info($args)
168
    {
169
        $archive = $this->open($args['ARCHIVE']);
170
        echo 'Archive              type: '.$archive->getFormat().PHP_EOL;
171
        echo 'Archive           changed: '.$this->formatDate(filemtime($args['ARCHIVE'])).PHP_EOL;
172
        echo 'Archive          contains: '.$archive->countFiles().' file'.($archive->countFiles() > 1 ? 's' : null).PHP_EOL;
173
        echo 'Archive   compressed size: '.implode(' ', $this->formatSize($archive->getCompressedSize(), 2)).PHP_EOL;
174
        echo 'Archive uncompressed size: '.implode(' ', $this->formatSize($archive->getOriginalSize(), 2)).PHP_EOL;
175
        echo 'Archive compression ratio: '.round($archive->getOriginalSize() / $archive->getCompressedSize(), 6).'/1 ('.floor($archive->getCompressedSize() / $archive->getOriginalSize() * 100).'%)'.PHP_EOL;
176
        if (($comment = $archive->getComment()) !== null)
0 ignored issues
show
introduced by
The condition $comment = $archive->getComment() !== null is always false.
Loading history...
Bug introduced by
Are you sure the assignment to $comment is correct as $archive->getComment() targeting wapmorgan\UnifiedArchive...edArchive::getComment() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
177
            echo 'Archive           comment: '.$comment.PHP_EOL;
178
    }
179
180
    /**
181
     * @param $args
182
     * @throws Exception
183
     * @throws \Archive7z\Exception
184
     */
185
    public function extract($args)
186
    {
187
        $archive = $this->open($args['ARCHIVE'], isset($args['--password']) ? $args['--password'] : null);
188
        $output = getcwd();
189
        if (isset($args['--output'])) {
190
            if (!is_dir($args['--output']))
191
                mkdir($args['--output']);
192
            $output = realpath($args['--output']);
193
        }
194
195
        if (empty($args['FILES_IN_ARCHIVE']) || $args['FILES_IN_ARCHIVE'] == array('/') || $args['FILES_IN_ARCHIVE'] == array('*')) {
196
            $result = $archive->extractFiles($output);
197
            if ($result === false) echo 'Error occured'.PHP_EOL;
0 ignored issues
show
introduced by
The condition $result === false is always false.
Loading history...
198
            else echo 'Extracted '.$result.' file(s) to '.$output.PHP_EOL;
199
        } else {
200
            $extracted = 0;
201
            $errored = [];
202
            foreach ($args['FILES_IN_ARCHIVE'] as $file) {
203
                $result = $archive->extractFiles($output, $file);
204
                if ($result === false) $errored[] = $file;
205
                else $extracted += $result;
206
            }
207
            if (!empty($errored)) echo 'Errored: '.implode(', ', $errored).PHP_EOL;
208
            if ($extracted > 0) echo 'Extracted '.$extracted.' file(s) to '.$output.PHP_EOL;
209
        }
210
    }
211
212
    /**
213
     * @param $args
214
     * @throws Exception
215
     * @throws \Archive7z\Exception
216
     */
217
    public function printFile($args)
218
    {
219
        $archive = $this->open($args['ARCHIVE'], isset($args['--password']) ? $args['--password'] : null);
220
        foreach ($args['FILES_IN_ARCHIVE'] as $file) {
221
            if (!$archive->hasFile($file)) {
222
                echo 'File '.$file.' IS NOT PRESENT'.PHP_EOL;
223
                exit(-1);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
224
            }
225
//            $info = $archive->getFileData($file);
226
//            echo 'File content: '.$file.' (size is '.implode('', $this->formatSize($info->uncompressedSize, 1)).')'.PHP_EOL;
227
            echo $archive->getFileContent($file);
228
        }
229
    }
230
231
    /**
232
     * @param $args
233
     * @throws Exception
234
     * @throws \Archive7z\Exception
235
     */
236
    public function details($args)
237
    {
238
        $archive = $this->open($args['ARCHIVE']);
239
        foreach ($args['FILES_IN_ARCHIVE'] as $file) {
240
            $info = $archive->getFileData($file);
241
            if ($info === false) {
242
                echo 'File '.$file.' IS NOT PRESENT'.PHP_EOL;
243
                continue;
244
            }
245
            echo 'File name        : '.$file.PHP_EOL;
246
            echo 'Compressed size  : '.implode('', $this->formatSize($info->compressedSize, 2)).PHP_EOL;
247
            echo 'Uncompressed size: '.implode('', $this->formatSize($info->uncompressedSize, 2)).PHP_EOL;
248
            echo 'Is compressed    : '.($info->isCompressed ? 'yes' : 'no').PHP_EOL;
249
            echo 'Date modification: '.$this->formatDate($info->modificationTime).PHP_EOL;
250
            $comment = $info->comment;
251
            if ($comment !== null)
252
                echo 'Comment: '.$comment.PHP_EOL;
253
        }
254
    }
255
256
    /**
257
     * @param $args
258
     * @throws Exception
259
     * @throws \Archive7z\Exception
260
     */
261
    public function delete($args)
262
    {
263
        $archive = $this->open($args['ARCHIVE']);
264
        $files = $archive->getFileNames();
265
        foreach ($args['FILES_IN_ARCHIVE'] as $file) {
266
            if (!in_array($file, $files)) {
267
                echo 'File '.$file.' is NOT in archive'.PHP_EOL;
268
                continue;
269
            }
270
            if ($archive->deleteFiles($file) === false)
271
                echo 'Error file '.$file.PHP_EOL;
272
        }
273
    }
274
275
    /**
276
     * @param $args
277
     * @throws Exception
278
     * @throws \Archive7z\Exception
279
     */
280
    public function add($args)
281
    {
282
        $archive = $this->open($args['ARCHIVE']);
283
        $added_files = $archive->addFiles($args['FILES_ON_DISK']);
284
        if ($added_files === false)
285
            echo 'Error'.PHP_EOL;
286
        else
287
            echo 'Added '.$added_files.' file(s)'.PHP_EOL;
288
    }
289
290
    /**
291
     * @param $args
292
     * @throws Exception
293
     * @throws \Archive7z\Exception
294
     */
295
    public function addFromStdin($args)
296
    {
297
        $archive = $this->open($args['ARCHIVE']);
298
        $content = null;
299
        while (!feof(STDIN)) {
300
            $content .= fgets(STDIN);
301
        }
302
        $len = strlen($content);
0 ignored issues
show
Bug introduced by
It seems like $content can also be of type null; however, parameter $string of strlen() 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

302
        $len = strlen(/** @scrutinizer ignore-type */ $content);
Loading history...
303
304
        $added_files = $archive->addFileFromString($args['FILE_IN_ARCHIVE'], $content);
305
        if ($added_files === false)
306
            echo 'Error'.PHP_EOL;
307
        else {
308
            $size = $this->formatSize($len);
309
            echo sprintf('Added %s(%1.1f%s) file to %s',
310
                    $args['FILE_IN_ARCHIVE'], $size[0], $size[1], $args['ARCHIVE']) . PHP_EOL;
311
        }
312
    }
313
314
    /**
315
     * @param $args
316
     * @throws Exception
317
     */
318
    public function create($args)
319
    {
320
        $password = isset($args['--password']) ? $args['--password'] : null;
321
        $compression_level = isset($args['--compressionLevel']) ? $args['--compressionLevel'] : BasicDriver::COMPRESSION_AVERAGE;
322
323
        if (file_exists($args['ARCHIVE'])) {
324
            if (is_dir($args['ARCHIVE']))
325
                echo $args['ARCHIVE'].' is a directory!'.PHP_EOL;
326
            else {
327
                echo 'File '.$args['ARCHIVE'].' already exists!'.PHP_EOL;
328
            }
329
        } else {
330
            $files = [];
331
            $is_absolute = $args['--path'] === 'absolute';
332
333
            foreach ($args['FILES_ON_DISK'] as $i => $file) {
334
                $file = realpath($file);
335
                if ($is_absolute) {
336
                    $files[] = $file;
337
                } else {
338
                    $files[basename($file)] = $file;
339
                }
340
            }
341
342
            $archived_files = UnifiedArchive::archiveFiles($files, $args['ARCHIVE'], $compression_level, $password);
343
            if ($archived_files === false)
344
                echo 'Error'.PHP_EOL;
345
            else {
346
                if (isset($args['--comment'])) {
347
                    $archive = UnifiedArchive::open($args['ARCHIVE']);
348
                    $archive->setComment($args['--comment']);
349
                }
350
                echo 'Created archive ' . $args['ARCHIVE'] . ' with ' . $archived_files . ' file(s) of total size ' . implode('', $this->formatSize(filesize($args['ARCHIVE']))) . PHP_EOL;
351
            }
352
        }
353
    }
354
355
    public function createFake($args)
356
    {
357
        $files = [];
358
        $is_absolute = $args['--path'] === 'absolute';
359
360
        foreach ($args['FILES_ON_DISK'] as $i => $file) {
361
            $file = realpath($file);
362
            if ($is_absolute) {
363
                $files[] = $file;
364
            } else {
365
                $files[basename($file)] = $file;
366
            }
367
        }
368
369
        var_dump(UnifiedArchive::prepareForArchiving($files, $args['ARCHIVE']));
0 ignored issues
show
Security Debugging Code introduced by
var_dump(wapmorgan\Unifi...les, $args['ARCHIVE'])) looks like debug code. Are you sure you do not want to remove it?
Loading history...
370
    }
371
372
    protected function getTerminalWidth()
373
    {
374
        if (is_numeric($columns = trim(getenv('COLUMNS')))) {
375
            return $columns;
376
        }
377
378
        if (function_exists('shell_exec')) {
379
            // try for bash
380
            if (is_numeric($bash_width = trim(shell_exec('tput cols'))))
381
                return $bash_width;
382
383
            // try for windows
384
            if (!empty($win_width_val = trim(shell_exec('mode con'))) && preg_match('~columns: (\d+)~i', $win_width_val, $win_width))
385
                return $win_width[1];
386
        }
387
388
        return 80;
389
    }
390
}
391