PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.8.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.8.2
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / vendor / prefixed / symfony / console / Formatter / OutputFormatter.php
matomo / app / vendor / prefixed / symfony / console / Formatter Last commit date
NullOutputFormatter.php 1 year ago NullOutputFormatterStyle.php 2 years ago OutputFormatter.php 1 year ago OutputFormatterInterface.php 2 years ago OutputFormatterStyle.php 1 year ago OutputFormatterStyleInterface.php 2 years ago OutputFormatterStyleStack.php 1 year ago WrappableOutputFormatterInterface.php 2 years ago
OutputFormatter.php
250 lines
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11 namespace Matomo\Dependencies\Symfony\Component\Console\Formatter;
12
13 use Matomo\Dependencies\Symfony\Component\Console\Exception\InvalidArgumentException;
14 use function Matomo\Dependencies\Symfony\Component\String\b;
15 /**
16 * Formatter class for console output.
17 *
18 * @author Konstantin Kudryashov <ever.zet@gmail.com>
19 * @author Roland Franssen <franssen.roland@gmail.com>
20 */
21 class OutputFormatter implements WrappableOutputFormatterInterface
22 {
23 private $decorated;
24 private $styles = [];
25 private $styleStack;
26 public function __clone()
27 {
28 $this->styleStack = clone $this->styleStack;
29 foreach ($this->styles as $key => $value) {
30 $this->styles[$key] = clone $value;
31 }
32 }
33 /**
34 * Escapes "<" and ">" special chars in given text.
35 *
36 * @return string
37 */
38 public static function escape(string $text)
39 {
40 $text = preg_replace('/([^\\\\]|^)([<>])/', '$1\\\\$2', $text);
41 return self::escapeTrailingBackslash($text);
42 }
43 /**
44 * Escapes trailing "\" in given text.
45 *
46 * @internal
47 */
48 public static function escapeTrailingBackslash(string $text) : string
49 {
50 if (str_ends_with($text, '\\')) {
51 $len = \strlen($text);
52 $text = rtrim($text, '\\');
53 $text = str_replace("\x00", '', $text);
54 $text .= str_repeat("\x00", $len - \strlen($text));
55 }
56 return $text;
57 }
58 /**
59 * Initializes console output formatter.
60 *
61 * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
62 */
63 public function __construct(bool $decorated = \false, array $styles = [])
64 {
65 $this->decorated = $decorated;
66 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
67 $this->setStyle('info', new OutputFormatterStyle('green'));
68 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
69 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
70 foreach ($styles as $name => $style) {
71 $this->setStyle($name, $style);
72 }
73 $this->styleStack = new OutputFormatterStyleStack();
74 }
75 /**
76 * {@inheritdoc}
77 */
78 public function setDecorated(bool $decorated)
79 {
80 $this->decorated = $decorated;
81 }
82 /**
83 * {@inheritdoc}
84 */
85 public function isDecorated()
86 {
87 return $this->decorated;
88 }
89 /**
90 * {@inheritdoc}
91 */
92 public function setStyle(string $name, OutputFormatterStyleInterface $style)
93 {
94 $this->styles[strtolower($name)] = $style;
95 }
96 /**
97 * {@inheritdoc}
98 */
99 public function hasStyle(string $name)
100 {
101 return isset($this->styles[strtolower($name)]);
102 }
103 /**
104 * {@inheritdoc}
105 */
106 public function getStyle(string $name)
107 {
108 if (!$this->hasStyle($name)) {
109 throw new InvalidArgumentException(sprintf('Undefined style: "%s".', $name));
110 }
111 return $this->styles[strtolower($name)];
112 }
113 /**
114 * {@inheritdoc}
115 */
116 public function format(?string $message)
117 {
118 return $this->formatAndWrap($message, 0);
119 }
120 /**
121 * {@inheritdoc}
122 */
123 public function formatAndWrap(?string $message, int $width)
124 {
125 if (null === $message) {
126 return '';
127 }
128 $offset = 0;
129 $output = '';
130 $openTagRegex = '[a-z](?:[^\\\\<>]*+ | \\\\.)*';
131 $closeTagRegex = '[a-z][^<>]*+';
132 $currentLineLength = 0;
133 preg_match_all("#<(({$openTagRegex}) | /({$closeTagRegex})?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE);
134 foreach ($matches[0] as $i => $match) {
135 $pos = $match[1];
136 $text = $match[0];
137 if (0 != $pos && '\\' == $message[$pos - 1]) {
138 continue;
139 }
140 // add the text up to the next tag
141 $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
142 $offset = $pos + \strlen($text);
143 // opening tag?
144 if ($open = '/' != $text[1]) {
145 $tag = $matches[1][$i][0];
146 } else {
147 $tag = $matches[3][$i][0] ?? '';
148 }
149 if (!$open && !$tag) {
150 // </>
151 $this->styleStack->pop();
152 } elseif (null === ($style = $this->createStyleFromString($tag))) {
153 $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
154 } elseif ($open) {
155 $this->styleStack->push($style);
156 } else {
157 $this->styleStack->pop($style);
158 }
159 }
160 $output .= $this->applyCurrentStyle(substr($message, $offset), $output, $width, $currentLineLength);
161 return strtr($output, ["\x00" => '\\', '\\<' => '<', '\\>' => '>']);
162 }
163 /**
164 * @return OutputFormatterStyleStack
165 */
166 public function getStyleStack()
167 {
168 return $this->styleStack;
169 }
170 /**
171 * Tries to create new style instance from string.
172 */
173 private function createStyleFromString(string $string) : ?OutputFormatterStyleInterface
174 {
175 if (isset($this->styles[$string])) {
176 return $this->styles[$string];
177 }
178 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) {
179 return null;
180 }
181 $style = new OutputFormatterStyle();
182 foreach ($matches as $match) {
183 array_shift($match);
184 $match[0] = strtolower($match[0]);
185 if ('fg' == $match[0]) {
186 $style->setForeground(strtolower($match[1]));
187 } elseif ('bg' == $match[0]) {
188 $style->setBackground(strtolower($match[1]));
189 } elseif ('href' === $match[0]) {
190 $url = preg_replace('{\\\\([<>])}', '$1', $match[1]);
191 $style->setHref($url);
192 } elseif ('options' === $match[0]) {
193 preg_match_all('([^,;]+)', strtolower($match[1]), $options);
194 $options = array_shift($options);
195 foreach ($options as $option) {
196 $style->setOption($option);
197 }
198 } else {
199 return null;
200 }
201 }
202 return $style;
203 }
204 /**
205 * Applies current style from stack to text, if must be applied.
206 */
207 private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength) : string
208 {
209 if ('' === $text) {
210 return '';
211 }
212 if (!$width) {
213 return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text;
214 }
215 if (!$currentLineLength && '' !== $current) {
216 $text = ltrim($text);
217 }
218 if ($currentLineLength) {
219 $prefix = substr($text, 0, $i = $width - $currentLineLength) . "\n";
220 $text = substr($text, $i);
221 } else {
222 $prefix = '';
223 }
224 preg_match('~(\\n)$~', $text, $matches);
225 $text = $prefix . $this->addLineBreaks($text, $width);
226 $text = rtrim($text, "\n") . ($matches[1] ?? '');
227 if (!$currentLineLength && '' !== $current && "\n" !== substr($current, -1)) {
228 $text = "\n" . $text;
229 }
230 $lines = explode("\n", $text);
231 foreach ($lines as $line) {
232 $currentLineLength += \strlen($line);
233 if ($width <= $currentLineLength) {
234 $currentLineLength = 0;
235 }
236 }
237 if ($this->isDecorated()) {
238 foreach ($lines as $i => $line) {
239 $lines[$i] = $this->styleStack->getCurrent()->apply($line);
240 }
241 }
242 return implode("\n", $lines);
243 }
244 private function addLineBreaks(string $text, int $width) : string
245 {
246 $encoding = mb_detect_encoding($text, null, \true) ?: 'UTF-8';
247 return b($text)->toCodePointString($encoding)->wordwrap($width, "\n", \true)->toByteString($encoding);
248 }
249 }
250