IO   A
last analyzed

Complexity

Total Complexity 33

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 33
eloc 79
dl 0
loc 159
rs 9.76
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A isInteractive() 0 3 1
A checkInteractivity() 0 18 6
A hasColorSupport() 0 3 1
A __construct() 0 8 1
A hasParameter() 0 16 3
B checkColorSupport() 0 32 11
A getVerbosity() 0 3 1
B configureVerbosity() 0 35 9
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\RequirementChecker;
16
17
use function fstat;
18
use function function_exists;
19
use function getenv;
20
use function implode;
21
use function posix_isatty;
22
use function preg_match;
23
use function preg_quote;
24
use function sapi_windows_vt100_support;
25
use function sprintf;
26
use function str_replace;
27
use function stream_isatty;
28
use const DIRECTORY_SEPARATOR;
29
use const STDOUT;
30
31
/**
32
 * @private
33
 */
34
final class IO
35
{
36
    public const VERBOSITY_QUIET = 16;
37
    public const VERBOSITY_NORMAL = 32;
38
    public const VERBOSITY_VERBOSE = 64;
39
    public const VERBOSITY_VERY_VERBOSE = 128;
40
    public const VERBOSITY_DEBUG = 256;
41
42
    private $interactive;
43
    private $verbosity = self::VERBOSITY_NORMAL;
44
    private $colorSupport;
45
    private $options;
46
47
    public function __construct()
48
    {
49
        $this->options = implode(' ', $_SERVER['argv']);
50
51
        $shellVerbosity = $this->configureVerbosity();
52
53
        $this->interactive = $this->checkInteractivity($shellVerbosity);
54
        $this->colorSupport = $this->checkColorSupport();
55
    }
56
57
    public function isInteractive(): bool
58
    {
59
        return $this->interactive;
60
    }
61
62
    public function getVerbosity(): int
63
    {
64
        return $this->verbosity;
65
    }
66
67
    public function hasColorSupport(): bool
68
    {
69
        return $this->colorSupport;
70
    }
71
72
    public function hasParameter($values): bool
73
    {
74
        $values = (array) $values;
75
76
        foreach ($values as $value) {
77
            $regexp = sprintf(
78
                '/\s%s\b/',
79
                str_replace(' ', '\s+', preg_quote($value, '/'))
80
            );
81
82
            if (1 === preg_match($regexp, $this->options)) {
83
                return true;
84
            }
85
        }
86
87
        return false;
88
    }
89
90
    private function checkInteractivity(int $shellVerbosity): bool
91
    {
92
        if (-1 === $shellVerbosity) {
93
            return false;
94
        }
95
96
        if (true === $this->hasParameter(['--no-interaction', '-n'])) {
97
            return false;
98
        }
99
100
        if (function_exists('posix_isatty')
101
            && !@posix_isatty(STDOUT)
102
            && false === getenv('SHELL_INTERACTIVE')
103
        ) {
104
            return false;
105
        }
106
107
        return true;
108
    }
109
110
    private function configureVerbosity(): int
111
    {
112
        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
113
            case -1:
114
                $this->verbosity = self::VERBOSITY_QUIET;
115
                break;
116
            case 1:
117
                $this->verbosity = self::VERBOSITY_VERBOSE;
118
                break;
119
            case 2:
120
                $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
121
                break;
122
            case 3:
123
                $this->verbosity = self::VERBOSITY_DEBUG;
124
                break;
125
            default:
126
                $shellVerbosity = 0;
127
                break;
128
        }
129
130
        if ($this->hasParameter(['--quiet', '-q'])) {
131
            $this->verbosity = self::VERBOSITY_QUIET;
132
            $shellVerbosity = -1;
133
        } elseif ($this->hasParameter(['-vvv', '--verbose=3', '--verbose 3'])) {
134
            $this->verbosity = self::VERBOSITY_DEBUG;
135
            $shellVerbosity = 3;
136
        } elseif ($this->hasParameter(['-vv', '--verbose=2', '--verbose 2'])) {
137
            $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
138
            $shellVerbosity = 2;
139
        } elseif ($this->hasParameter(['-v', '--verbose=1', '--verbose 1', '--verbose'])) {
140
            $this->verbosity = self::VERBOSITY_VERBOSE;
141
            $shellVerbosity = 1;
142
        }
143
144
        return $shellVerbosity;
145
    }
146
147
    /**
148
     * Returns true if the stream supports colorization.
149
     *
150
     * Colorization is disabled if not supported by the stream:
151
     *
152
     *  -  Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
153
     *  -  non tty consoles
154
     *
155
     * @return bool true if the stream supports colorization, false otherwise
156
     *
157
     * @see \Symfony\Component\Console\Output\StreamOutput
158
     *
159
     * @license MIT (c) Fabien Potencier <[email protected]>
160
     */
161
    private function checkColorSupport(): bool
162
    {
163
        if ($this->hasParameter(['--ansi'])) {
164
            return true;
165
        }
166
167
        if ($this->hasParameter(['--no-ansi'])) {
168
            return false;
169
        }
170
171
        if (DIRECTORY_SEPARATOR === '\\') {
172
            return (
173
                function_exists('sapi_windows_vt100_support')
174
                && sapi_windows_vt100_support(STDOUT)
175
            )
176
                || false !== getenv('ANSICON')
177
                || 'ON' === getenv('ConEmuANSI')
178
                || 'xterm' === getenv('TERM');
179
        }
180
181
        if (function_exists('stream_isatty')) {
182
            return stream_isatty(STDOUT);
183
        }
184
185
        if (function_exists('posix_isatty')) {
186
            return posix_isatty(STDOUT);
187
        }
188
189
        $stat = fstat(STDOUT);
190
191
        // Check if formatted mode is S_IFCHR
192
        return $stat ? 0020000 === ($stat['mode'] & 0170000) : false;
193
    }
194
}
195