[Console] added ProgressBar (to replace the stateful ProgressHelper class)
This commit is contained in:
parent
65c9aca2e6
commit
4e76aa3fbc
@ -23,6 +23,31 @@ UPGRADE FROM 2.x to 3.0
|
||||
* The methods `isQuiet`, `isVerbose`, `isVeryVerbose` and `isDebug` were added
|
||||
to `Symfony\Component\Console\Output\OutputInterface`.
|
||||
|
||||
* `ProgressHelper` has been removed in favor of `ProgressBar`.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
$h = new ProgressHelper();
|
||||
$h->start($output, 10);
|
||||
for ($i = 1; $i < 5; $i++) {
|
||||
usleep(200000);
|
||||
$h->advance();
|
||||
}
|
||||
$h->finish();
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
$bar = new ProgressBar($output, 10);
|
||||
$bar->start();
|
||||
for ($i = 1; $i < 5; $i++) {
|
||||
usleep(200000);
|
||||
$bar->advance();
|
||||
}
|
||||
```
|
||||
|
||||
### EventDispatcher
|
||||
|
||||
* The interface `Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface`
|
||||
|
@ -4,8 +4,9 @@ CHANGELOG
|
||||
2.5.0
|
||||
-----
|
||||
|
||||
* added a way to set a default command instead of `ListCommand`
|
||||
* added a way to set the process name of a command
|
||||
* deprecated ProgressHelper in favor of ProgressBar
|
||||
* added a way to set a default command instead of `ListCommand`
|
||||
* added a way to set the process name of a command
|
||||
|
||||
2.4.0
|
||||
-----
|
||||
|
@ -47,7 +47,7 @@ abstract class Helper implements HelperInterface
|
||||
*
|
||||
* @return integer The length of the string
|
||||
*/
|
||||
protected function strlen($string)
|
||||
public static function strlen($string)
|
||||
{
|
||||
if (!function_exists('mb_strlen')) {
|
||||
return strlen($string);
|
||||
|
403
src/Symfony/Component/Console/Helper/ProgressBar.php
Normal file
403
src/Symfony/Component/Console/Helper/ProgressBar.php
Normal file
@ -0,0 +1,403 @@
|
||||
<?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 ProgressBar provides helpers to display progress output.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Chris Jones <leeked@gmail.com>
|
||||
*/
|
||||
class ProgressBar
|
||||
{
|
||||
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;
|
||||
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
private $step;
|
||||
private $max;
|
||||
private $startTime;
|
||||
private $lastMessagesLength;
|
||||
private $barCharOriginal;
|
||||
|
||||
/**
|
||||
* List of formatting variables
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $defaultFormatVars = array(
|
||||
'current',
|
||||
'max',
|
||||
'bar',
|
||||
'percent',
|
||||
'elapsed',
|
||||
);
|
||||
|
||||
/**
|
||||
* Available formatting variables
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $formatVars;
|
||||
|
||||
/**
|
||||
* 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),
|
||||
);
|
||||
|
||||
private $stepWidth;
|
||||
private $percent;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param integer $max Maximum steps (0 if unknown)
|
||||
*/
|
||||
public function __construct(OutputInterface $output, $max = 0)
|
||||
{
|
||||
// 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->max = (int) $max;
|
||||
$this->stepWidth = $this->max > 0 ? Helper::strlen($this->max) : 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function start()
|
||||
{
|
||||
$this->startTime = time();
|
||||
$this->step = 0;
|
||||
$this->percent = 0;
|
||||
$this->lastMessagesLength = 0;
|
||||
$this->barCharOriginal = '';
|
||||
|
||||
if (null === $this->format) {
|
||||
$this->format = $this->determineBestFormat();
|
||||
}
|
||||
|
||||
$this->formatVars = array();
|
||||
foreach ($this->defaultFormatVars as $var) {
|
||||
if (false !== strpos($this->format, "%{$var}%")) {
|
||||
$this->formatVars[$var] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->max) {
|
||||
$this->barCharOriginal = $this->barChar;
|
||||
$this->barChar = $this->emptyBarChar;
|
||||
}
|
||||
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* Advances the progress output X steps.
|
||||
*
|
||||
* @param integer $step Number of steps to advance
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function advance($step = 1)
|
||||
{
|
||||
$this->setCurrent($this->step + $step);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current progress.
|
||||
*
|
||||
* @param integer $step The current progress
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function setCurrent($step)
|
||||
{
|
||||
if (null === $this->startTime) {
|
||||
throw new \LogicException('You must start the progress bar before calling setCurrent().');
|
||||
}
|
||||
|
||||
$step = (int) $step;
|
||||
if ($step < $this->step) {
|
||||
throw new \LogicException('You can\'t regress the progress bar.');
|
||||
}
|
||||
|
||||
if ($this->max > 0 && $step > $this->max) {
|
||||
throw new \LogicException('You can\'t advance the progress bar past the max value.');
|
||||
}
|
||||
|
||||
$prevPeriod = intval($this->step / $this->redrawFreq);
|
||||
$currPeriod = intval($step / $this->redrawFreq);
|
||||
$this->step = $step;
|
||||
$this->percent = $this->max > 0 ? (float) $this->step / $this->max : 0;
|
||||
if ($prevPeriod !== $currPeriod || $this->max === $step) {
|
||||
$this->display();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress output.
|
||||
*/
|
||||
public function finish()
|
||||
{
|
||||
if (null === $this->startTime) {
|
||||
throw new \LogicException('You must start the progress bar before calling finish().');
|
||||
}
|
||||
|
||||
if (!$this->max) {
|
||||
$this->barChar = $this->barCharOriginal;
|
||||
$this->max = $this->step;
|
||||
$this->setCurrent($this->max);
|
||||
$this->max = 0;
|
||||
$this->barChar = $this->emptyBarChar;
|
||||
} else {
|
||||
$this->setCurrent($this->max);
|
||||
}
|
||||
|
||||
$this->startTime = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the current progress string.
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
if (null === $this->startTime) {
|
||||
throw new \LogicException('You must start the progress bar before calling display().');
|
||||
}
|
||||
|
||||
$message = $this->format;
|
||||
foreach ($this->generate() as $name => $value) {
|
||||
$message = str_replace("%{$name}%", $value, $message);
|
||||
}
|
||||
$this->overwrite($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('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the array map of format variables to values.
|
||||
*
|
||||
* @return array Array of format vars and values
|
||||
*/
|
||||
private function generate()
|
||||
{
|
||||
$vars = array();
|
||||
|
||||
if (isset($this->formatVars['bar'])) {
|
||||
$completeBars = floor($this->max > 0 ? $this->percent * $this->barWidth : $this->step % $this->barWidth);
|
||||
$emptyBars = $this->barWidth - $completeBars - Helper::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), 6, ' ', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
if (isset($this->formatVars['current'])) {
|
||||
$vars['current'] = str_pad($this->step, $this->stepWidth, ' ', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
if (isset($this->formatVars['max'])) {
|
||||
$vars['max'] = $this->max;
|
||||
}
|
||||
|
||||
if (isset($this->formatVars['percent'])) {
|
||||
$vars['percent'] = str_pad(floor($this->percent * 100), 3, ' ', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts seconds into human-readable format.
|
||||
*
|
||||
* @param integer $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 string $message The message
|
||||
*/
|
||||
private function overwrite($message)
|
||||
{
|
||||
$length = Helper::strlen($message);
|
||||
|
||||
// append whitespace to match the last line's length
|
||||
if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
|
||||
$message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
|
||||
}
|
||||
|
||||
// carriage return
|
||||
$this->output->write("\x0D");
|
||||
$this->output->write($message);
|
||||
|
||||
$this->lastMessagesLength = Helper::strlen($message);
|
||||
}
|
||||
|
||||
private function determineBestFormat()
|
||||
{
|
||||
switch ($this->output->getVerbosity()) {
|
||||
case OutputInterface::VERBOSITY_QUIET:
|
||||
$format = self::FORMAT_QUIET_NOMAX;
|
||||
if ($this->max > 0) {
|
||||
$format = self::FORMAT_QUIET;
|
||||
}
|
||||
break;
|
||||
case OutputInterface::VERBOSITY_VERBOSE:
|
||||
case OutputInterface::VERBOSITY_VERY_VERBOSE:
|
||||
case OutputInterface::VERBOSITY_DEBUG:
|
||||
$format = self::FORMAT_VERBOSE_NOMAX;
|
||||
if ($this->max > 0) {
|
||||
$format = self::FORMAT_VERBOSE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$format = self::FORMAT_NORMAL_NOMAX;
|
||||
if ($this->max > 0) {
|
||||
$format = self::FORMAT_NORMAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $format;
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface;
|
||||
*
|
||||
* @author Chris Jones <leeked@gmail.com>
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* @deprecated Deprecated since 2.5, to be removed in 3.0; use ProgressBar instead.
|
||||
*/
|
||||
class ProgressHelper extends Helper
|
||||
{
|
||||
|
318
src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php
Normal file
318
src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php
Normal file
@ -0,0 +1,318 @@
|
||||
<?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\Tests\Helper;
|
||||
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Output\StreamOutput;
|
||||
|
||||
class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
protected $lastMessagesLength;
|
||||
|
||||
public function testAdvance()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||
$bar->start();
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0 [>---------------------------]').
|
||||
$this->generateOutput(' 1 [->--------------------------]'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testAdvanceWithStep()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||
$bar->start();
|
||||
$bar->advance(5);
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0 [>---------------------------]').
|
||||
$this->generateOutput(' 5 [----->----------------------]'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testAdvanceMultipleTimes()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||
$bar->start();
|
||||
$bar->advance(3);
|
||||
$bar->advance(2);
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0 [>---------------------------]').
|
||||
$this->generateOutput(' 3 [--->------------------------]').
|
||||
$this->generateOutput(' 5 [----->----------------------]'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testCustomizations()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 10);
|
||||
$bar->setBarWidth(10);
|
||||
$bar->setBarCharacter('_');
|
||||
$bar->setEmptyBarCharacter(' ');
|
||||
$bar->setProgressCharacter('/');
|
||||
$bar->setFormat(' %current%/%max% [%bar%] %percent%%');
|
||||
$bar->start();
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/10 [/ ] 0%').
|
||||
$this->generateOutput(' 1/10 [_/ ] 10%'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testPercent()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||
$bar->start();
|
||||
$bar->display();
|
||||
$bar->advance();
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 1/50 [>---------------------------] 2%').
|
||||
$this->generateOutput(' 2/50 [=>--------------------------] 4%'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testOverwriteWithShorterLine()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||
$bar->setFormat(' %current%/%max% [%bar%] %percent%%');
|
||||
$bar->start();
|
||||
$bar->display();
|
||||
$bar->advance();
|
||||
|
||||
// set shorter format
|
||||
$bar->setFormat(' %current%/%max% [%bar%]');
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 1/50 [>---------------------------] 2%').
|
||||
$this->generateOutput(' 2/50 [=>--------------------------] '),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testSetCurrentProgress()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||
$bar->start();
|
||||
$bar->display();
|
||||
$bar->advance();
|
||||
$bar->setCurrent(15);
|
||||
$bar->setCurrent(25);
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 1/50 [>---------------------------] 2%').
|
||||
$this->generateOutput(' 15/50 [========>-------------------] 30%').
|
||||
$this->generateOutput(' 25/50 [==============>-------------] 50%'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage You must start the progress bar
|
||||
*/
|
||||
public function testSetCurrentBeforeStarting()
|
||||
{
|
||||
$bar = new ProgressBar($this->getOutputStream());
|
||||
$bar->setCurrent(15);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \LogicException
|
||||
* @expectedExceptionMessage You can't regress the progress bar
|
||||
*/
|
||||
public function testRegressProgress()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||
$bar->start();
|
||||
$bar->setCurrent(15);
|
||||
$bar->setCurrent(10);
|
||||
}
|
||||
|
||||
public function testRedrawFrequency()
|
||||
{
|
||||
$bar = $this->getMock('Symfony\Component\Console\Helper\ProgressBar', array('display'), array($output = $this->getOutputStream(), 6));
|
||||
$bar->expects($this->exactly(4))->method('display');
|
||||
|
||||
$bar->setRedrawFrequency(2);
|
||||
$bar->start();
|
||||
$bar->setCurrent(1);
|
||||
$bar->advance(2);
|
||||
$bar->advance(2);
|
||||
$bar->advance(1);
|
||||
}
|
||||
|
||||
public function testMultiByteSupport()
|
||||
{
|
||||
if (!function_exists('mb_strlen') || (false === $encoding = mb_detect_encoding('■'))) {
|
||||
$this->markTestSkipped('The mbstring extension is needed for multi-byte support');
|
||||
}
|
||||
|
||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||
$bar->start();
|
||||
$bar->setBarCharacter('■');
|
||||
$bar->advance(3);
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0 [>---------------------------]').
|
||||
$this->generateOutput(' 3 [■■■>------------------------]'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testClear()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||
$bar->start();
|
||||
$bar->setCurrent(25);
|
||||
$bar->clear();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/50 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 25/50 [==============>-------------] 50%').
|
||||
$this->generateOutput(''),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testPercentNotHundredBeforeComplete()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(), 200);
|
||||
$bar->start();
|
||||
$bar->display();
|
||||
$bar->advance(199);
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/200 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 0/200 [>---------------------------] 0%').
|
||||
$this->generateOutput(' 199/200 [===========================>] 99%').
|
||||
$this->generateOutput(' 200/200 [============================] 100%'),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
public function testNonDecoratedOutput()
|
||||
{
|
||||
$bar = new ProgressBar($output = $this->getOutputStream(false));
|
||||
$bar->start();
|
||||
$bar->advance();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals('', stream_get_contents($output->getStream()));
|
||||
}
|
||||
|
||||
public function testParallelBars()
|
||||
{
|
||||
$output = $this->getOutputStream();
|
||||
$bar1 = new ProgressBar($output, 2);
|
||||
$bar2 = new ProgressBar($output, 3);
|
||||
$bar2->setProgressCharacter('#');
|
||||
$bar3 = new ProgressBar($output);
|
||||
|
||||
$bar1->start();
|
||||
$output->write("\n");
|
||||
$bar2->start();
|
||||
$output->write("\n");
|
||||
$bar3->start();
|
||||
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
// up two lines
|
||||
$output->write("\033[2A");
|
||||
if ($i <= 2) {
|
||||
$bar1->advance();
|
||||
}
|
||||
$output->write("\n");
|
||||
$bar2->advance();
|
||||
$output->write("\n");
|
||||
$bar3->advance();
|
||||
}
|
||||
$output->write("\033[2A");
|
||||
$output->write("\n");
|
||||
$output->write("\n");
|
||||
$bar3->finish();
|
||||
|
||||
rewind($output->getStream());
|
||||
$this->assertEquals(
|
||||
$this->generateOutput(' 0/2 [>---------------------------] 0%')."\n".
|
||||
$this->generateOutput(' 0/3 [#---------------------------] 0%')."\n".
|
||||
rtrim($this->generateOutput(' 0 [>---------------------------]')).
|
||||
|
||||
"\033[2A".
|
||||
$this->generateOutput(' 1/2 [==============>-------------] 50%')."\n".
|
||||
$this->generateOutput(' 1/3 [=========#------------------] 33%')."\n".
|
||||
rtrim($this->generateOutput(' 1 [->--------------------------]')).
|
||||
|
||||
"\033[2A".
|
||||
$this->generateOutput(' 2/2 [============================] 100%')."\n".
|
||||
$this->generateOutput(' 2/3 [==================#---------] 66%')."\n".
|
||||
rtrim($this->generateOutput(' 2 [-->-------------------------]')).
|
||||
|
||||
"\033[2A".
|
||||
"\n".
|
||||
$this->generateOutput(' 3/3 [============================] 100%')."\n".
|
||||
rtrim($this->generateOutput(' 3 [--->------------------------]')).
|
||||
|
||||
"\033[2A".
|
||||
"\n".
|
||||
"\n".
|
||||
rtrim($this->generateOutput(' 3 [============================]')),
|
||||
stream_get_contents($output->getStream())
|
||||
);
|
||||
}
|
||||
|
||||
protected function getOutputStream($decorated = true)
|
||||
{
|
||||
return new StreamOutput(fopen('php://memory', 'r+', false), StreamOutput::VERBOSITY_NORMAL, $decorated);
|
||||
}
|
||||
|
||||
protected function generateOutput($expected)
|
||||
{
|
||||
$expectedout = $expected;
|
||||
|
||||
if (null !== $this->lastMessagesLength) {
|
||||
$expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
|
||||
}
|
||||
|
||||
$this->lastMessagesLength = strlen($expectedout);
|
||||
|
||||
return "\x0D".$expectedout;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user