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 / Helper / ProgressBar.php
matomo / app / vendor / prefixed / symfony / console / Helper Last commit date
DebugFormatterHelper.php 1 year ago DescriptorHelper.php 1 year ago Dumper.php 1 year ago FormatterHelper.php 1 year ago Helper.php 1 year ago HelperInterface.php 2 years ago HelperSet.php 2 years ago InputAwareHelper.php 2 years ago ProcessHelper.php 2 years ago ProgressBar.php 1 year ago ProgressIndicator.php 1 year ago QuestionHelper.php 1 year ago SymfonyQuestionHelper.php 1 year ago Table.php 1 year ago TableCell.php 2 years ago TableCellStyle.php 2 years ago TableRows.php 2 years ago TableSeparator.php 2 years ago TableStyle.php 1 year ago
ProgressBar.php
503 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\Helper;
12
13 use Matomo\Dependencies\Symfony\Component\Console\Cursor;
14 use Matomo\Dependencies\Symfony\Component\Console\Exception\LogicException;
15 use Matomo\Dependencies\Symfony\Component\Console\Output\ConsoleOutputInterface;
16 use Matomo\Dependencies\Symfony\Component\Console\Output\ConsoleSectionOutput;
17 use Matomo\Dependencies\Symfony\Component\Console\Output\OutputInterface;
18 use Matomo\Dependencies\Symfony\Component\Console\Terminal;
19 /**
20 * The ProgressBar provides helpers to display progress output.
21 *
22 * @author Fabien Potencier <fabien@symfony.com>
23 * @author Chris Jones <leeked@gmail.com>
24 */
25 final class ProgressBar
26 {
27 public const FORMAT_VERBOSE = 'verbose';
28 public const FORMAT_VERY_VERBOSE = 'very_verbose';
29 public const FORMAT_DEBUG = 'debug';
30 public const FORMAT_NORMAL = 'normal';
31 private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
32 private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
33 private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
34 private const FORMAT_NORMAL_NOMAX = 'normal_nomax';
35 private $barWidth = 28;
36 private $barChar;
37 private $emptyBarChar = '-';
38 private $progressChar = '>';
39 private $format;
40 private $internalFormat;
41 private $redrawFreq = 1;
42 private $writeCount;
43 private $lastWriteTime;
44 private $minSecondsBetweenRedraws = 0;
45 private $maxSecondsBetweenRedraws = 1;
46 private $output;
47 private $step = 0;
48 private $max;
49 private $startTime;
50 private $stepWidth;
51 private $percent = 0.0;
52 private $messages = [];
53 private $overwrite = \true;
54 private $terminal;
55 private $previousMessage;
56 private $cursor;
57 private static $formatters;
58 private static $formats;
59 /**
60 * @param int $max Maximum steps (0 if unknown)
61 */
62 public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
63 {
64 if ($output instanceof ConsoleOutputInterface) {
65 $output = $output->getErrorOutput();
66 }
67 $this->output = $output;
68 $this->setMaxSteps($max);
69 $this->terminal = new Terminal();
70 if (0 < $minSecondsBetweenRedraws) {
71 $this->redrawFreq = null;
72 $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws;
73 }
74 if (!$this->output->isDecorated()) {
75 // disable overwrite when output does not support ANSI codes.
76 $this->overwrite = \false;
77 // set a reasonable redraw frequency so output isn't flooded
78 $this->redrawFreq = null;
79 }
80 $this->startTime = time();
81 $this->cursor = new Cursor($output);
82 }
83 /**
84 * Sets a placeholder formatter for a given name.
85 *
86 * This method also allow you to override an existing placeholder.
87 *
88 * @param string $name The placeholder name (including the delimiter char like %)
89 * @param callable $callable A PHP callable
90 */
91 public static function setPlaceholderFormatterDefinition(string $name, callable $callable) : void
92 {
93 if (!self::$formatters) {
94 self::$formatters = self::initPlaceholderFormatters();
95 }
96 self::$formatters[$name] = $callable;
97 }
98 /**
99 * Gets the placeholder formatter for a given name.
100 *
101 * @param string $name The placeholder name (including the delimiter char like %)
102 */
103 public static function getPlaceholderFormatterDefinition(string $name) : ?callable
104 {
105 if (!self::$formatters) {
106 self::$formatters = self::initPlaceholderFormatters();
107 }
108 return self::$formatters[$name] ?? null;
109 }
110 /**
111 * Sets a format for a given name.
112 *
113 * This method also allow you to override an existing format.
114 *
115 * @param string $name The format name
116 * @param string $format A format string
117 */
118 public static function setFormatDefinition(string $name, string $format) : void
119 {
120 if (!self::$formats) {
121 self::$formats = self::initFormats();
122 }
123 self::$formats[$name] = $format;
124 }
125 /**
126 * Gets the format for a given name.
127 *
128 * @param string $name The format name
129 */
130 public static function getFormatDefinition(string $name) : ?string
131 {
132 if (!self::$formats) {
133 self::$formats = self::initFormats();
134 }
135 return self::$formats[$name] ?? null;
136 }
137 /**
138 * Associates a text with a named placeholder.
139 *
140 * The text is displayed when the progress bar is rendered but only
141 * when the corresponding placeholder is part of the custom format line
142 * (by wrapping the name with %).
143 *
144 * @param string $message The text to associate with the placeholder
145 * @param string $name The name of the placeholder
146 */
147 public function setMessage(string $message, string $name = 'message')
148 {
149 $this->messages[$name] = $message;
150 }
151 /**
152 * @return string|null
153 */
154 public function getMessage(string $name = 'message')
155 {
156 return $this->messages[$name] ?? null;
157 }
158 public function getStartTime() : int
159 {
160 return $this->startTime;
161 }
162 public function getMaxSteps() : int
163 {
164 return $this->max;
165 }
166 public function getProgress() : int
167 {
168 return $this->step;
169 }
170 private function getStepWidth() : int
171 {
172 return $this->stepWidth;
173 }
174 public function getProgressPercent() : float
175 {
176 return $this->percent;
177 }
178 public function getBarOffset() : float
179 {
180 return floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
181 }
182 public function getEstimated() : float
183 {
184 if (!$this->step) {
185 return 0;
186 }
187 return round((time() - $this->startTime) / $this->step * $this->max);
188 }
189 public function getRemaining() : float
190 {
191 if (!$this->step) {
192 return 0;
193 }
194 return round((time() - $this->startTime) / $this->step * ($this->max - $this->step));
195 }
196 public function setBarWidth(int $size)
197 {
198 $this->barWidth = max(1, $size);
199 }
200 public function getBarWidth() : int
201 {
202 return $this->barWidth;
203 }
204 public function setBarCharacter(string $char)
205 {
206 $this->barChar = $char;
207 }
208 public function getBarCharacter() : string
209 {
210 return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
211 }
212 public function setEmptyBarCharacter(string $char)
213 {
214 $this->emptyBarChar = $char;
215 }
216 public function getEmptyBarCharacter() : string
217 {
218 return $this->emptyBarChar;
219 }
220 public function setProgressCharacter(string $char)
221 {
222 $this->progressChar = $char;
223 }
224 public function getProgressCharacter() : string
225 {
226 return $this->progressChar;
227 }
228 public function setFormat(string $format)
229 {
230 $this->format = null;
231 $this->internalFormat = $format;
232 }
233 /**
234 * Sets the redraw frequency.
235 *
236 * @param int|null $freq The frequency in steps
237 */
238 public function setRedrawFrequency(?int $freq)
239 {
240 $this->redrawFreq = null !== $freq ? max(1, $freq) : null;
241 }
242 public function minSecondsBetweenRedraws(float $seconds) : void
243 {
244 $this->minSecondsBetweenRedraws = $seconds;
245 }
246 public function maxSecondsBetweenRedraws(float $seconds) : void
247 {
248 $this->maxSecondsBetweenRedraws = $seconds;
249 }
250 /**
251 * Returns an iterator that will automatically update the progress bar when iterated.
252 *
253 * @param int|null $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
254 */
255 public function iterate(iterable $iterable, ?int $max = null) : iterable
256 {
257 $this->start($max ?? (is_countable($iterable) ? \count($iterable) : 0));
258 foreach ($iterable as $key => $value) {
259 (yield $key => $value);
260 $this->advance();
261 }
262 $this->finish();
263 }
264 /**
265 * Starts the progress output.
266 *
267 * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
268 */
269 public function start(?int $max = null)
270 {
271 $this->startTime = time();
272 $this->step = 0;
273 $this->percent = 0.0;
274 if (null !== $max) {
275 $this->setMaxSteps($max);
276 }
277 $this->display();
278 }
279 /**
280 * Advances the progress output X steps.
281 *
282 * @param int $step Number of steps to advance
283 */
284 public function advance(int $step = 1)
285 {
286 $this->setProgress($this->step + $step);
287 }
288 /**
289 * Sets whether to overwrite the progressbar, false for new line.
290 */
291 public function setOverwrite(bool $overwrite)
292 {
293 $this->overwrite = $overwrite;
294 }
295 public function setProgress(int $step)
296 {
297 if ($this->max && $step > $this->max) {
298 $this->max = $step;
299 } elseif ($step < 0) {
300 $step = 0;
301 }
302 $redrawFreq = $this->redrawFreq ?? ($this->max ?: 10) / 10;
303 $prevPeriod = (int) ($this->step / $redrawFreq);
304 $currPeriod = (int) ($step / $redrawFreq);
305 $this->step = $step;
306 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
307 $timeInterval = microtime(\true) - $this->lastWriteTime;
308 // Draw regardless of other limits
309 if ($this->max === $step) {
310 $this->display();
311 return;
312 }
313 // Throttling
314 if ($timeInterval < $this->minSecondsBetweenRedraws) {
315 return;
316 }
317 // Draw each step period, but not too late
318 if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) {
319 $this->display();
320 }
321 }
322 public function setMaxSteps(int $max)
323 {
324 $this->format = null;
325 $this->max = max(0, $max);
326 $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4;
327 }
328 /**
329 * Finishes the progress output.
330 */
331 public function finish() : void
332 {
333 if (!$this->max) {
334 $this->max = $this->step;
335 }
336 if ($this->step === $this->max && !$this->overwrite) {
337 // prevent double 100% output
338 return;
339 }
340 $this->setProgress($this->max);
341 }
342 /**
343 * Outputs the current progress string.
344 */
345 public function display() : void
346 {
347 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
348 return;
349 }
350 if (null === $this->format) {
351 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
352 }
353 $this->overwrite($this->buildLine());
354 }
355 /**
356 * Removes the progress bar from the current line.
357 *
358 * This is useful if you wish to write some output
359 * while a progress bar is running.
360 * Call display() to show the progress bar again.
361 */
362 public function clear() : void
363 {
364 if (!$this->overwrite) {
365 return;
366 }
367 if (null === $this->format) {
368 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
369 }
370 $this->overwrite('');
371 }
372 private function setRealFormat(string $format)
373 {
374 // try to use the _nomax variant if available
375 if (!$this->max && null !== self::getFormatDefinition($format . '_nomax')) {
376 $this->format = self::getFormatDefinition($format . '_nomax');
377 } elseif (null !== self::getFormatDefinition($format)) {
378 $this->format = self::getFormatDefinition($format);
379 } else {
380 $this->format = $format;
381 }
382 }
383 /**
384 * Overwrites a previous message to the output.
385 */
386 private function overwrite(string $message) : void
387 {
388 if ($this->previousMessage === $message) {
389 return;
390 }
391 $originalMessage = $message;
392 if ($this->overwrite) {
393 if (null !== $this->previousMessage) {
394 if ($this->output instanceof ConsoleSectionOutput) {
395 $messageLines = explode("\n", $this->previousMessage);
396 $lineCount = \count($messageLines);
397 foreach ($messageLines as $messageLine) {
398 $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
399 if ($messageLineLength > $this->terminal->getWidth()) {
400 $lineCount += floor($messageLineLength / $this->terminal->getWidth());
401 }
402 }
403 $this->output->clear($lineCount);
404 } else {
405 $lineCount = substr_count($this->previousMessage, "\n");
406 for ($i = 0; $i < $lineCount; ++$i) {
407 $this->cursor->moveToColumn(1);
408 $this->cursor->clearLine();
409 $this->cursor->moveUp();
410 }
411 $this->cursor->moveToColumn(1);
412 $this->cursor->clearLine();
413 }
414 }
415 } elseif ($this->step > 0) {
416 $message = \PHP_EOL . $message;
417 }
418 $this->previousMessage = $originalMessage;
419 $this->lastWriteTime = microtime(\true);
420 $this->output->write($message);
421 ++$this->writeCount;
422 }
423 private function determineBestFormat() : string
424 {
425 switch ($this->output->getVerbosity()) {
426 // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
427 case OutputInterface::VERBOSITY_VERBOSE:
428 return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX;
429 case OutputInterface::VERBOSITY_VERY_VERBOSE:
430 return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX;
431 case OutputInterface::VERBOSITY_DEBUG:
432 return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX;
433 default:
434 return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX;
435 }
436 }
437 private static function initPlaceholderFormatters() : array
438 {
439 return ['bar' => function (self $bar, OutputInterface $output) {
440 $completeBars = $bar->getBarOffset();
441 $display = str_repeat($bar->getBarCharacter(), $completeBars);
442 if ($completeBars < $bar->getBarWidth()) {
443 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
444 $display .= $bar->getProgressCharacter() . str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
445 }
446 return $display;
447 }, 'elapsed' => function (self $bar) {
448 return Helper::formatTime(time() - $bar->getStartTime());
449 }, 'remaining' => function (self $bar) {
450 if (!$bar->getMaxSteps()) {
451 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
452 }
453 return Helper::formatTime($bar->getRemaining());
454 }, 'estimated' => function (self $bar) {
455 if (!$bar->getMaxSteps()) {
456 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
457 }
458 return Helper::formatTime($bar->getEstimated());
459 }, 'memory' => function (self $bar) {
460 return Helper::formatMemory(memory_get_usage(\true));
461 }, 'current' => function (self $bar) {
462 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT);
463 }, 'max' => function (self $bar) {
464 return $bar->getMaxSteps();
465 }, 'percent' => function (self $bar) {
466 return floor($bar->getProgressPercent() * 100);
467 }];
468 }
469 private static function initFormats() : array
470 {
471 return [self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%'];
472 }
473 private function buildLine() : string
474 {
475 $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i";
476 $callback = function ($matches) {
477 if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
478 $text = $formatter($this, $this->output);
479 } elseif (isset($this->messages[$matches[1]])) {
480 $text = $this->messages[$matches[1]];
481 } else {
482 return $matches[0];
483 }
484 if (isset($matches[2])) {
485 $text = sprintf('%' . $matches[2], $text);
486 }
487 return $text;
488 };
489 $line = preg_replace_callback($regex, $callback, $this->format);
490 // gets string length for each sub line with multiline format
491 $linesLength = array_map(function ($subLine) {
492 return Helper::width(Helper::removeDecoration($this->output->getFormatter(), rtrim($subLine, "\r")));
493 }, explode("\n", $line));
494 $linesWidth = max($linesLength);
495 $terminalWidth = $this->terminal->getWidth();
496 if ($linesWidth <= $terminalWidth) {
497 return $line;
498 }
499 $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);
500 return preg_replace_callback($regex, $callback, $this->format);
501 }
502 }
503