Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Symfony/Component/Console/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CHANGELOG
* Add method `__toString()` to `InputInterface`
* Deprecate `Command::$defaultName` and `Command::$defaultDescription`, use the `AsCommand` attribute instead
* Add suggested values for arguments and options in input definition, for input completion
* Add `$resumeAt` parameter to `ProgressBar#start()`, so that one can easily 'resume' progress on longer tasks, and still get accurate `getEstimate()` and `getRemaining()` results.

6.0
---
Expand Down
19 changes: 12 additions & 7 deletions src/Symfony/Component/Console/Helper/ProgressBar.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ final class ProgressBar
private float $maxSecondsBetweenRedraws = 1;
private OutputInterface $output;
private int $step = 0;
private int $resumedStep = 0;
private ?int $max = null;
private int $startTime;
private int $stepWidth;
Expand Down Expand Up @@ -199,11 +200,11 @@ public function getBarOffset(): float

public function getEstimated(): float
{
if (!$this->step) {
if (0 === $this->step || $this->step === $this->resumedStep) {
return 0;
}

return round((time() - $this->startTime) / $this->step * $this->max);
return round((time() - $this->startTime) / ($this->step - $this->resumedStep) * $this->max);
}

public function getRemaining(): float
Expand All @@ -212,7 +213,7 @@ public function getRemaining(): float
return 0;
}

return round((time() - $this->startTime) / $this->step * ($this->max - $this->step));
return round((time() - $this->startTime) / ($this->step - $this->resumedStep) * ($this->max - $this->step));
}

public function setBarWidth(int $size)
Expand Down Expand Up @@ -302,13 +303,17 @@ public function iterate(iterable $iterable, int $max = null): iterable
/**
* Starts the progress output.
*
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
* @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
* @param int $resumeAt when restarting a previously started progress, set on what step we are restarting so that time estimations are calculated correctly, and the
* progress is automatically set to the appropriate step
*/
public function start(int $max = null)
public function start(int $max = null, int $resumeAt = 0): void
{
$this->startTime = time();
$this->step = 0;
$this->percent = 0.0;
$this->step = $resumeAt;
$this->resumedStep = $resumeAt;

$resumeAt > 0 ? $this->setProgress($resumeAt) : $this->percent = 0.0;

if (null !== $max) {
$this->setMaxSteps($max);
Expand Down
63 changes: 63 additions & 0 deletions src/Symfony/Component/Console/Tests/Helper/ProgressBarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,69 @@ public function testAdvance()
);
}

public function testResumeNoMax()
{
$bar = new ProgressBar($output = $this->getOutputStream(), 0, 0);
$bar->start(null, 15);
$bar->advance();

rewind($output->getStream());

$this->assertEquals(
' 15 [--------------->------------]'.
$this->generateOutput(' 16 [---------------->-----------]'),
stream_get_contents($output->getStream())
);
}

public function testResumeWithMax()
{
$bar = new ProgressBar($output = $this->getOutputStream(), 5000, 0);
$bar->start(null, 1000);

rewind($output->getStream());

$this->assertEquals(
' 1000/5000 [=====>----------------------] 20%',
stream_get_contents($output->getStream())
);
}

public function testRegularTimeEstimation()
{
$bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0);
$bar->start();

$bar->advance();
$bar->advance();

sleep(1);

$this->assertEquals(
600.0,
$bar->getEstimated()
);
}

public function testResumedTimeEstimation()
{
$bar = new ProgressBar($output = $this->getOutputStream(), 1_200, 0);
$bar->start(null, 599);
$bar->advance();

sleep(1);

$this->assertEquals(
1_200.0,
$bar->getEstimated()
);

$this->assertEquals(
600.0,
$bar->getRemaining()
);
}

public function testAdvanceWithStep()
{
$bar = new ProgressBar($output = $this->getOutputStream(), 0, 0);
Expand Down