Completed
Pull Request — master (#116)
by Théo
02:23
created

IO::parseInput()   B

Complexity

Conditions 6
Paths 5

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 19
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 12
nc 5
nop 0
1
<?php
2
3
/*
4
 * This file is part of the box project.
5
 *
6
 * (c) Kevin Herrera <[email protected]>
7
 *     Théo Fidry <[email protected]>
8
 *
9
 * This source file is subject to the MIT license that is bundled
10
 * with this source code in the file LICENSE.
11
 */
12
13
namespace KevinGH\Box\RequirementChecker;
14
15
/**
16
 * The code in this file must be PHP 5.3+ compatible as is used to know if the application can be run.
17
 *
18
 * @private
19
 */
20
final class IO
21
{
22
    const VERBOSITY_QUIET = 16;
23
    const VERBOSITY_NORMAL = 32;
24
    const VERBOSITY_VERBOSE = 64;
25
    const VERBOSITY_VERY_VERBOSE = 128;
26
    const VERBOSITY_DEBUG = 256;
27
    
28
    private $tokens;
29
    private $parsed;
30
    private $interactive;
31
    private $verbosity = self::VERBOSITY_NORMAL;
32
    private $colorSupport;
33
34
    public function __construct()
35
    {
36
        $this->parseInput();
37
38
        $shellVerbosity = $this->configureVerbosity();
39
        $this->interactive = $this->checkInteractivity($shellVerbosity);
40
        $this->colorSupport = $this->checkColorSupport();
41
    }
42
43
    /**
44
     * @return bool
45
     */
46
    public function isInteractive()
47
    {
48
        return $this->interactive;
49
    }
50
51
    /**
52
     * @return int
53
     */
54
    public function getVerbosity()
55
    {
56
        return $this->verbosity;
57
    }
58
59
    /**
60
     * @param int $verbosity
61
     */
62
    public function setVerbosity($verbosity)
63
    {
64
        $this->verbosity = $verbosity;
65
    }
66
67
    /**
68
     * @return bool
69
     */
70
    public function hasColorSupport()
71
    {
72
        return $this->colorSupport;
73
    }
74
75
    /**
76
     * @return array
77
     */
78
    private function parseInput()
79
    {
80
        $this->tokens = $_SERVER['argv'];
81
82
        $parsed = $this->tokens;
83
84
        while (null !== $token = array_shift($this->tokens)) {
85
            if ('' === $token) {
86
                continue;
87
            } elseif (0 === strpos($token, '--')) {
88
                list($name, $value) = $this->parseLongOption($token);
89
                $parsed[$name] = $value;
90
            } elseif ('-' === $token[0] && '-' !== $token) {
91
                list($name, $value) = $this->parseShortOption($token);
92
                $parsed[$name] = $value;
93
            }
94
        }
95
96
        $this->parsed = $parsed;
97
    }
98
99
    /**
100
     * @param string $token
101
     *
102
     * @return array
103
     */
104
    private function parseLongOption($token)
105
    {
106
        $name = substr($token, 2);
107
108
        if (false !== $pos = strpos($name, '=')) {
109
            if (0 === strlen($value = substr($name, $pos + 1))) {
110
                array_unshift($this->parsed, $value);
111
            }
112
113
            return array(substr($name, 0, $pos), $value);
114
        }
115
116
        return array($name, null);
117
    }
118
119
    /**
120
     * @param string $token
121
     *
122
     * @return array
123
     */
124
    private function parseShortOption($token)
125
    {
126
        $name = substr($token, 1);
127
128
        return array($name, null);
129
    }
130
131
    /**
132
     * {@inheritdoc}
133
     */
134
    public function hasParameterOption($values, $onlyParams = false)
135
    {
136
        $values = (array) $values;
137
138
        foreach ($this->parsed as $token) {
139
            if ($onlyParams && '--' === $token) {
140
                return false;
141
            }
142
            foreach ($values as $value) {
143
                if ($token === $value || 0 === strpos($token, $value.'=')) {
144
                    return true;
145
                }
146
            }
147
        }
148
149
        return false;
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function getParameterOption($values, $default = false, $onlyParams = false)
156
    {
157
        $values = (array) $values;
158
        $tokens = $this->parsed;
159
160
        while (0 < count($tokens)) {
161
            $token = array_shift($tokens);
162
            if ($onlyParams && '--' === $token) {
163
                return false;
164
            }
165
166
            foreach ($values as $value) {
167
                if ($token === $value || 0 === strpos($token, $value.'=')) {
168
                    if (false !== $pos = strpos($token, '=')) {
169
                        return substr($token, $pos + 1);
170
                    }
171
172
                    return array_shift($tokens);
173
                }
174
            }
175
        }
176
177
        return $default;
178
    }
179
180
    /**
181
     * @param int $shellVerbosity
182
     *
183
     * @return bool
184
     */
185
    private function checkInteractivity($shellVerbosity)
186
    {
187
        if (-1 === $shellVerbosity) {
188
            return false;
189
        }
190
191
        if (true === $this->hasParameterOption(array('--no-interaction', '-n'), true)) {
192
            return false;
193
        }
194
195
        if (function_exists('posix_isatty')) {
196
            if (!@posix_isatty(STDOUT) && false === getenv('SHELL_INTERACTIVE')) {
197
                return false;
198
            }
199
        }
200
201
        return true;
202
    }
203
204
    /**
205
     * @return int
206
     */
207
    private function configureVerbosity()
208
    {
209
        switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) {
210
            case -1:
211
                $this->verbosity = self::VERBOSITY_QUIET;
212
                break;
213
            case 1:
214
                $this->verbosity = self::VERBOSITY_VERBOSE;
215
                break;
216
            case 2:
217
                $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
218
                break;
219
            case 3:
220
                $this->verbosity = self::VERBOSITY_DEBUG;
221
                break;
222
                break;
223
            default:
224
                $shellVerbosity = 0;
225
                break;
226
        }
227
228
        if (true === $this->hasParameterOption(array('--quiet', '-q'), true)) {
229
            $this->verbosity = self::VERBOSITY_QUIET;
230
            $shellVerbosity = -1;
231
        } else {
232
            if ($this->hasParameterOption('-vvv', true)
233
                || $this->hasParameterOption('--verbose=3', true)
234
                || 3 === $this->getParameterOption('--verbose', false, true)
235
            ) {
236
                $this->verbosity = self::VERBOSITY_DEBUG;
237
                $shellVerbosity = 3;
238
            } elseif ($this->hasParameterOption('-vv', true)
239
                || $this->hasParameterOption('--verbose=2', true)
240
                || 2 === $this->getParameterOption('--verbose', false, true)
241
            ) {
242
                $this->verbosity = self::VERBOSITY_VERY_VERBOSE;
243
                $shellVerbosity = 2;
244
            } elseif ($this->hasParameterOption('-v', true)
245
                || $this->hasParameterOption('--verbose=1', true)
246
                || $this->hasParameterOption('--verbose', true)
247
                || $this->getParameterOption('--verbose', false, true)
248
            ) {
249
                $this->verbosity = self::VERBOSITY_VERBOSE;
250
                $shellVerbosity = 1;
251
            }
252
        }
253
254
        return $shellVerbosity;
255
    }
256
257
    /**
258
     * Returns true if the stream supports colorization.
259
     *
260
     * Colorization is disabled if not supported by the stream:
261
     *
262
     *  -  Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
263
     *  -  non tty consoles
264
     *
265
     * @return bool true if the stream supports colorization, false otherwise
266
     *
267
     * @see \Symfony\Component\Console\Output\StreamOutput
268
     */
269
    private function checkColorSupport()
270
    {
271
        if (DIRECTORY_SEPARATOR === '\\') {
272
            return
273
                '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR . '.' . PHP_WINDOWS_VERSION_MINOR . '.' . PHP_WINDOWS_VERSION_BUILD
274
                || false !== getenv('ANSICON')
275
                || 'ON' === getenv('ConEmuANSI')
276
                || 'xterm' === getenv('TERM');
277
        }
278
279
        return function_exists('posix_isatty') && @posix_isatty(STDOUT);
280
    }
281
}