You are here

ProgressHelper.php in Zircon Profile 8

Same filename and directory in other branches
  1. 8.0 vendor/symfony/console/Helper/ProgressHelper.php

File

vendor/symfony/console/Helper/ProgressHelper.php
View source
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Component\Console\Helper;

use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * The Progress class provides helpers to display progress output.
 *
 * @author Chris Jones <leeked@gmail.com>
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @deprecated since version 2.5, to be removed in 3.0
 *             Use {@link ProgressBar} instead.
 */
class ProgressHelper extends Helper {
  const FORMAT_QUIET = ' %percent%%';
  const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
  const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
  const FORMAT_QUIET_NOMAX = ' %current%';
  const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
  const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';

  // options
  private $barWidth = 28;
  private $barChar = '=';
  private $emptyBarChar = '-';
  private $progressChar = '>';
  private $format = null;
  private $redrawFreq = 1;
  private $lastMessagesLength;
  private $barCharOriginal;

  /**
   * @var OutputInterface
   */
  private $output;

  /**
   * Current step.
   *
   * @var int
   */
  private $current;

  /**
   * Maximum number of steps.
   *
   * @var int
   */
  private $max;

  /**
   * Start time of the progress bar.
   *
   * @var int
   */
  private $startTime;

  /**
   * List of formatting variables.
   *
   * @var array
   */
  private $defaultFormatVars = array(
    'current',
    'max',
    'bar',
    'percent',
    'elapsed',
  );

  /**
   * Available formatting variables.
   *
   * @var array
   */
  private $formatVars;

  /**
   * Stored format part widths (used for padding).
   *
   * @var array
   */
  private $widths = array(
    'current' => 4,
    'max' => 4,
    'percent' => 3,
    'elapsed' => 6,
  );

  /**
   * Various time formats.
   *
   * @var array
   */
  private $timeFormats = array(
    array(
      0,
      '???',
    ),
    array(
      2,
      '1 sec',
    ),
    array(
      59,
      'secs',
      1,
    ),
    array(
      60,
      '1 min',
    ),
    array(
      3600,
      'mins',
      60,
    ),
    array(
      5400,
      '1 hr',
    ),
    array(
      86400,
      'hrs',
      3600,
    ),
    array(
      129600,
      '1 day',
    ),
    array(
      604800,
      'days',
      86400,
    ),
  );
  public function __construct($triggerDeprecationError = true) {
    if ($triggerDeprecationError) {
      @trigger_error('The ' . __CLASS__ . ' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\\Component\\Console\\Helper\\ProgressBar class instead.', E_USER_DEPRECATED);
    }
  }

  /**
   * Sets the progress bar width.
   *
   * @param int $size The progress bar size
   */
  public function setBarWidth($size) {
    $this->barWidth = (int) $size;
  }

  /**
   * Sets the bar character.
   *
   * @param string $char A character
   */
  public function setBarCharacter($char) {
    $this->barChar = $char;
  }

  /**
   * Sets the empty bar character.
   *
   * @param string $char A character
   */
  public function setEmptyBarCharacter($char) {
    $this->emptyBarChar = $char;
  }

  /**
   * Sets the progress bar character.
   *
   * @param string $char A character
   */
  public function setProgressCharacter($char) {
    $this->progressChar = $char;
  }

  /**
   * Sets the progress bar format.
   *
   * @param string $format The format
   */
  public function setFormat($format) {
    $this->format = $format;
  }

  /**
   * Sets the redraw frequency.
   *
   * @param int $freq The frequency in steps
   */
  public function setRedrawFrequency($freq) {
    $this->redrawFreq = (int) $freq;
  }

  /**
   * Starts the progress output.
   *
   * @param OutputInterface $output An Output instance
   * @param int|null        $max    Maximum steps
   */
  public function start(OutputInterface $output, $max = null) {
    $this->startTime = time();
    $this->current = 0;
    $this->max = (int) $max;

    // Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
    $this->output = $output
      ->isDecorated() ? $output : new NullOutput();
    $this->lastMessagesLength = 0;
    $this->barCharOriginal = '';
    if (null === $this->format) {
      switch ($output
        ->getVerbosity()) {
        case OutputInterface::VERBOSITY_QUIET:
          $this->format = self::FORMAT_QUIET_NOMAX;
          if ($this->max > 0) {
            $this->format = self::FORMAT_QUIET;
          }
          break;
        case OutputInterface::VERBOSITY_VERBOSE:
        case OutputInterface::VERBOSITY_VERY_VERBOSE:
        case OutputInterface::VERBOSITY_DEBUG:
          $this->format = self::FORMAT_VERBOSE_NOMAX;
          if ($this->max > 0) {
            $this->format = self::FORMAT_VERBOSE;
          }
          break;
        default:
          $this->format = self::FORMAT_NORMAL_NOMAX;
          if ($this->max > 0) {
            $this->format = self::FORMAT_NORMAL;
          }
          break;
      }
    }
    $this
      ->initialize();
  }

  /**
   * Advances the progress output X steps.
   *
   * @param int  $step   Number of steps to advance
   * @param bool $redraw Whether to redraw or not
   *
   * @throws \LogicException
   */
  public function advance($step = 1, $redraw = false) {
    $this
      ->setCurrent($this->current + $step, $redraw);
  }

  /**
   * Sets the current progress.
   *
   * @param int  $current The current progress
   * @param bool $redraw  Whether to redraw or not
   *
   * @throws \LogicException
   */
  public function setCurrent($current, $redraw = false) {
    if (null === $this->startTime) {
      throw new \LogicException('You must start the progress bar before calling setCurrent().');
    }
    $current = (int) $current;
    if ($current < $this->current) {
      throw new \LogicException('You can\'t regress the progress bar');
    }
    if (0 === $this->current) {
      $redraw = true;
    }
    $prevPeriod = (int) ($this->current / $this->redrawFreq);
    $this->current = $current;
    $currPeriod = (int) ($this->current / $this->redrawFreq);
    if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
      $this
        ->display();
    }
  }

  /**
   * Outputs the current progress string.
   *
   * @param bool $finish Forces the end result
   *
   * @throws \LogicException
   */
  public function display($finish = false) {
    if (null === $this->startTime) {
      throw new \LogicException('You must start the progress bar before calling display().');
    }
    $message = $this->format;
    foreach ($this
      ->generate($finish) as $name => $value) {
      $message = str_replace("%{$name}%", $value, $message);
    }
    $this
      ->overwrite($this->output, $message);
  }

  /**
   * Removes the progress bar from the current line.
   *
   * This is useful if you wish to write some output
   * while a progress bar is running.
   * Call display() to show the progress bar again.
   */
  public function clear() {
    $this
      ->overwrite($this->output, '');
  }

  /**
   * Finishes the progress output.
   */
  public function finish() {
    if (null === $this->startTime) {
      throw new \LogicException('You must start the progress bar before calling finish().');
    }
    if (null !== $this->startTime) {
      if (!$this->max) {
        $this->barChar = $this->barCharOriginal;
        $this
          ->display(true);
      }
      $this->startTime = null;
      $this->output
        ->writeln('');
      $this->output = null;
    }
  }

  /**
   * Initializes the progress helper.
   */
  private function initialize() {
    $this->formatVars = array();
    foreach ($this->defaultFormatVars as $var) {
      if (false !== strpos($this->format, "%{$var}%")) {
        $this->formatVars[$var] = true;
      }
    }
    if ($this->max > 0) {
      $this->widths['max'] = $this
        ->strlen($this->max);
      $this->widths['current'] = $this->widths['max'];
    }
    else {
      $this->barCharOriginal = $this->barChar;
      $this->barChar = $this->emptyBarChar;
    }
  }

  /**
   * Generates the array map of format variables to values.
   *
   * @param bool $finish Forces the end result
   *
   * @return array Array of format vars and values
   */
  private function generate($finish = false) {
    $vars = array();
    $percent = 0;
    if ($this->max > 0) {
      $percent = (double) $this->current / $this->max;
    }
    if (isset($this->formatVars['bar'])) {
      $completeBars = 0;
      if ($this->max > 0) {
        $completeBars = floor($percent * $this->barWidth);
      }
      else {
        if (!$finish) {
          $completeBars = floor($this->current % $this->barWidth);
        }
        else {
          $completeBars = $this->barWidth;
        }
      }
      $emptyBars = $this->barWidth - $completeBars - $this
        ->strlen($this->progressChar);
      $bar = str_repeat($this->barChar, $completeBars);
      if ($completeBars < $this->barWidth) {
        $bar .= $this->progressChar;
        $bar .= str_repeat($this->emptyBarChar, $emptyBars);
      }
      $vars['bar'] = $bar;
    }
    if (isset($this->formatVars['elapsed'])) {
      $elapsed = time() - $this->startTime;
      $vars['elapsed'] = str_pad($this
        ->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
    }
    if (isset($this->formatVars['current'])) {
      $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
    }
    if (isset($this->formatVars['max'])) {
      $vars['max'] = $this->max;
    }
    if (isset($this->formatVars['percent'])) {
      $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
    }
    return $vars;
  }

  /**
   * Converts seconds into human-readable format.
   *
   * @param int $secs Number of seconds
   *
   * @return string Time in readable format
   */
  private function humaneTime($secs) {
    $text = '';
    foreach ($this->timeFormats as $format) {
      if ($secs < $format[0]) {
        if (count($format) == 2) {
          $text = $format[1];
          break;
        }
        else {
          $text = ceil($secs / $format[2]) . ' ' . $format[1];
          break;
        }
      }
    }
    return $text;
  }

  /**
   * Overwrites a previous message to the output.
   *
   * @param OutputInterface $output  An Output instance
   * @param string          $message The message
   */
  private function overwrite(OutputInterface $output, $message) {
    $length = $this
      ->strlen($message);

    // append whitespace to match the last line's length
    if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
      $message = str_pad($message, $this->lastMessagesLength, " ", STR_PAD_RIGHT);
    }

    // carriage return
    $output
      ->write("\r");
    $output
      ->write($message);
    $this->lastMessagesLength = $this
      ->strlen($message);
  }

  /**
   * {@inheritdoc}
   */
  public function getName() {
    return 'progress';
  }

}

Classes

Namesort descending Description
ProgressHelper Deprecated The Progress class provides helpers to display progress output.