1 <?php
2 /**
3 * Part of the Joomla Framework Application Package
4 *
5 * @copyright Copyright (C) 2005 - 2016 Open Source Matters, Inc. All rights reserved.
6 * @license GNU General Public License version 2 or later; see LICENSE
7 */
8
9 namespace Joomla\Application\Cli\Output\Processor;
10
11 use Joomla\Application\Cli\ColorStyle;
12 use Joomla\Application\Cli\Output\Stdout;
13
14 /**
15 * Class ColorProcessor.
16 *
17 * @since 1.0
18 */
19 class ColorProcessor implements ProcessorInterface
20 {
21 /**
22 * Flag to remove color codes from the output
23 *
24 * @var boolean
25 * @since 1.0
26 */
27 public $noColors = false;
28
29 /**
30 * Regex to match tags
31 *
32 * @var string
33 * @since 1.0
34 */
35 protected $tagFilter = '/<([a-z=;]+)>(.*?)<\/\\1>/s';
36
37 /**
38 * Regex used for removing color codes
39 *
40 * @var string
41 * @since 1.0
42 */
43 protected static $stripFilter = '/<[\/]?[a-z=;]+>/';
44
45 /**
46 * Array of ColorStyle objects
47 *
48 * @var array
49 * @since 1.0
50 */
51 protected $styles = array();
52
53 /**
54 * Class constructor
55 *
56 * @param boolean $noColors Defines non-colored mode on construct
57 *
58 * @since 1.1.0
59 */
60 public function __construct($noColors = null)
61 {
62 if (is_null($noColors))
63 {
64 /*
65 * By default windows cmd.exe and PowerShell does not support ANSI-colored output
66 * if the variable is not set explicitly colors should be disabled on Windows
67 */
68 $noColors = (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN');
69 }
70
71 $this->noColors = $noColors;
72
73 $this->addPredefinedStyles();
74 }
75
76 /**
77 * Add a style.
78 *
79 * @param string $name The style name.
80 * @param ColorStyle $style The color style.
81 *
82 * @return ColorProcessor Instance of $this to allow chaining.
83 *
84 * @since 1.0
85 */
86 public function addStyle($name, ColorStyle $style)
87 {
88 $this->styles[$name] = $style;
89
90 return $this;
91 }
92
93 /**
94 * Strip color tags from a string.
95 *
96 * @param string $string The string.
97 *
98 * @return string
99 *
100 * @since 1.0
101 */
102 public static function stripColors($string)
103 {
104 return preg_replace(static::$stripFilter, '', $string);
105 }
106
107 /**
108 * Process a string.
109 *
110 * @param string $string The string to process.
111 *
112 * @return string
113 *
114 * @since 1.0
115 */
116 public function process($string)
117 {
118 preg_match_all($this->tagFilter, $string, $matches);
119
120 if (!$matches)
121 {
122 return $string;
123 }
124
125 foreach ($matches[0] as $i => $m)
126 {
127 if (array_key_exists($matches[1][$i], $this->styles))
128 {
129 $string = $this->replaceColors($string, $matches[1][$i], $matches[2][$i], $this->styles[$matches[1][$i]]);
130 }
131 // Custom format
132 elseif (strpos($matches[1][$i], '='))
133 {
134 $string = $this->replaceColors($string, $matches[1][$i], $matches[2][$i], ColorStyle::fromString($matches[1][$i]));
135 }
136 }
137
138 return $string;
139 }
140
141 /**
142 * Replace color tags in a string.
143 *
144 * @param string $text The original text.
145 * @param string $tag The matched tag.
146 * @param string $match The match.
147 * @param ColorStyle $style The color style to apply.
148 *
149 * @return mixed
150 *
151 * @since 1.0
152 */
153 private function replaceColors($text, $tag, $match, Colorstyle $style)
154 {
155 $replace = $this->noColors
156 ? $match
157 : "\033[" . $style . "m" . $match . "\033[0m";
158
159 return str_replace('<' . $tag . '>' . $match . '</' . $tag . '>', $replace, $text);
160 }
161
162 /**
163 * Adds predefined color styles to the ColorProcessor object
164 *
165 * @return Stdout Instance of $this to allow chaining.
166 *
167 * @since 1.0
168 */
169 private function addPredefinedStyles()
170 {
171 $this->addStyle(
172 'info',
173 new ColorStyle('green', '', array('bold'))
174 );
175
176 $this->addStyle(
177 'comment',
178 new ColorStyle('yellow', '', array('bold'))
179 );
180
181 $this->addStyle(
182 'question',
183 new ColorStyle('black', 'cyan')
184 );
185
186 $this->addStyle(
187 'error',
188 new ColorStyle('white', 'red')
189 );
190
191 return $this;
192 }
193 }
194