Passed
Push — develop ( 95bbc2...2e9417 )
by nguereza
02:16
created

Reader::readPipe()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 12
nc 6
nop 1
dl 0
loc 19
rs 9.5555
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Platine Console
5
 *
6
 * Platine Console is a powerful library with support of custom
7
 * style to build command line interface applications
8
 *
9
 * This content is released under the MIT License (MIT)
10
 *
11
 * Copyright (c) 2020 Platine Console
12
 * Copyright (c) 2017-2020 Jitendra Adhikari
13
 *
14
 * Permission is hereby granted, free of charge, to any person obtaining a copy
15
 * of this software and associated documentation files (the "Software"), to deal
16
 * in the Software without restriction, including without limitation the rights
17
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
 * copies of the Software, and to permit persons to whom the Software is
19
 * furnished to do so, subject to the following conditions:
20
 *
21
 * The above copyright notice and this permission notice shall be included in all
22
 * copies or substantial portions of the Software.
23
 *
24
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
 * SOFTWARE.
31
 */
32
33
/**
34
 *  @file Reader.php
35
 *
36
 *  The Input Reader class
37
 *
38
 *  @package    Platine\Console\Input
39
 *  @author Platine Developers Team
40
 *  @copyright  Copyright (c) 2020
41
 *  @license    http://opensource.org/licenses/MIT  MIT License
42
 *  @link   https://www.platine-php.com
43
 *  @version 1.0.0
44
 *  @filesource
45
 */
46
47
declare(strict_types=1);
48
49
namespace Platine\Console\Input;
50
51
/**
52
 * Class Reader
53
 * @package Platine\Console\Input
54
 */
55
class Reader
56
{
57
    /**
58
     * The input stream
59
     * @var resource
60
     */
61
    protected $stream;
62
63
    /**
64
     * Create new instance
65
     * @param string|null $path the input read path
66
     */
67
    public function __construct(?string $path = null)
68
    {
69
        $stream = STDIN;
70
        if ($path !== null) {
71
            $stream = fopen($path, 'r');
72
        }
73
74
        $this->stream = $stream;
75
    }
76
    
77
    /**
78
     * Set the stream
79
     * @param resource $stream
80
     * @return $this
81
     */
82
    public function setStream($stream)
83
    {
84
        $this->stream = $stream;
85
        return $this;
86
    }
87
88
    
89
    /**
90
     * Read the user input
91
     * @param mixed $default
92
     * @param callable|null $callback The validator/sanitizer callback.
93
     * @return mixed
94
     */
95
    public function read($default = null, ?callable $callback = null)
96
    {
97
        // see https://www.php.net/manual/en/filesystem.configuration.php#ini.auto-detect-line-endings
98
        ini_set('auto_detect_line_endings', 'true');
99
        $input = '';
100
        $read = fgets($this->stream);
101
102
        if ($read !== false) {
103
            $input = rtrim($read, "\r\n");
104
        }
105
106
        if ($input === '' && $default !== null) {
107
            return $default;
108
        }
109
110
        return $callback !== null
111
                ? $callback($input)
112
                : $input;
113
    }
114
115
    /**
116
     * Read all line of the user input
117
     * @param callable|null $callback The validator/sanitizer callback.
118
     * @return mixed
119
     */
120
    public function readAll(?callable $callback = null)
121
    {
122
        $input = stream_get_contents($this->stream);
123
124
        return $callback !== null
125
                ? $callback($input)
126
                : $input;
127
    }
128
129
    /**
130
     * Read content piped to the stream without waiting.
131
     * @param callable|null $callback The validator/sanitizer callback.
132
     * @return mixed
133
     */
134
    public function readPipe(?callable $callback = null)
135
    {
136
        $stdin = '';
137
        $read = [$this->stream];
138
        $write = [];
139
        $except = [];
140
141
        if (stream_select($read, $write, $except, 0) === 1) {
142
            while ($line = fgets($this->stream)) {
143
                $stdin .= $line;
144
            }
145
        }
146
147
        if ($stdin === '') {
148
            return $callback !== null
149
                ? $callback($this)
150
                : '';
151
        }
152
        return $stdin;
153
    }
154
155
    /**
156
     * Read a line from configured stream (or terminal) but don't echo it back.
157
     * @param mixed $default
158
     * @param callable|null $callback The validator/sanitizer callback.
159
     * @return mixed
160
     */
161
    public function readHidden($default = null, ?callable $callback = null)
162
    {
163
        if (substr(strtoupper(PHP_OS), 0, 3) === 'WIN') {
164
            return $this->readHiddenWindows($default, $callback);
165
        }
166
167
        shell_exec('stty -echo');
168
        $input = $this->read($default, $callback);
169
        shell_exec('stty echo');
170
171
        echo PHP_EOL;
172
173
        return $input;
174
    }
175
176
    /**
177
     * Read a line from configured stream (or terminal)
178
     *  in  windows Os but don't echo it back.
179
     * @param mixed $default
180
     * @param callable|null $callback The validator/sanitizer callback.
181
     * @return mixed
182
     */
183
    protected function readHiddenWindows($default = null, ?callable $callback = null)
184
    {
185
        $cmd = 'powershell -Command ' . implode('; ', array_filter([
186
                    '$pword = Read-Host -AsSecureString',
187
                    '$pword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword)',
188
                    '$pword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($pword)',
189
                    'echo $pword',
190
                ]));
191
192
        $input = '';
193
        $result = shell_exec($cmd);
194
195
        if ($result !== null) {
196
            $input = rtrim($result, "\r\n");
197
        }
198
199
        if ($input === '' && $default !== null) {
200
            return $default;
201
        }
202
203
        return $callback !== null
204
                ? $callback($input)
205
                : $input;
206
    }
207
}
208