Skip to content

Commit 13ddfc0

Browse files
author
Stefano Sala
committed
[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
1 parent 50f77fb commit 13ddfc0

File tree

2 files changed

+98
-21
lines changed

2 files changed

+98
-21
lines changed

Helper/ProgressBar.php

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class ProgressBar
5555
*/
5656
public function __construct(OutputInterface $output, $max = 0)
5757
{
58+
if (!is_integer($max) || $max < 0) {
59+
throw new \InvalidArgumentException('Max steps should be a positive integer, 0 or null. Got "%s".', $max);
60+
}
61+
5862
// Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
5963
$this->output = $output->isDecorated() ? $output : new NullOutput();
6064
$this->max = (int) $max;
@@ -69,6 +73,12 @@ public function __construct(OutputInterface $output, $max = 0)
6973
}
7074

7175
$this->setFormat($this->determineBestFormat());
76+
77+
$this->startTime = time();
78+
$this->step = 0;
79+
$this->percent = 0;
80+
$this->lastMessagesLength = 0;
81+
$this->barCharOriginal = '';
7282
}
7383

7484
/**
@@ -170,16 +180,30 @@ public function getMaxSteps()
170180
/**
171181
* Gets the progress bar step.
172182
*
183+
* @deprecated since 2.6, to be removed in 3.0. Use {@link getCurrent()} instead.
184+
*
173185
* @return int The progress bar step
174186
*/
175187
public function getStep()
188+
{
189+
return $this->getCurrent();
190+
}
191+
192+
/**
193+
* Gets the progress bar step.
194+
*
195+
* @return int The progress bar step
196+
*/
197+
public function getCurrent()
176198
{
177199
return $this->step;
178200
}
179201

180202
/**
181203
* Gets the progress bar step width.
182204
*
205+
* @deprecated since 2.6, it will be marked private from 3.0.
206+
*
183207
* @return int The progress bar step width
184208
*/
185209
public function getStepWidth()
@@ -308,14 +332,15 @@ public function setRedrawFrequency($freq)
308332

309333
/**
310334
* Starts the progress output.
335+
*
336+
* @param int $max Maximum Step (0 if unknown)
311337
*/
312-
public function start()
338+
public function start($max = 0)
313339
{
314-
$this->startTime = time();
315-
$this->step = 0;
316-
$this->percent = 0;
317-
$this->lastMessagesLength = 0;
318-
$this->barCharOriginal = '';
340+
if (0 !== $max) {
341+
$this->max = $max;
342+
$this->stepWidth = $this->max > 0 ? Helper::strlen($this->max) : 4;
343+
}
319344

320345
if (!$this->max) {
321346
$this->barCharOriginal = $this->barChar;
@@ -346,10 +371,6 @@ public function advance($step = 1)
346371
*/
347372
public function setCurrent($step)
348373
{
349-
if (null === $this->startTime) {
350-
throw new \LogicException('You must start the progress bar before calling setCurrent().');
351-
}
352-
353374
$step = (int) $step;
354375
if ($step < $this->step) {
355376
throw new \LogicException('You can\'t regress the progress bar.');
@@ -373,10 +394,6 @@ public function setCurrent($step)
373394
*/
374395
public function finish()
375396
{
376-
if (null === $this->startTime) {
377-
throw new \LogicException('You must start the progress bar before calling finish().');
378-
}
379-
380397
if (!$this->max) {
381398
$this->barChar = $this->barCharOriginal;
382399
$this->max = $this->step;
@@ -397,8 +414,8 @@ public function finish()
397414
*/
398415
public function display()
399416
{
400-
if (null === $this->startTime) {
401-
throw new \LogicException('You must start the progress bar before calling display().');
417+
if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
418+
return;
402419
}
403420

404421
// these 3 variables can be removed in favor of using $this in the closure when support for PHP 5.3 will be dropped.

Tests/Helper/ProgressBarTest.php

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ class ProgressBarTest extends \PHPUnit_Framework_TestCase
1919
{
2020
protected $lastMessagesLength;
2121

22+
/**
23+
* @expectedException InvalidArgumentException
24+
*/
25+
public function testInitializeWithNegativeMax()
26+
{
27+
$bar = new ProgressBar($output = $this->getOutputStream(), -1);
28+
}
29+
2230
public function testAdvance()
2331
{
2432
$bar = new ProgressBar($output = $this->getOutputStream());
@@ -82,6 +90,42 @@ public function testCustomizations()
8290
);
8391
}
8492

93+
public function testDisplayWithoutStart()
94+
{
95+
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
96+
$bar->display();
97+
98+
rewind($output->getStream());
99+
$this->assertEquals(
100+
$this->generateOutput(' 0/50 [>---------------------------] 0%'),
101+
stream_get_contents($output->getStream())
102+
);
103+
}
104+
105+
public function testDisplayWithQuietVerbosity()
106+
{
107+
$bar = new ProgressBar($output = $this->getOutputStream(true, StreamOutput::VERBOSITY_QUIET), 50);
108+
$bar->display();
109+
110+
rewind($output->getStream());
111+
$this->assertEquals(
112+
'',
113+
stream_get_contents($output->getStream())
114+
);
115+
}
116+
117+
public function testFinishWithoutStart()
118+
{
119+
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
120+
$bar->finish();
121+
122+
rewind($output->getStream());
123+
$this->assertEquals(
124+
$this->generateOutput(' 50/50 [============================] 100%'),
125+
stream_get_contents($output->getStream())
126+
);
127+
}
128+
85129
public function testPercent()
86130
{
87131
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
@@ -122,6 +166,23 @@ public function testOverwriteWithShorterLine()
122166
);
123167
}
124168

169+
public function testStartWithMax()
170+
{
171+
$bar = new ProgressBar($output = $this->getOutputStream());
172+
$bar->setFormat('%current%/%max% [%bar%]');
173+
$bar->start(50);
174+
$bar->display();
175+
$bar->advance();
176+
177+
rewind($output->getStream());
178+
$this->assertEquals(
179+
$this->generateOutput(' 0/50 [>---------------------------]').
180+
$this->generateOutput(' 0/50 [>---------------------------]').
181+
$this->generateOutput(' 1/50 [>---------------------------]'),
182+
stream_get_contents($output->getStream())
183+
);
184+
}
185+
125186
public function testSetCurrentProgress()
126187
{
127188
$bar = new ProgressBar($output = $this->getOutputStream(), 50);
@@ -143,13 +204,12 @@ public function testSetCurrentProgress()
143204
}
144205

145206
/**
146-
* @expectedException \LogicException
147-
* @expectedExceptionMessage You must start the progress bar
148207
*/
149208
public function testSetCurrentBeforeStarting()
150209
{
151210
$bar = new ProgressBar($this->getOutputStream());
152211
$bar->setCurrent(15);
212+
$this->assertNotNull($bar->getStartTime());
153213
}
154214

155215
/**
@@ -302,7 +362,7 @@ public function testParallelBars()
302362
public function testAddingPlaceholderFormatter()
303363
{
304364
ProgressBar::setPlaceholderFormatterDefinition('remaining_steps', function (ProgressBar $bar) {
305-
return $bar->getMaxSteps() - $bar->getStep();
365+
return $bar->getMaxSteps() - $bar->getCurrent();
306366
});
307367
$bar = new ProgressBar($output = $this->getOutputStream(), 3);
308368
$bar->setFormat(' %remaining_steps% [%bar%]');
@@ -432,9 +492,9 @@ public function provideFormat()
432492
);
433493
}
434494

435-
protected function getOutputStream($decorated = true)
495+
protected function getOutputStream($decorated = true, $verbosity = StreamOutput::VERBOSITY_NORMAL)
436496
{
437-
return new StreamOutput(fopen('php://memory', 'r+', false), StreamOutput::VERBOSITY_NORMAL, $decorated);
497+
return new StreamOutput(fopen('php://memory', 'r+', false), $verbosity, $decorated);
438498
}
439499

440500
protected function generateOutput($expected)

0 commit comments

Comments
 (0)