Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * Hoa
5
 *
6
 *
7
 * @license
8
 *
9
 * New BSD License
10
 *
11
 * Copyright © 2007-2017, Hoa community. All rights reserved.
12
 *
13
 * Redistribution and use in source and binary forms, with or without
14
 * modification, are permitted provided that the following conditions are met:
15
 *     * Redistributions of source code must retain the above copyright
16
 *       notice, this list of conditions and the following disclaimer.
17
 *     * Redistributions in binary form must reproduce the above copyright
18
 *       notice, this list of conditions and the following disclaimer in the
19
 *       documentation and/or other materials provided with the distribution.
20
 *     * Neither the name of the Hoa nor the names of its contributors may be
21
 *       used to endorse or promote products derived from this software without
22
 *       specific prior written permission.
23
 *
24
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34
 * POSSIBILITY OF SUCH DAMAGE.
35
 */
36
 
37
namespace Psy\Readline\Hoa;
38
 
39
/**
40
 * Class \Hoa\Console.
41
 *
42
 * A set of utils and helpers about the console.
43
 */
44
class Console
45
{
46
    /**
47
     * Pipe mode: FIFO.
48
     */
49
    const IS_FIFO = 0;
50
 
51
    /**
52
     * Pipe mode: character.
53
     */
54
    const IS_CHARACTER = 1;
55
 
56
    /**
57
     * Pipe mode: directory.
58
     */
59
    const IS_DIRECTORY = 2;
60
 
61
    /**
62
     * Pipe mode: block.
63
     */
64
    const IS_BLOCK = 3;
65
 
66
    /**
67
     * Pipe mode: regular.
68
     */
69
    const IS_REGULAR = 4;
70
 
71
    /**
72
     * Pipe mode: link.
73
     */
74
    const IS_LINK = 5;
75
 
76
    /**
77
     * Pipe mode: socket.
78
     */
79
    const IS_SOCKET = 6;
80
 
81
    /**
82
     * Pipe mode: whiteout.
83
     */
84
    const IS_WHITEOUT = 7;
85
 
86
    /**
87
     * Advanced interaction is on.
88
     */
89
    private static $_advanced = null;
90
 
91
    /**
92
     * Previous STTY configuration.
93
     */
94
    private static $_old = null;
95
 
96
    /**
97
     * Mode.
98
     */
99
    protected static $_mode = [];
100
 
101
    /**
102
     * Input.
103
     */
104
    protected static $_input = null;
105
 
106
    /**
107
     * Output.
108
     */
109
    protected static $_output = null;
110
 
111
    /**
112
     * Tput.
113
     */
114
    protected static $_tput = null;
115
 
116
    /**
117
     * Prepare the environment for advanced interactions.
118
     */
119
    public static function advancedInteraction(bool $force = false): bool
120
    {
121
        if (null !== self::$_advanced) {
122
            return self::$_advanced;
123
        }
124
 
125
        if (\defined('PHP_WINDOWS_VERSION_PLATFORM')) {
126
            return self::$_advanced = false;
127
        }
128
 
129
        if (false === $force &&
130
            true === \defined('STDIN') &&
131
            false === self::isDirect(\STDIN)) {
132
            return self::$_advanced = false;
133
        }
134
 
135
        self::$_old = ConsoleProcessus::execute('stty -g < /dev/tty', false);
136
        ConsoleProcessus::execute('stty -echo -icanon min 1 time 0 < /dev/tty', false);
137
 
138
        return self::$_advanced = true;
139
    }
140
 
141
    /**
142
     * Restore previous interaction options.
143
     */
144
    public static function restoreInteraction()
145
    {
146
        if (null === self::$_old) {
147
            return;
148
        }
149
 
150
        ConsoleProcessus::execute('stty '.self::$_old.' < /dev/tty', false);
151
 
152
        return;
153
    }
154
 
155
    /**
156
     * Get mode of a certain pipe.
157
     * Inspired by sys/stat.h.
158
     */
159
    public static function getMode($pipe = \STDIN): int
160
    {
161
        $_pipe = (int) $pipe;
162
 
163
        if (isset(self::$_mode[$_pipe])) {
164
            return self::$_mode[$_pipe];
165
        }
166
 
167
        $stat = \fstat($pipe);
168
 
169
        switch ($stat['mode'] & 0170000) {
170
            // named pipe (fifo).
171
            case 0010000:
172
                $mode = self::IS_FIFO;
173
 
174
                break;
175
 
176
            // character special.
177
            case 0020000:
178
                $mode = self::IS_CHARACTER;
179
 
180
                break;
181
 
182
            // directory.
183
            case 0040000:
184
                $mode = self::IS_DIRECTORY;
185
 
186
                break;
187
 
188
            // block special.
189
            case 0060000:
190
                $mode = self::IS_BLOCK;
191
 
192
                break;
193
 
194
            // regular.
195
            case 0100000:
196
                $mode = self::IS_REGULAR;
197
 
198
                break;
199
 
200
            // symbolic link.
201
            case 0120000:
202
                $mode = self::IS_LINK;
203
 
204
                 break;
205
 
206
            // socket.
207
            case 0140000:
208
                $mode = self::IS_SOCKET;
209
 
210
                break;
211
 
212
            // whiteout.
213
            case 0160000:
214
                $mode = self::IS_WHITEOUT;
215
 
216
                break;
217
 
218
            default:
219
                $mode = -1;
220
        }
221
 
222
        return self::$_mode[$_pipe] = $mode;
223
    }
224
 
225
    /**
226
     * Check whether a certain pipe is a character device (keyboard, screen
227
     * etc.).
228
     * For example:
229
     *     $ php Mode.php
230
     * In this case, self::isDirect(STDOUT) will return true.
231
     */
232
    public static function isDirect($pipe): bool
233
    {
234
        return self::IS_CHARACTER === self::getMode($pipe);
235
    }
236
 
237
    /**
238
     * Check whether a certain pipe is a pipe.
239
     * For example:
240
     *     $ php Mode.php | foobar
241
     * In this case, self::isPipe(STDOUT) will return true.
242
     */
243
    public static function isPipe($pipe): bool
244
    {
245
        return self::IS_FIFO === self::getMode($pipe);
246
    }
247
 
248
    /**
249
     * Check whether a certain pipe is a redirection.
250
     * For example:
251
     *     $ php Mode.php < foobar
252
     * In this case, self::isRedirection(STDIN) will return true.
253
     */
254
    public static function isRedirection($pipe): bool
255
    {
256
        $mode = self::getMode($pipe);
257
 
258
        return
259
            self::IS_REGULAR === $mode ||
260
            self::IS_DIRECTORY === $mode ||
261
            self::IS_LINK === $mode ||
262
            self::IS_SOCKET === $mode ||
263
            self::IS_BLOCK === $mode;
264
    }
265
 
266
    /**
267
     * Set input layer.
268
     */
269
    public static function setInput(ConsoleInput $input)
270
    {
271
        $old = static::$_input;
272
        static::$_input = $input;
273
 
274
        return $old;
275
    }
276
 
277
    /**
278
     * Get input layer.
279
     */
280
    public static function getInput(): ConsoleInput
281
    {
282
        if (null === static::$_input) {
283
            static::$_input = new ConsoleInput();
284
        }
285
 
286
        return static::$_input;
287
    }
288
 
289
    /**
290
     * Set output layer.
291
     */
292
    public static function setOutput(ConsoleOutput $output)
293
    {
294
        $old = static::$_output;
295
        static::$_output = $output;
296
 
297
        return $old;
298
    }
299
 
300
    /**
301
     * Get output layer.
302
     */
303
    public static function getOutput(): ConsoleOutput
304
    {
305
        if (null === static::$_output) {
306
            static::$_output = new ConsoleOutput();
307
        }
308
 
309
        return static::$_output;
310
    }
311
 
312
    /**
313
     * Set tput.
314
     */
315
    public static function setTput(ConsoleTput $tput)
316
    {
317
        $old = static::$_tput;
318
        static::$_tput = $tput;
319
 
320
        return $old;
321
    }
322
 
323
    /**
324
     * Get the current tput instance of the current process.
325
     */
326
    public static function getTput(): ConsoleTput
327
    {
328
        if (null === static::$_tput) {
329
            static::$_tput = new ConsoleTput();
330
        }
331
 
332
        return static::$_tput;
333
    }
334
 
335
    /**
336
     * Check whether we are running behind TMUX(1).
337
     */
338
    public static function isTmuxRunning(): bool
339
    {
340
        return isset($_SERVER['TMUX']);
341
    }
342
}
343
 
344
/*
345
 * Restore interaction.
346
 */
347
\register_shutdown_function([Console::class, 'restoreInteraction']);