Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
16591 anikendra 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
}