統計
| ブランチ: | リビジョン:

pictcode / lib / Cake / Console / ConsoleOutput.php @ 0b1b8047

履歴 | 表示 | アノテート | ダウンロード (7.879 KB)

1
<?php
2
/**
3
 * ConsoleOutput file.
4
 *
5
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
6
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
7
 *
8
 * Licensed under The MIT License
9
 * For full copyright and license information, please see the LICENSE.txt
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
13
 * @link          http://cakephp.org CakePHP(tm) Project
14
 * @since         CakePHP(tm) v 2.0
15
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
16
 */
17

    
18
/**
19
 * Object wrapper for outputting information from a shell application.
20
 * Can be connected to any stream resource that can be used with fopen()
21
 *
22
 * Can generate colorized output on consoles that support it. There are a few
23
 * built in styles
24
 *
25
 * - `error` Error messages.
26
 * - `warning` Warning messages.
27
 * - `info` Informational messages.
28
 * - `comment` Additional text.
29
 * - `question` Magenta text used for user prompts
30
 *
31
 * By defining styles with addStyle() you can create custom console styles.
32
 *
33
 * ### Using styles in output
34
 *
35
 * You can format console output using tags with the name of the style to apply. From inside a shell object
36
 *
37
 * `$this->out('<warning>Overwrite:</warning> foo.php was overwritten.');`
38
 *
39
 * This would create orange 'Overwrite:' text, while the rest of the text would remain the normal color.
40
 * See ConsoleOutput::styles() to learn more about defining your own styles. Nested styles are not supported
41
 * at this time.
42
 *
43
 * @package       Cake.Console
44
 */
45
class ConsoleOutput {
46

    
47
/**
48
 * Raw output constant - no modification of output text.
49
 *
50
 * @var int
51
 */
52
        const RAW = 0;
53

    
54
/**
55
 * Plain output - tags will be stripped.
56
 *
57
 * @var int
58
 */
59
        const PLAIN = 1;
60

    
61
/**
62
 * Color output - Convert known tags in to ANSI color escape codes.
63
 *
64
 * @var int
65
 */
66
        const COLOR = 2;
67

    
68
/**
69
 * Constant for a newline.
70
 *
71
 * @var string
72
 */
73
        const LF = PHP_EOL;
74

    
75
/**
76
 * File handle for output.
77
 *
78
 * @var resource
79
 */
80
        protected $_output;
81

    
82
/**
83
 * The current output type. Manipulated with ConsoleOutput::outputAs();
84
 *
85
 * @var int
86
 */
87
        protected $_outputAs = self::COLOR;
88

    
89
/**
90
 * text colors used in colored output.
91
 *
92
 * @var array
93
 */
94
        protected static $_foregroundColors = array(
95
                'black' => 30,
96
                'red' => 31,
97
                'green' => 32,
98
                'yellow' => 33,
99
                'blue' => 34,
100
                'magenta' => 35,
101
                'cyan' => 36,
102
                'white' => 37
103
        );
104

    
105
/**
106
 * background colors used in colored output.
107
 *
108
 * @var array
109
 */
110
        protected static $_backgroundColors = array(
111
                'black' => 40,
112
                'red' => 41,
113
                'green' => 42,
114
                'yellow' => 43,
115
                'blue' => 44,
116
                'magenta' => 45,
117
                'cyan' => 46,
118
                'white' => 47
119
        );
120

    
121
/**
122
 * formatting options for colored output
123
 *
124
 * @var string
125
 */
126
        protected static $_options = array(
127
                'bold' => 1,
128
                'underline' => 4,
129
                'blink' => 5,
130
                'reverse' => 7,
131
        );
132

    
133
/**
134
 * Styles that are available as tags in console output.
135
 * You can modify these styles with ConsoleOutput::styles()
136
 *
137
 * @var array
138
 */
139
        protected static $_styles = array(
140
                'emergency' => array('text' => 'red', 'underline' => true),
141
                'alert' => array('text' => 'red', 'underline' => true),
142
                'critical' => array('text' => 'red', 'underline' => true),
143
                'error' => array('text' => 'red', 'underline' => true),
144
                'warning' => array('text' => 'yellow'),
145
                'info' => array('text' => 'cyan'),
146
                'debug' => array('text' => 'yellow'),
147
                'success' => array('text' => 'green'),
148
                'comment' => array('text' => 'blue'),
149
                'question' => array('text' => 'magenta'),
150
                'notice' => array('text' => 'cyan')
151
        );
152

    
153
/**
154
 * Construct the output object.
155
 *
156
 * Checks for a pretty console environment. Ansicon and ConEmu allows
157
 * pretty consoles on Windows, and is supported.
158
 *
159
 * @param string $stream The identifier of the stream to write output to.
160
 */
161
        public function __construct($stream = 'php://stdout') {
162
                $this->_output = fopen($stream, 'w');
163

    
164
                if ((DS === '\\' && !(bool)env('ANSICON') && env('ConEmuANSI') !== 'ON') ||
165
                        $stream === 'php://output' ||
166
                        (function_exists('posix_isatty') && !posix_isatty($this->_output))
167
                ) {
168
                        $this->_outputAs = static::PLAIN;
169
                }
170
        }
171

    
172
/**
173
 * Outputs a single or multiple messages to stdout. If no parameters
174
 * are passed, outputs just a newline.
175
 *
176
 * @param string|array $message A string or an array of strings to output
177
 * @param int $newlines Number of newlines to append
178
 * @return int Returns the number of bytes returned from writing to stdout.
179
 */
180
        public function write($message, $newlines = 1) {
181
                if (is_array($message)) {
182
                        $message = implode(static::LF, $message);
183
                }
184
                return $this->_write($this->styleText($message . str_repeat(static::LF, $newlines)));
185
        }
186

    
187
/**
188
 * Apply styling to text.
189
 *
190
 * @param string $text Text with styling tags.
191
 * @return string String with color codes added.
192
 */
193
        public function styleText($text) {
194
                if ($this->_outputAs == static::RAW) {
195
                        return $text;
196
                }
197
                if ($this->_outputAs == static::PLAIN) {
198
                        $tags = implode('|', array_keys(static::$_styles));
199
                        return preg_replace('#</?(?:' . $tags . ')>#', '', $text);
200
                }
201
                return preg_replace_callback(
202
                        '/<(?P<tag>[a-z0-9-_]+)>(?P<text>.*?)<\/(\1)>/ims', array($this, '_replaceTags'), $text
203
                );
204
        }
205

    
206
/**
207
 * Replace tags with color codes.
208
 *
209
 * @param array $matches An array of matches to replace.
210
 * @return string
211
 */
212
        protected function _replaceTags($matches) {
213
                $style = $this->styles($matches['tag']);
214
                if (empty($style)) {
215
                        return '<' . $matches['tag'] . '>' . $matches['text'] . '</' . $matches['tag'] . '>';
216
                }
217

    
218
                $styleInfo = array();
219
                if (!empty($style['text']) && isset(static::$_foregroundColors[$style['text']])) {
220
                        $styleInfo[] = static::$_foregroundColors[$style['text']];
221
                }
222
                if (!empty($style['background']) && isset(static::$_backgroundColors[$style['background']])) {
223
                        $styleInfo[] = static::$_backgroundColors[$style['background']];
224
                }
225
                unset($style['text'], $style['background']);
226
                foreach ($style as $option => $value) {
227
                        if ($value) {
228
                                $styleInfo[] = static::$_options[$option];
229
                        }
230
                }
231
                return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m";
232
        }
233

    
234
/**
235
 * Writes a message to the output stream.
236
 *
237
 * @param string $message Message to write.
238
 * @return bool success
239
 */
240
        protected function _write($message) {
241
                return fwrite($this->_output, $message);
242
        }
243

    
244
/**
245
 * Get the current styles offered, or append new ones in.
246
 *
247
 * ### Get a style definition
248
 *
249
 * `$this->output->styles('error');`
250
 *
251
 * ### Get all the style definitions
252
 *
253
 * `$this->output->styles();`
254
 *
255
 * ### Create or modify an existing style
256
 *
257
 * `$this->output->styles('annoy', array('text' => 'purple', 'background' => 'yellow', 'blink' => true));`
258
 *
259
 * ### Remove a style
260
 *
261
 * `$this->output->styles('annoy', false);`
262
 *
263
 * @param string $style The style to get or create.
264
 * @param array $definition The array definition of the style to change or create a style
265
 *   or false to remove a style.
266
 * @return mixed If you are getting styles, the style or null will be returned. If you are creating/modifying
267
 *   styles true will be returned.
268
 */
269
        public function styles($style = null, $definition = null) {
270
                if ($style === null && $definition === null) {
271
                        return static::$_styles;
272
                }
273
                if (is_string($style) && $definition === null) {
274
                        return isset(static::$_styles[$style]) ? static::$_styles[$style] : null;
275
                }
276
                if ($definition === false) {
277
                        unset(static::$_styles[$style]);
278
                        return true;
279
                }
280
                static::$_styles[$style] = $definition;
281
                return true;
282
        }
283

    
284
/**
285
 * Get/Set the output type to use. The output type how formatting tags are treated.
286
 *
287
 * @param int $type The output type to use. Should be one of the class constants.
288
 * @return mixed Either null or the value if getting.
289
 */
290
        public function outputAs($type = null) {
291
                if ($type === null) {
292
                        return $this->_outputAs;
293
                }
294
                $this->_outputAs = $type;
295
        }
296

    
297
/**
298
 * Clean up and close handles
299
 */
300
        public function __destruct() {
301
                if (is_resource($this->_output)) {
302
                        fclose($this->_output);
303
                }
304
        }
305

    
306
}