Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
13532 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
	const RAW = 0;
51
 
52
/**
53
 * Plain output - tags will be stripped.
54
 */
55
	const PLAIN = 1;
56
 
57
/**
58
 * Color output - Convert known tags in to ANSI color escape codes.
59
 */
60
	const COLOR = 2;
61
 
62
/**
63
 * Constant for a newline.
64
 */
65
	const LF = PHP_EOL;
66
 
67
/**
68
 * File handle for output.
69
 *
70
 * @var resource
71
 */
72
	protected $_output;
73
 
74
/**
75
 * The current output type. Manipulated with ConsoleOutput::outputAs();
76
 *
77
 * @var integer
78
 */
79
	protected $_outputAs = self::COLOR;
80
 
81
/**
82
 * text colors used in colored output.
83
 *
84
 * @var array
85
 */
86
	protected static $_foregroundColors = array(
87
		'black' => 30,
88
		'red' => 31,
89
		'green' => 32,
90
		'yellow' => 33,
91
		'blue' => 34,
92
		'magenta' => 35,
93
		'cyan' => 36,
94
		'white' => 37
95
	);
96
 
97
/**
98
 * background colors used in colored output.
99
 *
100
 * @var array
101
 */
102
	protected static $_backgroundColors = array(
103
		'black' => 40,
104
		'red' => 41,
105
		'green' => 42,
106
		'yellow' => 43,
107
		'blue' => 44,
108
		'magenta' => 45,
109
		'cyan' => 46,
110
		'white' => 47
111
	);
112
 
113
/**
114
 * formatting options for colored output
115
 *
116
 * @var string
117
 */
118
	protected static $_options = array(
119
		'bold' => 1,
120
		'underline' => 4,
121
		'blink' => 5,
122
		'reverse' => 7,
123
	);
124
 
125
/**
126
 * Styles that are available as tags in console output.
127
 * You can modify these styles with ConsoleOutput::styles()
128
 *
129
 * @var array
130
 */
131
	protected static $_styles = array(
132
		'emergency' => array('text' => 'red', 'underline' => true),
133
		'alert' => array('text' => 'red', 'underline' => true),
134
		'critical' => array('text' => 'red', 'underline' => true),
135
		'error' => array('text' => 'red', 'underline' => true),
136
		'warning' => array('text' => 'yellow'),
137
		'info' => array('text' => 'cyan'),
138
		'debug' => array('text' => 'yellow'),
139
		'success' => array('text' => 'green'),
140
		'comment' => array('text' => 'blue'),
141
		'question' => array('text' => 'magenta'),
142
		'notice' => array('text' => 'cyan')
143
	);
144
 
145
/**
146
 * Construct the output object.
147
 *
148
 * Checks for a pretty console environment. Ansicon allows pretty consoles
149
 * on windows, and is supported.
150
 *
151
 * @param string $stream The identifier of the stream to write output to.
152
 */
153
	public function __construct($stream = 'php://stdout') {
154
		$this->_output = fopen($stream, 'w');
155
 
156
		if (DS === '\\' && !(bool)env('ANSICON')) {
157
			$this->_outputAs = self::PLAIN;
158
		}
159
	}
160
 
161
/**
162
 * Outputs a single or multiple messages to stdout. If no parameters
163
 * are passed, outputs just a newline.
164
 *
165
 * @param string|array $message A string or a an array of strings to output
166
 * @param integer $newlines Number of newlines to append
167
 * @return integer Returns the number of bytes returned from writing to stdout.
168
 */
169
	public function write($message, $newlines = 1) {
170
		if (is_array($message)) {
171
			$message = implode(self::LF, $message);
172
		}
173
		return $this->_write($this->styleText($message . str_repeat(self::LF, $newlines)));
174
	}
175
 
176
/**
177
 * Apply styling to text.
178
 *
179
 * @param string $text Text with styling tags.
180
 * @return string String with color codes added.
181
 */
182
	public function styleText($text) {
183
		if ($this->_outputAs == self::RAW) {
184
			return $text;
185
		}
186
		if ($this->_outputAs == self::PLAIN) {
187
			$tags = implode('|', array_keys(self::$_styles));
188
			return preg_replace('#</?(?:' . $tags . ')>#', '', $text);
189
		}
190
		return preg_replace_callback(
191
			'/<(?P<tag>[a-z0-9-_]+)>(?P<text>.*?)<\/(\1)>/ims', array($this, '_replaceTags'), $text
192
		);
193
	}
194
 
195
/**
196
 * Replace tags with color codes.
197
 *
198
 * @param array $matches.
199
 * @return string
200
 */
201
	protected function _replaceTags($matches) {
202
		$style = $this->styles($matches['tag']);
203
		if (empty($style)) {
204
			return '<' . $matches['tag'] . '>' . $matches['text'] . '</' . $matches['tag'] . '>';
205
		}
206
 
207
		$styleInfo = array();
208
		if (!empty($style['text']) && isset(self::$_foregroundColors[$style['text']])) {
209
			$styleInfo[] = self::$_foregroundColors[$style['text']];
210
		}
211
		if (!empty($style['background']) && isset(self::$_backgroundColors[$style['background']])) {
212
			$styleInfo[] = self::$_backgroundColors[$style['background']];
213
		}
214
		unset($style['text'], $style['background']);
215
		foreach ($style as $option => $value) {
216
			if ($value) {
217
				$styleInfo[] = self::$_options[$option];
218
			}
219
		}
220
		return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m";
221
	}
222
 
223
/**
224
 * Writes a message to the output stream.
225
 *
226
 * @param string $message Message to write.
227
 * @return boolean success
228
 */
229
	protected function _write($message) {
230
		return fwrite($this->_output, $message);
231
	}
232
 
233
/**
234
 * Get the current styles offered, or append new ones in.
235
 *
236
 * ### Get a style definition
237
 *
238
 * `$this->output->styles('error');`
239
 *
240
 * ### Get all the style definitions
241
 *
242
 * `$this->output->styles();`
243
 *
244
 * ### Create or modify an existing style
245
 *
246
 * `$this->output->styles('annoy', array('text' => 'purple', 'background' => 'yellow', 'blink' => true));`
247
 *
248
 * ### Remove a style
249
 *
250
 * `$this->output->styles('annoy', false);`
251
 *
252
 * @param string $style The style to get or create.
253
 * @param array $definition The array definition of the style to change or create a style
254
 *   or false to remove a style.
255
 * @return mixed If you are getting styles, the style or null will be returned. If you are creating/modifying
256
 *   styles true will be returned.
257
 */
258
	public function styles($style = null, $definition = null) {
259
		if ($style === null && $definition === null) {
260
			return self::$_styles;
261
		}
262
		if (is_string($style) && $definition === null) {
263
			return isset(self::$_styles[$style]) ? self::$_styles[$style] : null;
264
		}
265
		if ($definition === false) {
266
			unset(self::$_styles[$style]);
267
			return true;
268
		}
269
		self::$_styles[$style] = $definition;
270
		return true;
271
	}
272
 
273
/**
274
 * Get/Set the output type to use. The output type how formatting tags are treated.
275
 *
276
 * @param integer $type The output type to use. Should be one of the class constants.
277
 * @return mixed Either null or the value if getting.
278
 */
279
	public function outputAs($type = null) {
280
		if ($type === null) {
281
			return $this->_outputAs;
282
		}
283
		$this->_outputAs = $type;
284
	}
285
 
286
/**
287
 * Clean up and close handles
288
 */
289
	public function __destruct() {
290
		fclose($this->_output);
291
	}
292
 
293
}