[ Index ]

PHP Cross Reference of phpBB-3.2.11-deutsch

title

Body

[close]

/vendor/symfony/console/Helper/ -> ProgressBar.php (source)

   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  
  12  namespace Symfony\Component\Console\Helper;
  13  
  14  use Symfony\Component\Console\Exception\LogicException;
  15  use Symfony\Component\Console\Output\ConsoleOutputInterface;
  16  use Symfony\Component\Console\Output\OutputInterface;
  17  
  18  /**
  19   * The ProgressBar provides helpers to display progress output.
  20   *
  21   * @author Fabien Potencier <fabien@symfony.com>
  22   * @author Chris Jones <leeked@gmail.com>
  23   */
  24  class ProgressBar
  25  {
  26      private $barWidth = 28;
  27      private $barChar;
  28      private $emptyBarChar = '-';
  29      private $progressChar = '>';
  30      private $format;
  31      private $internalFormat;
  32      private $redrawFreq = 1;
  33      private $output;
  34      private $step = 0;
  35      private $max;
  36      private $startTime;
  37      private $stepWidth;
  38      private $percent = 0.0;
  39      private $formatLineCount;
  40      private $messages = array();
  41      private $overwrite = true;
  42      private $firstRun = true;
  43  
  44      private static $formatters;
  45      private static $formats;
  46  
  47      /**
  48       * @param OutputInterface $output An OutputInterface instance
  49       * @param int             $max    Maximum steps (0 if unknown)
  50       */
  51      public function __construct(OutputInterface $output, $max = 0)
  52      {
  53          if ($output instanceof ConsoleOutputInterface) {
  54              $output = $output->getErrorOutput();
  55          }
  56  
  57          $this->output = $output;
  58          $this->setMaxSteps($max);
  59  
  60          if (!$this->output->isDecorated()) {
  61              // disable overwrite when output does not support ANSI codes.
  62              $this->overwrite = false;
  63  
  64              // set a reasonable redraw frequency so output isn't flooded
  65              $this->setRedrawFrequency($max / 10);
  66          }
  67  
  68          $this->startTime = time();
  69      }
  70  
  71      /**
  72       * Sets a placeholder formatter for a given name.
  73       *
  74       * This method also allow you to override an existing placeholder.
  75       *
  76       * @param string   $name     The placeholder name (including the delimiter char like %)
  77       * @param callable $callable A PHP callable
  78       */
  79      public static function setPlaceholderFormatterDefinition($name, $callable)
  80      {
  81          if (!self::$formatters) {
  82              self::$formatters = self::initPlaceholderFormatters();
  83          }
  84  
  85          self::$formatters[$name] = $callable;
  86      }
  87  
  88      /**
  89       * Gets the placeholder formatter for a given name.
  90       *
  91       * @param string $name The placeholder name (including the delimiter char like %)
  92       *
  93       * @return callable|null A PHP callable
  94       */
  95      public static function getPlaceholderFormatterDefinition($name)
  96      {
  97          if (!self::$formatters) {
  98              self::$formatters = self::initPlaceholderFormatters();
  99          }
 100  
 101          return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
 102      }
 103  
 104      /**
 105       * Sets a format for a given name.
 106       *
 107       * This method also allow you to override an existing format.
 108       *
 109       * @param string $name   The format name
 110       * @param string $format A format string
 111       */
 112      public static function setFormatDefinition($name, $format)
 113      {
 114          if (!self::$formats) {
 115              self::$formats = self::initFormats();
 116          }
 117  
 118          self::$formats[$name] = $format;
 119      }
 120  
 121      /**
 122       * Gets the format for a given name.
 123       *
 124       * @param string $name The format name
 125       *
 126       * @return string|null A format string
 127       */
 128      public static function getFormatDefinition($name)
 129      {
 130          if (!self::$formats) {
 131              self::$formats = self::initFormats();
 132          }
 133  
 134          return isset(self::$formats[$name]) ? self::$formats[$name] : null;
 135      }
 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($message, $name = 'message')
 148      {
 149          $this->messages[$name] = $message;
 150      }
 151  
 152      public function getMessage($name = 'message')
 153      {
 154          return $this->messages[$name];
 155      }
 156  
 157      /**
 158       * Gets the progress bar start time.
 159       *
 160       * @return int The progress bar start time
 161       */
 162      public function getStartTime()
 163      {
 164          return $this->startTime;
 165      }
 166  
 167      /**
 168       * Gets the progress bar maximal steps.
 169       *
 170       * @return int The progress bar max steps
 171       */
 172      public function getMaxSteps()
 173      {
 174          return $this->max;
 175      }
 176  
 177      /**
 178       * Gets the progress bar step.
 179       *
 180       * @deprecated since version 2.6, to be removed in 3.0. Use {@link getProgress()} instead.
 181       *
 182       * @return int The progress bar step
 183       */
 184      public function getStep()
 185      {
 186          @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the getProgress() method instead.', E_USER_DEPRECATED);
 187  
 188          return $this->getProgress();
 189      }
 190  
 191      /**
 192       * Gets the current step position.
 193       *
 194       * @return int The progress bar step
 195       */
 196      public function getProgress()
 197      {
 198          return $this->step;
 199      }
 200  
 201      /**
 202       * Gets the progress bar step width.
 203       *
 204       * @internal This method is public for PHP 5.3 compatibility, it should not be used.
 205       *
 206       * @return int The progress bar step width
 207       */
 208      public function getStepWidth()
 209      {
 210          return $this->stepWidth;
 211      }
 212  
 213      /**
 214       * Gets the current progress bar percent.
 215       *
 216       * @return float The current progress bar percent
 217       */
 218      public function getProgressPercent()
 219      {
 220          return $this->percent;
 221      }
 222  
 223      /**
 224       * Sets the progress bar width.
 225       *
 226       * @param int $size The progress bar size
 227       */
 228      public function setBarWidth($size)
 229      {
 230          $this->barWidth = (int) $size;
 231      }
 232  
 233      /**
 234       * Gets the progress bar width.
 235       *
 236       * @return int The progress bar size
 237       */
 238      public function getBarWidth()
 239      {
 240          return $this->barWidth;
 241      }
 242  
 243      /**
 244       * Sets the bar character.
 245       *
 246       * @param string $char A character
 247       */
 248      public function setBarCharacter($char)
 249      {
 250          $this->barChar = $char;
 251      }
 252  
 253      /**
 254       * Gets the bar character.
 255       *
 256       * @return string A character
 257       */
 258      public function getBarCharacter()
 259      {
 260          if (null === $this->barChar) {
 261              return $this->max ? '=' : $this->emptyBarChar;
 262          }
 263  
 264          return $this->barChar;
 265      }
 266  
 267      /**
 268       * Sets the empty bar character.
 269       *
 270       * @param string $char A character
 271       */
 272      public function setEmptyBarCharacter($char)
 273      {
 274          $this->emptyBarChar = $char;
 275      }
 276  
 277      /**
 278       * Gets the empty bar character.
 279       *
 280       * @return string A character
 281       */
 282      public function getEmptyBarCharacter()
 283      {
 284          return $this->emptyBarChar;
 285      }
 286  
 287      /**
 288       * Sets the progress bar character.
 289       *
 290       * @param string $char A character
 291       */
 292      public function setProgressCharacter($char)
 293      {
 294          $this->progressChar = $char;
 295      }
 296  
 297      /**
 298       * Gets the progress bar character.
 299       *
 300       * @return string A character
 301       */
 302      public function getProgressCharacter()
 303      {
 304          return $this->progressChar;
 305      }
 306  
 307      /**
 308       * Sets the progress bar format.
 309       *
 310       * @param string $format The format
 311       */
 312      public function setFormat($format)
 313      {
 314          $this->format = null;
 315          $this->internalFormat = $format;
 316      }
 317  
 318      /**
 319       * Sets the redraw frequency.
 320       *
 321       * @param int|float $freq The frequency in steps
 322       */
 323      public function setRedrawFrequency($freq)
 324      {
 325          $this->redrawFreq = max((int) $freq, 1);
 326      }
 327  
 328      /**
 329       * Starts the progress output.
 330       *
 331       * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
 332       */
 333      public function start($max = null)
 334      {
 335          $this->startTime = time();
 336          $this->step = 0;
 337          $this->percent = 0.0;
 338  
 339          if (null !== $max) {
 340              $this->setMaxSteps($max);
 341          }
 342  
 343          $this->display();
 344      }
 345  
 346      /**
 347       * Advances the progress output X steps.
 348       *
 349       * @param int $step Number of steps to advance
 350       *
 351       * @throws LogicException
 352       */
 353      public function advance($step = 1)
 354      {
 355          $this->setProgress($this->step + $step);
 356      }
 357  
 358      /**
 359       * Sets the current progress.
 360       *
 361       * @deprecated since version 2.6, to be removed in 3.0. Use {@link setProgress()} instead.
 362       *
 363       * @param int $step The current progress
 364       *
 365       * @throws LogicException
 366       */
 367      public function setCurrent($step)
 368      {
 369          @trigger_error('The '.__METHOD__.' method is deprecated since Symfony 2.6 and will be removed in 3.0. Use the setProgress() method instead.', E_USER_DEPRECATED);
 370  
 371          $this->setProgress($step);
 372      }
 373  
 374      /**
 375       * Sets whether to overwrite the progressbar, false for new line.
 376       *
 377       * @param bool $overwrite
 378       */
 379      public function setOverwrite($overwrite)
 380      {
 381          $this->overwrite = (bool) $overwrite;
 382      }
 383  
 384      /**
 385       * Sets the current progress.
 386       *
 387       * @param int $step The current progress
 388       *
 389       * @throws LogicException
 390       */
 391      public function setProgress($step)
 392      {
 393          $step = (int) $step;
 394          if ($step < $this->step) {
 395              throw new LogicException('You can\'t regress the progress bar.');
 396          }
 397  
 398          if ($this->max && $step > $this->max) {
 399              $this->max = $step;
 400          }
 401  
 402          $prevPeriod = (int) ($this->step / $this->redrawFreq);
 403          $currPeriod = (int) ($step / $this->redrawFreq);
 404          $this->step = $step;
 405          $this->percent = $this->max ? (float) $this->step / $this->max : 0;
 406          if ($prevPeriod !== $currPeriod || $this->max === $step) {
 407              $this->display();
 408          }
 409      }
 410  
 411      /**
 412       * Finishes the progress output.
 413       */
 414      public function finish()
 415      {
 416          if (!$this->max) {
 417              $this->max = $this->step;
 418          }
 419  
 420          if ($this->step === $this->max && !$this->overwrite) {
 421              // prevent double 100% output
 422              return;
 423          }
 424  
 425          $this->setProgress($this->max);
 426      }
 427  
 428      /**
 429       * Outputs the current progress string.
 430       */
 431      public function display()
 432      {
 433          if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
 434              return;
 435          }
 436  
 437          if (null === $this->format) {
 438              $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
 439          }
 440  
 441          // these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.
 442          $self = $this;
 443          $output = $this->output;
 444          $messages = $this->messages;
 445          $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
 446              if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
 447                  $text = \call_user_func($formatter, $self, $output);
 448              } elseif (isset($messages[$matches[1]])) {
 449                  $text = $messages[$matches[1]];
 450              } else {
 451                  return $matches[0];
 452              }
 453  
 454              if (isset($matches[2])) {
 455                  $text = sprintf('%'.$matches[2], $text);
 456              }
 457  
 458              return $text;
 459          }, $this->format));
 460      }
 461  
 462      /**
 463       * Removes the progress bar from the current line.
 464       *
 465       * This is useful if you wish to write some output
 466       * while a progress bar is running.
 467       * Call display() to show the progress bar again.
 468       */
 469      public function clear()
 470      {
 471          if (!$this->overwrite) {
 472              return;
 473          }
 474  
 475          if (null === $this->format) {
 476              $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
 477          }
 478  
 479          $this->overwrite('');
 480      }
 481  
 482      /**
 483       * Sets the progress bar format.
 484       *
 485       * @param string $format The format
 486       */
 487      private function setRealFormat($format)
 488      {
 489          // try to use the _nomax variant if available
 490          if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
 491              $this->format = self::getFormatDefinition($format.'_nomax');
 492          } elseif (null !== self::getFormatDefinition($format)) {
 493              $this->format = self::getFormatDefinition($format);
 494          } else {
 495              $this->format = $format;
 496          }
 497  
 498          $this->formatLineCount = substr_count($this->format, "\n");
 499      }
 500  
 501      /**
 502       * Sets the progress bar maximal steps.
 503       *
 504       * @param int $max The progress bar max steps
 505       */
 506      private function setMaxSteps($max)
 507      {
 508          $this->max = max(0, (int) $max);
 509          $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
 510      }
 511  
 512      /**
 513       * Overwrites a previous message to the output.
 514       *
 515       * @param string $message The message
 516       */
 517      private function overwrite($message)
 518      {
 519          if ($this->overwrite) {
 520              if (!$this->firstRun) {
 521                  // Move the cursor to the beginning of the line
 522                  $this->output->write("\x0D");
 523  
 524                  // Erase the line
 525                  $this->output->write("\x1B[2K");
 526  
 527                  // Erase previous lines
 528                  if ($this->formatLineCount > 0) {
 529                      $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
 530                  }
 531              }
 532          } elseif ($this->step > 0) {
 533              $this->output->writeln('');
 534          }
 535  
 536          $this->firstRun = false;
 537  
 538          $this->output->write($message);
 539      }
 540  
 541      private function determineBestFormat()
 542      {
 543          switch ($this->output->getVerbosity()) {
 544              // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
 545              case OutputInterface::VERBOSITY_VERBOSE:
 546                  return $this->max ? 'verbose' : 'verbose_nomax';
 547              case OutputInterface::VERBOSITY_VERY_VERBOSE:
 548                  return $this->max ? 'very_verbose' : 'very_verbose_nomax';
 549              case OutputInterface::VERBOSITY_DEBUG:
 550                  return $this->max ? 'debug' : 'debug_nomax';
 551              default:
 552                  return $this->max ? 'normal' : 'normal_nomax';
 553          }
 554      }
 555  
 556      private static function initPlaceholderFormatters()
 557      {
 558          return array(
 559              'bar' => function (ProgressBar $bar, OutputInterface $output) {
 560                  $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
 561                  $display = str_repeat($bar->getBarCharacter(), $completeBars);
 562                  if ($completeBars < $bar->getBarWidth()) {
 563                      $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
 564                      $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
 565                  }
 566  
 567                  return $display;
 568              },
 569              'elapsed' => function (ProgressBar $bar) {
 570                  return Helper::formatTime(time() - $bar->getStartTime());
 571              },
 572              'remaining' => function (ProgressBar $bar) {
 573                  if (!$bar->getMaxSteps()) {
 574                      throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
 575                  }
 576  
 577                  if (!$bar->getProgress()) {
 578                      $remaining = 0;
 579                  } else {
 580                      $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
 581                  }
 582  
 583                  return Helper::formatTime($remaining);
 584              },
 585              'estimated' => function (ProgressBar $bar) {
 586                  if (!$bar->getMaxSteps()) {
 587                      throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
 588                  }
 589  
 590                  if (!$bar->getProgress()) {
 591                      $estimated = 0;
 592                  } else {
 593                      $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
 594                  }
 595  
 596                  return Helper::formatTime($estimated);
 597              },
 598              'memory' => function (ProgressBar $bar) {
 599                  return Helper::formatMemory(memory_get_usage(true));
 600              },
 601              'current' => function (ProgressBar $bar) {
 602                  return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
 603              },
 604              'max' => function (ProgressBar $bar) {
 605                  return $bar->getMaxSteps();
 606              },
 607              'percent' => function (ProgressBar $bar) {
 608                  return floor($bar->getProgressPercent() * 100);
 609              },
 610          );
 611      }
 612  
 613      private static function initFormats()
 614      {
 615          return array(
 616              'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
 617              'normal_nomax' => ' %current% [%bar%]',
 618  
 619              'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
 620              'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
 621  
 622              'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
 623              'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
 624  
 625              'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
 626              'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
 627          );
 628      }
 629  }


Generated: Wed Nov 11 20:33:01 2020 Cross-referenced by PHPXref 0.7.1