Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
12345 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 allows pretty consoles
157
 * 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')) {
165
			$this->_outputAs = self::PLAIN;
166
		}
167
	}
168
 
169
/**
170
 * Outputs a single or multiple messages to stdout. If no parameters
171
 * are passed, outputs just a newline.
172
 *
173
 * @param string|array $message A string or a an array of strings to output
174
 * @param int $newlines Number of newlines to append
175
 * @return int Returns the number of bytes returned from writing to stdout.
176
 */
177
	public function write($message, $newlines = 1) {
178
		if (is_array($message)) {
179
			$message = implode(self::LF, $message);
180
		}
181
		return $this->_write($this->styleText($message . str_repeat(self::LF, $newlines)));
182
	}
183
 
184
/**
185
 * Apply styling to text.
186
 *
187
 * @param string $text Text with styling tags.
188
 * @return string String with color codes added.
189
 */
190
	public function styleText($text) {
191
		if ($this->_outputAs == self::RAW) {
192
			return $text;
193
		}
194
		if ($this->_outputAs == self::PLAIN) {
195
			$tags = implode('|', array_keys(self::$_styles));
196
			return preg_replace('#</?(?:' . $tags . ')>#', '', $text);
197
		}
198
		return preg_replace_callback(
199
			'/<(?P<tag>[a-z0-9-_]+)>(?P<text>.*?)<\/(\1)>/ims', array($this, '_replaceTags'), $text
200
		);
201
	}
202
 
203
/**
204
 * Replace tags with color codes.
205
 *
206
 * @param array $matches An array of matches to replace.
207
 * @return string
208
 */
209
	protected function _replaceTags($matches) {
210
		$style = $this->styles($matches['tag']);
211
		if (empty($style)) {
212
			return '<' . $matches['tag'] . '>' . $matches['text'] . '</' . $matches['tag'] . '>';
213
		}
214
 
215
		$styleInfo = array();
216
		if (!empty($style['text']) && isset(self::$_foregroundColors[$style['text']])) {
217
			$styleInfo[] = self::$_foregroundColors[$style['text']];
218
		}
219
		if (!empty($style['background']) && isset(self::$_backgroundColors[$style['background']])) {
220
			$styleInfo[] = self::$_backgroundColors[$style['background']];
221
		}
222
		unset($style['text'], $style['background']);
223
		foreach ($style as $option => $value) {
224
			if ($value) {
225
				$styleInfo[] = self::$_options[$option];
226
			}
227
		}
228
		return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m";
229
	}
230
 
231
/**
232
 * Writes a message to the output stream.
233
 *
234
 * @param string $message Message to write.
235
 * @return bool success
236
 */
237
	protected function _write($message) {
238
		return fwrite($this->_output, $message);
239
	}
240
 
241
/**
242
 * Get the current styles offered, or append new ones in.
243
 *
244
 * ### Get a style definition
245
 *
246
 * `$this->output->styles('error');`
247
 *
248
 * ### Get all the style definitions
249
 *
250
 * `$this->output->styles();`
251
 *
252
 * ### Create or modify an existing style
253
 *
254
 * `$this->output->styles('annoy', array('text' => 'purple', 'background' => 'yellow', 'blink' => true));`
255
 *
256
 * ### Remove a style
257
 *
258
 * `$this->output->styles('annoy', false);`
259
 *
260
 * @param string $style The style to get or create.
261
 * @param array $definition The array definition of the style to change or create a style
262
 *   or false to remove a style.
263
 * @return mixed If you are getting styles, the style or null will be returned. If you are creating/modifying
264
 *   styles true will be returned.
265
 */
266
	public function styles($style = null, $definition = null) {
267
		if ($style === null && $definition === null) {
268
			return self::$_styles;
269
		}
270
		if (is_string($style) && $definition === null) {
271
			return isset(self::$_styles[$style]) ? self::$_styles[$style] : null;
272
		}
273
		if ($definition === false) {
274
			unset(self::$_styles[$style]);
275
			return true;
276
		}
277
		self::$_styles[$style] = $definition;
278
		return true;
279
	}
280
 
281
/**
282
 * Get/Set the output type to use. The output type how formatting tags are treated.
283
 *
284
 * @param int $type The output type to use. Should be one of the class constants.
285
 * @return mixed Either null or the value if getting.
286
 */
287
	public function outputAs($type = null) {
288
		if ($type === null) {
289
			return $this->_outputAs;
290
		}
291
		$this->_outputAs = $type;
292
	}
293
 
294
/**
295
 * Clean up and close handles
296
 */
297
	public function __destruct() {
298
		if (is_resource($this->_output)) {
299
			fclose($this->_output);
300
		}
301
	}
302
 
303
}