Reader   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 58
dl 0
loc 156
rs 10
c 2
b 0
f 0
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
A readHidden() 0 13 2
A setStream() 0 4 1
A __construct() 0 15 3
A readAll() 0 7 2
A readHiddenWindows() 0 23 5
A readPipe() 0 19 5
A read() 0 16 5
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
use Platine\Console\Exception\RuntimeException;
52
53
/**
54
 * @class Reader
55
 * @package Platine\Console\Input
56
 */
57
class Reader
58
{
59
    /**
60
     * The input stream
61
     * @var resource
62
     */
63
    protected $stream;
64
65
    /**
66
     * Create new instance
67
     * @param string|null $path the input read path
68
     */
69
    public function __construct(?string $path = null)
70
    {
71
        $stream = STDIN;
72
        if ($path !== null) {
73
            $stream = fopen($path, 'r');
74
75
            if ($stream === false) {
76
                throw new RuntimeException(sprintf(
77
                    'Can not open stream using path [%s]',
78
                    $path
79
                ));
80
            }
81
        }
82
83
        $this->stream = $stream;
84
    }
85
86
    /**
87
     * Set the stream
88
     * @param resource $stream
89
     * @return $this
90
     */
91
    public function setStream($stream)
92
    {
93
        $this->stream = $stream;
94
        return $this;
95
    }
96
97
98
    /**
99
     * Read the user input
100
     * @param mixed $default
101
     * @param callable|null $callback The validator/sanitizer callback.
102
     * @return mixed
103
     */
104
    public function read($default = null, ?callable $callback = null)
105
    {
106
        $input = '';
107
        $read = fgets($this->stream);
108
109
        if ($read !== false) {
110
            $input = rtrim($read, "\r\n");
111
        }
112
113
        if ($input === '' && $default !== null) {
114
            return $default;
115
        }
116
117
        return $callback !== null
118
                ? $callback($input)
119
                : $input;
120
    }
121
122
    /**
123
     * Read all line of the user input
124
     * @param callable|null $callback The validator/sanitizer callback.
125
     * @return mixed
126
     */
127
    public function readAll(?callable $callback = null)
128
    {
129
        $input = stream_get_contents($this->stream);
130
131
        return $callback !== null
132
                ? $callback($input)
133
                : $input;
134
    }
135
136
    /**
137
     * Read content piped to the stream without waiting.
138
     * @param callable|null $callback The validator/sanitizer callback.
139
     * @return mixed
140
     */
141
    public function readPipe(?callable $callback = null)
142
    {
143
        $stdin = '';
144
        $read = [$this->stream];
145
        $write = [];
146
        $except = [];
147
148
        if (stream_select($read, $write, $except, 0) === 1) {
149
            while ($line = fgets($this->stream)) {
150
                $stdin .= $line;
151
            }
152
        }
153
154
        if ($stdin === '') {
155
            return $callback !== null
156
                ? $callback($this)
157
                : '';
158
        }
159
        return $stdin;
160
    }
161
162
    /**
163
     * Read a line from configured stream (or terminal) but don't echo it back.
164
     * @param mixed $default
165
     * @param callable|null $callback The validator/sanitizer callback.
166
     * @return mixed
167
     */
168
    public function readHidden($default = null, ?callable $callback = null)
169
    {
170
        if (substr(strtoupper(PHP_OS), 0, 3) === 'WIN') {
171
            return $this->readHiddenWindows($default, $callback);
172
        }
173
174
        shell_exec('stty -echo');
175
        $input = $this->read($default, $callback);
176
        shell_exec('stty echo');
177
178
        echo PHP_EOL;
179
180
        return $input;
181
    }
182
183
    /**
184
     * Read a line from configured stream (or terminal)
185
     *  in  windows Os but don't echo it back.
186
     * @param mixed $default
187
     * @param callable|null $callback The validation/sanitizer callback.
188
     * @return mixed
189
     */
190
    protected function readHiddenWindows($default = null, ?callable $callback = null)
191
    {
192
        $cmd = 'powershell -Command ' . implode('; ', [
193
                    '$pword = Read-Host -AsSecureString',
194
                    '$pword = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($pword)',
195
                    '$pword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($pword)',
196
                    'echo $pword',
197
                ]);
198
199
        $input = '';
200
        $result = shell_exec($cmd);
201
202
        if ($result !== null) {
203
            $input = rtrim($result, "\r\n");
204
        }
205
206
        if ($input === '' && $default !== null) {
207
            return $default;
208
        }
209
210
        return $callback !== null
211
                ? $callback($input)
212
                : $input;
213
    }
214
}
215