[Console][ProgressBar] Developer experience
- Create getProgress/setProgress methods to replace getStep/setCurrent - ProgressBar::setCurrent should auto-start the ProgressBar. - You should be able to pass max to start - getStepWidth is internal information that should not be public - when verbosity set to quiet, the progress bar does not even need to execute all the logic to generate output that is then thrown away
This commit is contained in:
parent
27a2280d29
commit
73ca340827
@ -55,6 +55,10 @@ class ProgressBar
|
|||||||
*/
|
*/
|
||||||
public function __construct(OutputInterface $output, $max = 0)
|
public function __construct(OutputInterface $output, $max = 0)
|
||||||
{
|
{
|
||||||
|
if (!is_integer($max) || $max < 0) {
|
||||||
|
throw new \InvalidArgumentException('Max steps should be a positive integer, 0 or null. Got "%s".', $max);
|
||||||
|
}
|
||||||
|
|
||||||
// Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
|
// 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->output = $output->isDecorated() ? $output : new NullOutput();
|
||||||
$this->max = (int) $max;
|
$this->max = (int) $max;
|
||||||
@ -69,6 +73,12 @@ class ProgressBar
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->setFormat($this->determineBestFormat());
|
$this->setFormat($this->determineBestFormat());
|
||||||
|
|
||||||
|
$this->startTime = time();
|
||||||
|
$this->step = 0;
|
||||||
|
$this->percent = 0;
|
||||||
|
$this->lastMessagesLength = 0;
|
||||||
|
$this->barCharOriginal = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -170,9 +180,21 @@ class ProgressBar
|
|||||||
/**
|
/**
|
||||||
* Gets the progress bar step.
|
* Gets the progress bar step.
|
||||||
*
|
*
|
||||||
|
* @deprecated since 2.6, to be removed in 3.0. Use {@link getCurrent()} instead.
|
||||||
|
*
|
||||||
* @return int The progress bar step
|
* @return int The progress bar step
|
||||||
*/
|
*/
|
||||||
public function getStep()
|
public function getStep()
|
||||||
|
{
|
||||||
|
return $this->getCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the progress bar step.
|
||||||
|
*
|
||||||
|
* @return int The progress bar step
|
||||||
|
*/
|
||||||
|
public function getCurrent()
|
||||||
{
|
{
|
||||||
return $this->step;
|
return $this->step;
|
||||||
}
|
}
|
||||||
@ -180,6 +202,8 @@ class ProgressBar
|
|||||||
/**
|
/**
|
||||||
* Gets the progress bar step width.
|
* Gets the progress bar step width.
|
||||||
*
|
*
|
||||||
|
* @deprecated since 2.6, it will be marked private from 3.0.
|
||||||
|
*
|
||||||
* @return int The progress bar step width
|
* @return int The progress bar step width
|
||||||
*/
|
*/
|
||||||
public function getStepWidth()
|
public function getStepWidth()
|
||||||
@ -308,14 +332,15 @@ class ProgressBar
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts the progress output.
|
* Starts the progress output.
|
||||||
|
*
|
||||||
|
* @param int $max Maximum Step (0 if unknown)
|
||||||
*/
|
*/
|
||||||
public function start()
|
public function start($max = 0)
|
||||||
{
|
{
|
||||||
$this->startTime = time();
|
if (0 !== $max) {
|
||||||
$this->step = 0;
|
$this->max = $max;
|
||||||
$this->percent = 0;
|
$this->stepWidth = $this->max > 0 ? Helper::strlen($this->max) : 4;
|
||||||
$this->lastMessagesLength = 0;
|
}
|
||||||
$this->barCharOriginal = '';
|
|
||||||
|
|
||||||
if (!$this->max) {
|
if (!$this->max) {
|
||||||
$this->barCharOriginal = $this->barChar;
|
$this->barCharOriginal = $this->barChar;
|
||||||
@ -346,10 +371,6 @@ class ProgressBar
|
|||||||
*/
|
*/
|
||||||
public function setCurrent($step)
|
public function setCurrent($step)
|
||||||
{
|
{
|
||||||
if (null === $this->startTime) {
|
|
||||||
throw new \LogicException('You must start the progress bar before calling setCurrent().');
|
|
||||||
}
|
|
||||||
|
|
||||||
$step = (int) $step;
|
$step = (int) $step;
|
||||||
if ($step < $this->step) {
|
if ($step < $this->step) {
|
||||||
throw new \LogicException('You can\'t regress the progress bar.');
|
throw new \LogicException('You can\'t regress the progress bar.');
|
||||||
@ -373,10 +394,6 @@ class ProgressBar
|
|||||||
*/
|
*/
|
||||||
public function finish()
|
public function finish()
|
||||||
{
|
{
|
||||||
if (null === $this->startTime) {
|
|
||||||
throw new \LogicException('You must start the progress bar before calling finish().');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->max) {
|
if (!$this->max) {
|
||||||
$this->barChar = $this->barCharOriginal;
|
$this->barChar = $this->barCharOriginal;
|
||||||
$this->max = $this->step;
|
$this->max = $this->step;
|
||||||
@ -397,8 +414,8 @@ class ProgressBar
|
|||||||
*/
|
*/
|
||||||
public function display()
|
public function display()
|
||||||
{
|
{
|
||||||
if (null === $this->startTime) {
|
if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
|
||||||
throw new \LogicException('You must start the progress bar before calling display().');
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.
|
// these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.
|
||||||
|
@ -19,6 +19,14 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
protected $lastMessagesLength;
|
protected $lastMessagesLength;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function testInitializeWithNegativeMax()
|
||||||
|
{
|
||||||
|
$bar = new ProgressBar($output = $this->getOutputStream(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
public function testAdvance()
|
public function testAdvance()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream());
|
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||||
@ -82,6 +90,42 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDisplayWithoutStart()
|
||||||
|
{
|
||||||
|
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||||
|
$bar->display();
|
||||||
|
|
||||||
|
rewind($output->getStream());
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->generateOutput(' 0/50 [>---------------------------] 0%'),
|
||||||
|
stream_get_contents($output->getStream())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testDisplayWithQuietVerbosity()
|
||||||
|
{
|
||||||
|
$bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50);
|
||||||
|
$bar->display();
|
||||||
|
|
||||||
|
rewind($output->getStream());
|
||||||
|
$this->assertEquals(
|
||||||
|
'',
|
||||||
|
stream_get_contents($output->getStream())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testFinishWithoutStart()
|
||||||
|
{
|
||||||
|
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||||
|
$bar->finish();
|
||||||
|
|
||||||
|
rewind($output->getStream());
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->generateOutput(' 50/50 [============================] 100%'),
|
||||||
|
stream_get_contents($output->getStream())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testPercent()
|
public function testPercent()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||||
@ -122,6 +166,23 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testStartWithMax()
|
||||||
|
{
|
||||||
|
$bar = new ProgressBar($output = $this->getOutputStream());
|
||||||
|
$bar->setFormat('%current%/%max% [%bar%]');
|
||||||
|
$bar->start(50);
|
||||||
|
$bar->display();
|
||||||
|
$bar->advance();
|
||||||
|
|
||||||
|
rewind($output->getStream());
|
||||||
|
$this->assertEquals(
|
||||||
|
$this->generateOutput(' 0/50 [>---------------------------]').
|
||||||
|
$this->generateOutput(' 0/50 [>---------------------------]').
|
||||||
|
$this->generateOutput(' 1/50 [>---------------------------]'),
|
||||||
|
stream_get_contents($output->getStream())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetCurrentProgress()
|
public function testSetCurrentProgress()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
|
||||||
@ -143,13 +204,12 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \LogicException
|
|
||||||
* @expectedExceptionMessage You must start the progress bar
|
|
||||||
*/
|
*/
|
||||||
public function testSetCurrentBeforeStarting()
|
public function testSetCurrentBeforeStarting()
|
||||||
{
|
{
|
||||||
$bar = new ProgressBar($this->getOutputStream());
|
$bar = new ProgressBar($this->getOutputStream());
|
||||||
$bar->setCurrent(15);
|
$bar->setCurrent(15);
|
||||||
|
$this->assertNotNull($bar->getStartTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -302,7 +362,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testAddingPlaceholderFormatter()
|
public function testAddingPlaceholderFormatter()
|
||||||
{
|
{
|
||||||
ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
|
ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
|
||||||
return $bar->getMaxSteps() - $bar->getStep();
|
return $bar->getMaxSteps() - $bar->getCurrent();
|
||||||
});
|
});
|
||||||
$bar = new ProgressBar($output = $this->getOutputStream(), 3);
|
$bar = new ProgressBar($output = $this->getOutputStream(), 3);
|
||||||
$bar->setFormat(' %remaining_steps% [%bar%]');
|
$bar->setFormat(' %remaining_steps% [%bar%]');
|
||||||
@ -432,9 +492,9 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getOutputStream($decorated = true)
|
protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
|
||||||
{
|
{
|
||||||
return new StreamOutput(fopen('php://memory', 'r+', false), StreamOutput::VERBOSITY_NORMAL, $decorated);
|
return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function generateOutput($expected)
|
protected function generateOutput($expected)
|
||||||
|
Reference in New Issue
Block a user