Completed
Push — master ( 1a6302...042aa1 )
by Bernhard
02:57
created

Installer::validateOptions()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 13.7937

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 22
ccs 5
cts 17
cp 0.2941
rs 8.6738
cc 5
eloc 13
nc 4
nop 0
crap 13.7937
1
<?php
2
3
/*
4
 * This file is part of the puli/installer package.
5
 *
6
 * (c) Bernhard Schussek <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Puli\Installer;
13
14
use Exception;
15
use Humbug\SelfUpdate\VersionParser;
16
use Phar;
17
use PharException;
18
use RuntimeException;
19
use UnexpectedValueException;
20
21
/**
22
 * Installs the puli.phar on the local system.
23
 *
24
 * Use it like this:
25
 *
26
 * ```
27
 * $ curl -sS https://puli.io/installer | php
28
 * ```
29
 *
30
 * This file was adapted from the installer file bundled with Composer. For the
31
 * original file, authors and copyright information see
32
 *
33
 * https://github.com/composer/getcomposer.org/blob/master/web/installer
34
 *
35
 * @author Nils Adermann <[email protected]>
36
 * @author Jordi Boggiano <[email protected]>
37
 * @author Thomas Rudolph <[email protected]>
38
 * @author Bernhard Schussek <[email protected]>
39
 */
40
class Installer
41
{
42
    /**
43
     * The help text of the installer.
44
     */
45
    const HELP_TEXT = <<<HELP
46
Puli Installer
47
--------------
48
Options
49
--help               this help
50
--check              for checking environment only
51
--force              forces the installation even if the system requirements are not satisfied
52
--ansi               force ANSI color output
53
--no-ansi            disable ANSI color output
54
--quiet              do not output unimportant messages
55
--install-dir="..."  set the target installation directory
56
--version="..."      install a specific version
57
--filename="..."     set the target filename (default: puli.phar)
58
59
HELP;
60
61
    /**
62
     * The api url to determine the available versions of puli.
63
     */
64
    const VERSION_API_URL = 'https://puli.io/download/versions.json';
65
66
    /**
67
     * The phar download url.
68
     */
69
    const PHAR_DOWNLOAD_URL = 'https://puli.io/download/%s/puli.phar';
70
71
    /**
72
     * @var string
73
     */
74
    private $stability;
75
76
    /**
77
     * @var bool
78
     */
79
    private $check;
80
81
    /**
82
     * @var bool
83
     */
84
    private $help;
85
86
    /**
87
     * @var bool
88
     */
89
    private $force;
90
91
    /**
92
     * @var bool
93
     */
94
    private $quiet;
95
96
    /**
97
     * @var string
98
     */
99
    private $installDir;
100
101
    /**
102
     * @var string
103
     */
104
    private $version;
105
106
    /**
107
     * @var string
108
     */
109
    private $filename;
110
111
    /**
112
     * Runs the installer.
113
     *
114
     * @param array $argv The console arguments.
115
     *
116
     * @return int The return status.
117
     */
118 5
    public function run(array $argv)
119
    {
120 5
        $this->parseOptions($argv);
121
122 5
        if ($this->help) {
123
            echo self::HELP_TEXT;
124
125
            return 0;
126
        }
127
128 5
        $ok = $this->validateSystem() && $this->validateOptions();
129
130 5
        if ($this->check) {
131
            return $ok ? 0 : 1;
132
        }
133
134 5
        if ($ok || $this->force) {
135 5
            return $this->installPuli();
136
        }
137
138
        return 1;
139
    }
140
141
    /**
142
     * Installs puli to the current working directory.
143
     *
144
     * @return int The return status.
145
     *
146
     * @throws Exception
147
     */
148 5
    private function installPuli()
149
    {
150 5
        $workingDir = str_replace('\\', '/', getcwd());
151 5
        $installDir = is_dir($this->installDir) ? realpath($this->installDir) : $workingDir;
152 5
        $installPath = str_replace('\\', '/', $installDir).'/'.$this->filename;
153 5
        $shortInstallPath = $installPath;
154
155
        // Strip the current working directory if possible
156 5
        if (0 === strpos($shortInstallPath, $workingDir.'/')) {
157 3
            $shortInstallPath = substr($shortInstallPath, strlen($workingDir.'/'));
158 3
        }
159
160 5
        if (is_readable($installPath)) {
161
            @unlink($installPath);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
162
        }
163
164 5
        $httpClient = new HttpClient();
165
166 5
        $versions = array();
167 5
        for ($retries = 3; $retries > 0; --$retries) {
168 5
            if (!$this->quiet) {
169 5
                $this->info('Downloading available versions...');
170 5
            }
171
172
            try {
173 5
                $versions = $this->downloadVersions($httpClient, static::VERSION_API_URL);
174 5
                break;
175
            } catch (RuntimeException $e) {
176
                $this->error($e->getMessage());
177
            }
178
        }
179
180 5
        if (0 === $retries || empty($versions)) {
181
            $this->error('fatal: The download failed repeatedly, aborting.');
182
183
            return 1;
184
        }
185
186 5
        $versionParser = new VersionParser($versions);
187 5
        if (!empty($this->version)) {
188 1
            if (!in_array($this->version, $versions, true)) {
189
                $this->error(sprintf(
190
                    'fatal: Could not find version: %s.',
191
                    $this->version
192
                ));
193
194
                return 1;
195
            }
196 5
        } elseif ('stable' === $this->stability) {
197 1
            $this->version = $versionParser->getMostRecentStable();
198 1
            if (false === $this->version) {
199 1
                $this->error('fatal: Could not find a stable version.');
200
201 1
                return 1;
202
            }
203
        } else {
204 3
            $this->version = $versionParser->getMostRecentAll();
205
        }
206
207 4
        $url = sprintf(
208 4
            static::PHAR_DOWNLOAD_URL,
209 4
            $this->version
210 4
        );
211
212 4
        for ($retries = 3; $retries > 0; --$retries) {
213 4
            if (!$this->quiet) {
214 4
                $this->info(sprintf(
215 4
                    'Downloading puli.phar at version %s...',
216 4
                    $this->version)
217 4
                );
218 4
            }
219
220 4
            if (!$this->downloadFile($httpClient, $url, $installPath)) {
221
                continue;
222
            }
223
224
            try {
225 4
                $this->validatePhar($installPath);
226 4
            } catch (Exception $e) {
227
                unlink($installPath);
228
229
                if (!$e instanceof UnexpectedValueException && !$e instanceof PharException) {
230
                    throw $e;
231
                }
232
233
                if ($retries > 0) {
234
                    if (!$this->quiet) {
235
                        $this->error('The download is corrupt, retrying...');
236
                    }
237
                } else {
238
                    $this->error(sprintf(
239
                        'fatal: The download is corrupt (%s), aborting.',
240
                        $e->getMessage()
241
                    ));
242
243
                    return 1;
244
                }
245
            }
246
247 4
            break;
248
        }
249
250 4
        if (0 === $retries) {
251
            $this->error('fatal: The download failed repeatedly, aborting.');
252
253
            return 1;
254
        }
255
256 4
        chmod($installPath, 0755);
257
258 4
        if (!$this->quiet) {
259 4
            $this->success(PHP_EOL.'Puli successfully installed to: '.$installPath);
260 4
            $this->info('Use it: php '.$shortInstallPath);
261 4
        }
262
263 4
        return 0;
264
    }
265
266
    /**
267
     * Downloads a URL to a path.
268
     *
269
     * @param HttpClient $httpClient The client to use.
270
     * @param string     $url        The URL to download.
271
     * @param string     $targetPath The path to download the URL to.
272
     *
273
     * @return bool Whether the download completed successfully.
274
     */
275 4
    private function downloadFile(HttpClient $httpClient, $url, $targetPath)
276
    {
277 4
        ErrorHandler::register();
278
279 4
        $fh = fopen($targetPath, 'w');
280
281 4
        if (!$fh) {
282
            $this->error(sprintf(
283
                'Could not create file %s: %s',
284
                $targetPath,
285
                implode(PHP_EOL, ErrorHandler::getErrors())
286
            ));
287
        }
288
289 4
        if (!fwrite($fh, $httpClient->download($url))) {
290
            $this->error(sprintf(
291
                'Download failed: %s',
292
                implode(PHP_EOL, ErrorHandler::getErrors())
293
            ));
294
        }
295
296 4
        fclose($fh);
297
298 4
        ErrorHandler::unregister();
299
300 4
        return !ErrorHandler::hasErrors();
301
    }
302
303
    /**
304
     * Downloads the available puli versions.
305
     *
306
     * @param HttpClient $httpClient The client to use.
307
     * @param string     $url        The URL to download.
308
     *
309
     * @return array The available versions, null if the download failed.
310
     *
311
     * @throws RuntimeException If an error occurs.
312
     */
313 5
    public function downloadVersions(HttpClient $httpClient, $url)
314
    {
315 5
        ErrorHandler::register();
316 5
        $versions = $httpClient->download($url);
317 5
        ErrorHandler::unregister();
318
319 5
        if (ErrorHandler::hasErrors()) {
320
            throw new RuntimeException(sprintf(
321
                'Could not download %s:'.PHP_EOL.'%s',
322
                $url,
323
                implode(PHP_EOL, ErrorHandler::getErrors())
324
            ));
325
        }
326
327 5
        $versions = json_decode($versions);
328 5
        if (json_last_error() !== JSON_ERROR_NONE || !is_array($versions)) {
329
            throw new RuntimeException(sprintf(
330
                'Could not download %s:'.PHP_EOL.'Malformed JSON returned.',
331
                $url
332
            ));
333
        }
334
335 5
        usort($versions, 'version_compare');
336
337 5
        return $versions;
338
    }
339
340
    /**
341
     * Validates that the given path is a valid PHAR file.
342
     *
343
     * @param string $path A path to a PHAR file.
344
     *
345
     * @throws Exception If an error occurs.
346
     */
347 4
    private function validatePhar($path)
348
    {
349 4
        $tmpFile = $path;
350
351
        try {
352
            // create a temp file ending in .phar since the Phar class only accepts that
353 4
            if ('.phar' !== substr($path, -5)) {
354
                copy($path, $path.'.tmp.phar');
355
                $tmpFile = $path.'.tmp.phar';
356
            }
357
358 4
            if (!ini_get('phar.readonly')) {
359
                // test the phar validity
360 4
                $phar = new Phar($tmpFile);
361
362
                // free the variable to unlock the file
363 4
                unset($phar);
364 4
            }
365 4
        } catch (Exception $e) {
366
            // clean up temp file if needed
367
            if ($path !== $tmpFile) {
368
                unlink($tmpFile);
369
            }
370
371
            throw $e;
372
        }
373
374
        // clean up temp file if needed
375 4
        if ($path !== $tmpFile) {
376
            unlink($tmpFile);
377
        }
378 4
    }
379
380
    /**
381
     * Check the platform for possible issues on running Puli.
382
     *
383
     * @return bool Whether the platform requirements are satisfied.
384
     */
385 5
    private function validateSystem()
386
    {
387 5
        $errors = array();
388 5
        $warnings = array();
389
390 5
        $iniPath = php_ini_loaded_file();
391 5
        $displayIniMessage = false;
392
393 5
        if ($iniPath) {
394 5
            $iniMessage = PHP_EOL.PHP_EOL.'The php.ini used by your command-line PHP is: '.$iniPath;
395 5
        } else {
396
            $iniMessage = PHP_EOL.PHP_EOL.'A php.ini file does not exist. You will have to create one.';
397
        }
398
399 5
        $iniMessage .= PHP_EOL.'If you can not modify the ini file, you can also run `php -d option=value` to modify ini values on the fly. You can use -d multiple times.';
400
401 5
        if (ini_get('detect_unicode')) {
402
            $errors['unicode'] = 'On';
403
        }
404
405 5
        if (extension_loaded('suhosin')) {
406
            $suhosin = ini_get('suhosin.executor.include.whitelist');
407
            $suhosinBlacklist = ini_get('suhosin.executor.include.blacklist');
408
            if (false === stripos($suhosin,
409
                    'phar') && (!$suhosinBlacklist || false !== stripos($suhosinBlacklist,
410
                        'phar'))
411
            ) {
412
                $errors['suhosin'] = $suhosin;
413
            }
414
        }
415
416 5
        if (!function_exists('json_decode')) {
417
            $errors['json'] = true;
418
        }
419
420 5
        if (!extension_loaded('Phar')) {
421
            $errors['phar'] = true;
422
        }
423
424 5
        if (!ini_get('allow_url_fopen')) {
425
            $errors['allow_url_fopen'] = true;
426
        }
427
428 5
        if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
429
            $errors['ioncube'] = ioncube_loader_version();
430
        }
431
432 5
        if (version_compare(PHP_VERSION, '5.3.9', '<')) {
433
            $errors['php'] = PHP_VERSION;
434
        }
435
436 5
        if (!extension_loaded('openssl')) {
437
            $errors['openssl'] = true;
438
        }
439
440 5
        if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
441
            $warnings['apc_cli'] = true;
442
        }
443
444 5
        ob_start();
445 5
        phpinfo(INFO_GENERAL);
446 5
        $phpinfo = ob_get_clean();
447 5
        if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m',
448 5
            $phpinfo, $match)) {
449 5
            $configure = $match[1];
450
451 5
            if (false !== strpos($configure, '--enable-sigchild')) {
452
                $warnings['sigchild'] = true;
453
            }
454
455 5
            if (false !== strpos($configure, '--with-curlwrappers')) {
456
                $warnings['curlwrappers'] = true;
457
            }
458 5
        }
459
460 5
        if (!empty($errors)) {
461
            $this->error('Some settings on your machine make Puli unable to work properly.');
462
            $this->error('Make sure that you fix the issues listed below and run this script again:');
463
464
            foreach ($errors as $error => $current) {
465
                $text = '';
466
                switch ($error) {
467
                    case 'json':
468
                        $text = PHP_EOL.'The json extension is missing.'.PHP_EOL;
469
                        $text .= 'Install it or recompile php without --disable-json';
470
                        break;
471
472
                    case 'phar':
473
                        $text = PHP_EOL.'The phar extension is missing.'.PHP_EOL;
474
                        $text .= 'Install it or recompile php without --disable-phar';
475
                        break;
476
477 View Code Duplication
                    case 'unicode':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
478
                        $text = PHP_EOL.'The detect_unicode setting must be disabled.'.PHP_EOL;
479
                        $text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL;
480
                        $text .= '    detect_unicode = Off';
481
                        $displayIniMessage = true;
482
                        break;
483
484 View Code Duplication
                    case 'suhosin':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
485
                        $text = PHP_EOL.'The suhosin.executor.include.whitelist setting is incorrect.'.PHP_EOL;
486
                        $text .= 'Add the following to the end of your `php.ini` or suhosin.ini (Example path [for Debian]: /etc/php5/cli/conf.d/suhosin.ini):'.PHP_EOL;
487
                        $text .= '    suhosin.executor.include.whitelist = phar '.$current;
488
                        $displayIniMessage = true;
489
                        break;
490
491
                    case 'php':
492
                        $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.9 or higher.";
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $current instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
493
                        break;
494
495 View Code Duplication
                    case 'allow_url_fopen':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
496
                        $text = PHP_EOL.'The allow_url_fopen setting is incorrect.'.PHP_EOL;
497
                        $text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL;
498
                        $text .= '    allow_url_fopen = On';
499
                        $displayIniMessage = true;
500
                        break;
501
502 View Code Duplication
                    case 'ioncube':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
503
                        $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
0 ignored issues
show
Coding Style Best Practice introduced by
As per coding-style, please use concatenation or sprintf for the variable $current instead of interpolation.

It is generally a best practice as it is often more readable to use concatenation instead of interpolation for variables inside strings.

// Instead of
$x = "foo $bar $baz";

// Better use either
$x = "foo " . $bar . " " . $baz;
$x = sprintf("foo %s %s", $bar, $baz);
Loading history...
504
                        $text .= 'Upgrade to ionCube 4.0.9 or higher or remove this line (path may be different) from your `php.ini` to disable it:'.PHP_EOL;
505
                        $text .= '    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so';
506
                        $displayIniMessage = true;
507
                        break;
508
509
                    case 'openssl':
510
                        $text = PHP_EOL.'The openssl extension is missing, which means that secure HTTPS transfers are impossible.'.PHP_EOL;
511
                        $text .= 'If possible you should enable it or recompile php with --with-openssl';
512
                        break;
513
                }
514
515
                if ($displayIniMessage) {
516
                    $text .= $iniMessage;
517
                }
518
519
                $this->info($text);
520
            }
521
522
            echo PHP_EOL;
523
524
            return false;
525
        }
526
527 5
        if (!empty($warnings)) {
528
            $this->error('Some settings on your machine may cause stability issues with Puli.');
529
            $this->error('If you encounter issues, try to change the following:');
530
531
            foreach ($warnings as $warning => $current) {
532
                $text = '';
533
                switch ($warning) {
534 View Code Duplication
                    case 'apc_cli':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
535
                        $text = PHP_EOL.'The apc.enable_cli setting is incorrect.'.PHP_EOL;
536
                        $text .= 'Add the following to the end of your `php.ini`:'.PHP_EOL;
537
                        $text .= '    apc.enable_cli = Off';
538
                        $displayIniMessage = true;
539
                        break;
540
541
                    case 'sigchild':
542
                        $text = PHP_EOL.'PHP was compiled with --enable-sigchild which can cause issues on some platforms.'.PHP_EOL;
543
                        $text .= 'Recompile it without this flag if possible, see also:'.PHP_EOL;
544
                        $text .= '    https://bugs.php.net/bug.php?id=22999';
545
                        break;
546
547
                    case 'curlwrappers':
548
                        $text = PHP_EOL.'PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.'.PHP_EOL;
549
                        $text .= 'Recompile it without this flag if possible';
550
                        break;
551
552
                    case 'openssl':
553
                        $text = PHP_EOL.'The openssl extension is missing, which means that secure HTTPS transfers are impossible.'.PHP_EOL;
554
                        $text .= 'If possible you should enable it or recompile php with --with-openssl';
555
                        break;
556
                }
557
                if ($displayIniMessage) {
558
                    $text .= $iniMessage;
559
                }
560
                $this->info($text);
561
            }
562
563
            echo PHP_EOL;
564
565
            return true;
566
        }
567
568 5
        if (!$this->quiet) {
569 5
            $this->success('All settings correct for using Puli');
570 5
        }
571
572 5
        return true;
573
    }
574
575
    /**
576
     * Validate whether the passed command line options are correct.
577
     *
578
     * @return bool Returns `true` if the options are valid and `false` otherwise.
579
     */
580 5
    private function validateOptions()
581
    {
582 5
        $ok = true;
583
584 5
        if (false !== $this->installDir && !is_dir($this->installDir)) {
585
            $this->info(sprintf(
586
                'The defined install dir (%s) does not exist.',
587
                $this->installDir
588
            ));
589
            $ok = false;
590
        }
591
592 5
        if (false !== $this->version && 1 !== preg_match('/^\d+\.\d+\.\d+(\-(alpha|beta)\d+)*$/', $this->version)) {
593
            $this->info(sprintf(
594
                'The defined install version (%s) does not match release pattern.',
595
                $this->version
596
            ));
597
            $ok = false;
598
        }
599
600 5
        return $ok;
601
    }
602
603
    /**
604
     * Parses the command line options.
605
     *
606
     * @param string[] $argv The command line options.
607
     */
608 5
    private function parseOptions(array $argv)
609
    {
610 5
        $this->check = in_array('--check', $argv);
611 5
        $this->help = in_array('--help', $argv);
612 5
        $this->force = in_array('--force', $argv);
613 5
        $this->quiet = in_array('--quiet', $argv);
614 5
        $this->installDir = false;
0 ignored issues
show
Documentation Bug introduced by
The property $installDir was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
615 5
        $this->version = false;
0 ignored issues
show
Documentation Bug introduced by
The property $version was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
616 5
        $this->filename = 'puli.phar';
617 5
        $this->stability = 'unstable';
618 5
        if (in_array('--stable', $argv)) {
619 1
            $this->stability = 'stable';
620 1
        }
621
622
        // --no-ansi wins over --ansi
623 5
        if (in_array('--no-ansi', $argv)) {
624 4
            define('USE_ANSI', false);
625 5
        } elseif (in_array('--ansi', $argv)) {
626
            define('USE_ANSI', true);
627
        } else {
628
            // On Windows, default to no ANSI, except in ANSICON and ConEmu.
629
            // Everywhere else, default to ANSI if stdout is a terminal.
630 1
            define('USE_ANSI', ('\\' === DIRECTORY_SEPARATOR)
631 1
                ? (false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'))
632 1
                : (function_exists('posix_isatty') && posix_isatty(1)));
633
        }
634
635 5
        foreach ($argv as $key => $val) {
636 5 View Code Duplication
            if (0 === strpos($val, '--install-dir')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
637 2
                if (13 === strlen($val) && isset($argv[$key + 1])) {
638 2
                    $this->installDir = trim($argv[$key + 1]);
639 2
                } else {
640
                    $this->installDir = trim(substr($val, 14));
641
                }
642 2
            }
643
644 5 View Code Duplication
            if (0 === strpos($val, '--version')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
645 1
                if (9 === strlen($val) && isset($argv[$key + 1])) {
646 1
                    $this->version = trim($argv[$key + 1]);
647 1
                } else {
648
                    $this->version = trim(substr($val, 10));
649
                }
650 1
            }
651
652 5 View Code Duplication
            if (0 === strpos($val, '--filename')) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
653
                if (10 === strlen($val) && isset($argv[$key + 1])) {
654
                    $this->filename = trim($argv[$key + 1]);
655
                } else {
656
                    $this->filename = trim(substr($val, 11));
657
                }
658
            }
659 5
        }
660 5
    }
661
662
    /**
663
     * Prints output indicating a success.
664
     *
665
     * @param string $text The text to print.
666
     */
667 5
    private function success($text)
668
    {
669 5
        printf(USE_ANSI ? "\033[0;32m%s\033[0m" : '%s', $text.PHP_EOL);
670 5
    }
671
672
    /**
673
     * Prints output indicating an error.
674
     *
675
     * @param string $text The text to print.
676
     */
677 1
    private function error($text)
678
    {
679 1
        printf(USE_ANSI ? "\033[31;31m%s\033[0m" : '%s', $text.PHP_EOL);
680 1
    }
681
682
    /**
683
     * Prints output indicating some information.
684
     *
685
     * @param string $text The text to print.
686
     */
687 5
    private function info($text)
688
    {
689 5
        printf(USE_ANSI ? "\033[33;33m%s\033[0m" : '%s', $text.PHP_EOL);
690 5
    }
691
}
692