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 / Style / SymfonyStyle.php
matomo / app / vendor / prefixed / symfony / console / Style Last commit date
OutputStyle.php 1 year ago StyleInterface.php 1 year ago SymfonyStyle.php 1 year ago
SymfonyStyle.php
435 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\Style;
12
13 use Matomo\Dependencies\Symfony\Component\Console\Exception\InvalidArgumentException;
14 use Matomo\Dependencies\Symfony\Component\Console\Exception\RuntimeException;
15 use Matomo\Dependencies\Symfony\Component\Console\Formatter\OutputFormatter;
16 use Matomo\Dependencies\Symfony\Component\Console\Helper\Helper;
17 use Matomo\Dependencies\Symfony\Component\Console\Helper\ProgressBar;
18 use Matomo\Dependencies\Symfony\Component\Console\Helper\SymfonyQuestionHelper;
19 use Matomo\Dependencies\Symfony\Component\Console\Helper\Table;
20 use Matomo\Dependencies\Symfony\Component\Console\Helper\TableCell;
21 use Matomo\Dependencies\Symfony\Component\Console\Helper\TableSeparator;
22 use Matomo\Dependencies\Symfony\Component\Console\Input\InputInterface;
23 use Matomo\Dependencies\Symfony\Component\Console\Output\ConsoleOutputInterface;
24 use Matomo\Dependencies\Symfony\Component\Console\Output\OutputInterface;
25 use Matomo\Dependencies\Symfony\Component\Console\Output\TrimmedBufferOutput;
26 use Matomo\Dependencies\Symfony\Component\Console\Question\ChoiceQuestion;
27 use Matomo\Dependencies\Symfony\Component\Console\Question\ConfirmationQuestion;
28 use Matomo\Dependencies\Symfony\Component\Console\Question\Question;
29 use Matomo\Dependencies\Symfony\Component\Console\Terminal;
30 /**
31 * Output decorator helpers for the Symfony Style Guide.
32 *
33 * @author Kevin Bond <kevinbond@gmail.com>
34 */
35 class SymfonyStyle extends OutputStyle
36 {
37 public const MAX_LINE_LENGTH = 120;
38 private $input;
39 private $output;
40 private $questionHelper;
41 private $progressBar;
42 private $lineLength;
43 private $bufferedOutput;
44 public function __construct(InputInterface $input, OutputInterface $output)
45 {
46 $this->input = $input;
47 $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), \false, clone $output->getFormatter());
48 // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
49 $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
50 $this->lineLength = min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
51 parent::__construct($this->output = $output);
52 }
53 /**
54 * Formats a message as a block of text.
55 *
56 * @param string|array $messages The message to write in the block
57 */
58 public function block($messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \true)
59 {
60 $messages = \is_array($messages) ? array_values($messages) : [$messages];
61 $this->autoPrependBlock();
62 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
63 $this->newLine();
64 }
65 /**
66 * {@inheritdoc}
67 */
68 public function title(string $message)
69 {
70 $this->autoPrependBlock();
71 $this->writeln([sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), sprintf('<comment>%s</>', str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
72 $this->newLine();
73 }
74 /**
75 * {@inheritdoc}
76 */
77 public function section(string $message)
78 {
79 $this->autoPrependBlock();
80 $this->writeln([sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), sprintf('<comment>%s</>', str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
81 $this->newLine();
82 }
83 /**
84 * {@inheritdoc}
85 */
86 public function listing(array $elements)
87 {
88 $this->autoPrependText();
89 $elements = array_map(function ($element) {
90 return sprintf(' * %s', $element);
91 }, $elements);
92 $this->writeln($elements);
93 $this->newLine();
94 }
95 /**
96 * {@inheritdoc}
97 */
98 public function text($message)
99 {
100 $this->autoPrependText();
101 $messages = \is_array($message) ? array_values($message) : [$message];
102 foreach ($messages as $message) {
103 $this->writeln(sprintf(' %s', $message));
104 }
105 }
106 /**
107 * Formats a command comment.
108 *
109 * @param string|array $message
110 */
111 public function comment($message)
112 {
113 $this->block($message, null, null, '<fg=default;bg=default> // </>', \false, \false);
114 }
115 /**
116 * {@inheritdoc}
117 */
118 public function success($message)
119 {
120 $this->block($message, 'OK', 'fg=black;bg=green', ' ', \true);
121 }
122 /**
123 * {@inheritdoc}
124 */
125 public function error($message)
126 {
127 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', \true);
128 }
129 /**
130 * {@inheritdoc}
131 */
132 public function warning($message)
133 {
134 $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', \true);
135 }
136 /**
137 * {@inheritdoc}
138 */
139 public function note($message)
140 {
141 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
142 }
143 /**
144 * Formats an info message.
145 *
146 * @param string|array $message
147 */
148 public function info($message)
149 {
150 $this->block($message, 'INFO', 'fg=green', ' ', \true);
151 }
152 /**
153 * {@inheritdoc}
154 */
155 public function caution($message)
156 {
157 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', \true);
158 }
159 /**
160 * {@inheritdoc}
161 */
162 public function table(array $headers, array $rows)
163 {
164 $this->createTable()->setHeaders($headers)->setRows($rows)->render();
165 $this->newLine();
166 }
167 /**
168 * Formats a horizontal table.
169 */
170 public function horizontalTable(array $headers, array $rows)
171 {
172 $this->createTable()->setHorizontal(\true)->setHeaders($headers)->setRows($rows)->render();
173 $this->newLine();
174 }
175 /**
176 * Formats a list of key/value horizontally.
177 *
178 * Each row can be one of:
179 * * 'A title'
180 * * ['key' => 'value']
181 * * new TableSeparator()
182 *
183 * @param string|array|TableSeparator ...$list
184 */
185 public function definitionList(...$list)
186 {
187 $headers = [];
188 $row = [];
189 foreach ($list as $value) {
190 if ($value instanceof TableSeparator) {
191 $headers[] = $value;
192 $row[] = $value;
193 continue;
194 }
195 if (\is_string($value)) {
196 $headers[] = new TableCell($value, ['colspan' => 2]);
197 $row[] = null;
198 continue;
199 }
200 if (!\is_array($value)) {
201 throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
202 }
203 $headers[] = key($value);
204 $row[] = current($value);
205 }
206 $this->horizontalTable($headers, [$row]);
207 }
208 /**
209 * {@inheritdoc}
210 */
211 public function ask(string $question, ?string $default = null, ?callable $validator = null)
212 {
213 $question = new Question($question, $default);
214 $question->setValidator($validator);
215 return $this->askQuestion($question);
216 }
217 /**
218 * {@inheritdoc}
219 */
220 public function askHidden(string $question, ?callable $validator = null)
221 {
222 $question = new Question($question);
223 $question->setHidden(\true);
224 $question->setValidator($validator);
225 return $this->askQuestion($question);
226 }
227 /**
228 * {@inheritdoc}
229 */
230 public function confirm(string $question, bool $default = \true)
231 {
232 return $this->askQuestion(new ConfirmationQuestion($question, $default));
233 }
234 /**
235 * {@inheritdoc}
236 */
237 public function choice(string $question, array $choices, $default = null)
238 {
239 if (null !== $default) {
240 $values = array_flip($choices);
241 $default = $values[$default] ?? $default;
242 }
243 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
244 }
245 /**
246 * {@inheritdoc}
247 */
248 public function progressStart(int $max = 0)
249 {
250 $this->progressBar = $this->createProgressBar($max);
251 $this->progressBar->start();
252 }
253 /**
254 * {@inheritdoc}
255 */
256 public function progressAdvance(int $step = 1)
257 {
258 $this->getProgressBar()->advance($step);
259 }
260 /**
261 * {@inheritdoc}
262 */
263 public function progressFinish()
264 {
265 $this->getProgressBar()->finish();
266 $this->newLine(2);
267 $this->progressBar = null;
268 }
269 /**
270 * {@inheritdoc}
271 */
272 public function createProgressBar(int $max = 0)
273 {
274 $progressBar = parent::createProgressBar($max);
275 if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === getenv('TERM_PROGRAM')) {
276 $progressBar->setEmptyBarCharacter('');
277 // light shade character \u2591
278 $progressBar->setProgressCharacter('');
279 $progressBar->setBarCharacter('');
280 // dark shade character \u2593
281 }
282 return $progressBar;
283 }
284 /**
285 * @see ProgressBar::iterate()
286 */
287 public function progressIterate(iterable $iterable, ?int $max = null) : iterable
288 {
289 yield from $this->createProgressBar()->iterate($iterable, $max);
290 $this->newLine(2);
291 }
292 /**
293 * @return mixed
294 */
295 public function askQuestion(Question $question)
296 {
297 if ($this->input->isInteractive()) {
298 $this->autoPrependBlock();
299 }
300 if (!$this->questionHelper) {
301 $this->questionHelper = new SymfonyQuestionHelper();
302 }
303 $answer = $this->questionHelper->ask($this->input, $this, $question);
304 if ($this->input->isInteractive()) {
305 $this->newLine();
306 $this->bufferedOutput->write("\n");
307 }
308 return $answer;
309 }
310 /**
311 * {@inheritdoc}
312 */
313 public function writeln($messages, int $type = self::OUTPUT_NORMAL)
314 {
315 if (!is_iterable($messages)) {
316 $messages = [$messages];
317 }
318 foreach ($messages as $message) {
319 parent::writeln($message, $type);
320 $this->writeBuffer($message, \true, $type);
321 }
322 }
323 /**
324 * {@inheritdoc}
325 */
326 public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
327 {
328 if (!is_iterable($messages)) {
329 $messages = [$messages];
330 }
331 foreach ($messages as $message) {
332 parent::write($message, $newline, $type);
333 $this->writeBuffer($message, $newline, $type);
334 }
335 }
336 /**
337 * {@inheritdoc}
338 */
339 public function newLine(int $count = 1)
340 {
341 parent::newLine($count);
342 $this->bufferedOutput->write(str_repeat("\n", $count));
343 }
344 /**
345 * Returns a new instance which makes use of stderr if available.
346 *
347 * @return self
348 */
349 public function getErrorStyle()
350 {
351 return new self($this->input, $this->getErrorOutput());
352 }
353 public function createTable() : Table
354 {
355 $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
356 $style = clone Table::getStyleDefinition('symfony-style-guide');
357 $style->setCellHeaderFormat('<info>%s</info>');
358 return (new Table($output))->setStyle($style);
359 }
360 private function getProgressBar() : ProgressBar
361 {
362 if (!$this->progressBar) {
363 throw new RuntimeException('The ProgressBar is not started.');
364 }
365 return $this->progressBar;
366 }
367 private function autoPrependBlock() : void
368 {
369 $chars = substr(str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
370 if (!isset($chars[0])) {
371 $this->newLine();
372 // empty history, so we should start with a new line.
373 return;
374 }
375 // Prepend new line for each non LF chars (This means no blank line was output before)
376 $this->newLine(2 - substr_count($chars, "\n"));
377 }
378 private function autoPrependText() : void
379 {
380 $fetched = $this->bufferedOutput->fetch();
381 // Prepend new line if last char isn't EOL:
382 if (!str_ends_with($fetched, "\n")) {
383 $this->newLine();
384 }
385 }
386 private function writeBuffer(string $message, bool $newLine, int $type) : void
387 {
388 // We need to know if the last chars are PHP_EOL
389 $this->bufferedOutput->write($message, $newLine, $type);
390 }
391 private function createBlock(iterable $messages, ?string $type = null, ?string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \false) : array
392 {
393 $indentLength = 0;
394 $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
395 $lines = [];
396 if (null !== $type) {
397 $type = sprintf('[%s] ', $type);
398 $indentLength = \strlen($type);
399 $lineIndentation = str_repeat(' ', $indentLength);
400 }
401 // wrap and add newlines for each element
402 foreach ($messages as $key => $message) {
403 if ($escape) {
404 $message = OutputFormatter::escape($message);
405 }
406 $decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message));
407 $messageLineLength = min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength);
408 $messageLines = explode(\PHP_EOL, wordwrap($message, $messageLineLength, \PHP_EOL, \true));
409 foreach ($messageLines as $messageLine) {
410 $lines[] = $messageLine;
411 }
412 if (\count($messages) > 1 && $key < \count($messages) - 1) {
413 $lines[] = '';
414 }
415 }
416 $firstLineIndex = 0;
417 if ($padding && $this->isDecorated()) {
418 $firstLineIndex = 1;
419 array_unshift($lines, '');
420 $lines[] = '';
421 }
422 foreach ($lines as $i => &$line) {
423 if (null !== $type) {
424 $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line;
425 }
426 $line = $prefix . $line;
427 $line .= str_repeat(' ', max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
428 if ($style) {
429 $line = sprintf('<%s>%s</>', $style, $line);
430 }
431 }
432 return $lines;
433 }
434 }
435