From 73ca34082750df7ecf24447958fca05ac0e78f92 Mon Sep 17 00:00:00 2001 From: Stefano Sala Date: Mon, 7 Jul 2014 15:59:31 +0200 Subject: [PATCH] [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 --- .../Component/Console/Helper/ProgressBar.php | 49 ++++++++----- .../Console/Tests/Helper/ProgressBarTest.php | 70 +++++++++++++++++-- 2 files changed, 98 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 99c0dfc59b..09cb5690ea 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -55,6 +55,10 @@ class ProgressBar */ 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. $this->output = $output->isDecorated() ? $output : new NullOutput(); $this->max = (int) $max; @@ -69,6 +73,12 @@ class ProgressBar } $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. * + * @deprecated since 2.6, to be removed in 3.0. Use {@link getCurrent()} instead. + * * @return int The progress bar step */ public function getStep() + { + return $this->getCurrent(); + } + + /** + * Gets the progress bar step. + * + * @return int The progress bar step + */ + public function getCurrent() { return $this->step; } @@ -180,6 +202,8 @@ class ProgressBar /** * 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 */ public function getStepWidth() @@ -308,14 +332,15 @@ class ProgressBar /** * Starts the progress output. + * + * @param int $max Maximum Step (0 if unknown) */ - public function start() + public function start($max = 0) { - $this->startTime = time(); - $this->step = 0; - $this->percent = 0; - $this->lastMessagesLength = 0; - $this->barCharOriginal = ''; + if (0 !== $max) { + $this->max = $max; + $this->stepWidth = $this->max > 0 ? Helper::strlen($this->max) : 4; + } if (!$this->max) { $this->barCharOriginal = $this->barChar; @@ -346,10 +371,6 @@ class ProgressBar */ 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.'); @@ -373,10 +394,6 @@ class ProgressBar */ 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; @@ -397,8 +414,8 @@ class ProgressBar */ public function display() { - if (null === $this->startTime) { - throw new \LogicException('You must start the progress bar before calling display().'); + if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { + return; } // these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped. diff --git a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php index d087713867..53ab6105a7 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php @@ -19,6 +19,14 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase { protected $lastMessagesLength; + /** + * @expectedException InvalidArgumentException + */ + public function testInitializeWithNegativeMax() + { + $bar = new ProgressBar($output = $this->getOutputStream(), -1); + } + public function testAdvance() { $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() { $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() { $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() { $bar = new ProgressBar($this->getOutputStream()); $bar->setCurrent(15); + $this->assertNotNull($bar->getStartTime()); } /** @@ -302,7 +362,7 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase public function testAddingPlaceholderFormatter() { 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->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)