diff --git a/src/Progressable.php b/src/Progressable.php index 0997237..ce44b62 100644 --- a/src/Progressable.php +++ b/src/Progressable.php @@ -17,6 +17,16 @@ trait Progressable { */ protected float $progress = 0; + /** + * The total number of steps for the progress. + */ + protected ?int $totalSteps = null; + + /** + * The current step of the progress. + */ + protected int $currentStep = 0; + /** * The callback function for saving cache data. * @@ -112,6 +122,75 @@ public function setCustomGetData(callable $callback): static { return $this; } + /** + * Set the total number of steps for the progress. + * + * @param int $steps The total number of steps. + * @return $this + * @throws \InvalidArgumentException If steps is not greater than 0. + */ + public function setTotalSteps(int $steps): static { + if ($steps <= 0) { + throw new \InvalidArgumentException("Total steps must be greater than 0"); + } + $this->totalSteps = $steps; + return $this; + } + + /** + * Get the total number of steps. + * + * @return int|null + */ + public function getTotalSteps(): ?int { + return $this->totalSteps; + } + + /** + * Increment the current step by a given amount. + * + * @param int $amount The amount to increment. + * @return $this + * @throws \LogicException If total steps are not set. + */ + public function incrementStep(int $amount = 1): static { + if ($this->totalSteps === null) { + throw new \LogicException("Total steps not set. Call setTotalSteps() first."); + } + + $this->currentStep += $amount; + $progress = ($this->currentStep / $this->totalSteps) * 100; + + return $this->setLocalProgress($progress); + } + + /** + * Set the current step. + * + * @param int $step The current step. + * @return $this + * @throws \LogicException If total steps are not set. + */ + public function setCurrentStep(int $step): static { + if ($this->totalSteps === null) { + throw new \LogicException("Total steps not set. Call setTotalSteps() first."); + } + + $this->currentStep = $step; + $progress = ($this->currentStep / $this->totalSteps) * 100; + + return $this->setLocalProgress($progress); + } + + /** + * Get the current step. + * + * @return int + */ + public function getCurrentStep(): int { + return $this->currentStep; + } + /** * Get the overall progress for the unique name. * diff --git a/tests/ProgressableTest.php b/tests/ProgressableTest.php index 40f5003..1668076 100644 --- a/tests/ProgressableTest.php +++ b/tests/ProgressableTest.php @@ -485,4 +485,49 @@ public function test_merge_metadata(): void { $this->assertEquals('new_value1', $storedMetadata['key1']); $this->assertEquals('value2', $storedMetadata['key2']); } + + public function test_set_total_steps(): void { + $this->setOverallUniqueName('test_steps_'.$this->testId); + $this->setTotalSteps(10); + + $this->assertEquals(10, $this->getTotalSteps()); + $this->assertEquals(0, $this->getCurrentStep()); + } + + public function test_increment_step(): void { + $this->setOverallUniqueName('test_increment_step_'.$this->testId); + $this->setTotalSteps(10); + + $this->incrementStep(); + $this->assertEquals(1, $this->getCurrentStep()); + $this->assertEquals(10.0, $this->getLocalProgress()); + + $this->incrementStep(4); + $this->assertEquals(5, $this->getCurrentStep()); + $this->assertEquals(50.0, $this->getLocalProgress()); + } + + public function test_set_current_step(): void { + $this->setOverallUniqueName('test_set_current_step_'.$this->testId); + $this->setTotalSteps(100); + + $this->setCurrentStep(25); + $this->assertEquals(25, $this->getCurrentStep()); + $this->assertEquals(25.0, $this->getLocalProgress()); + } + + public function test_increment_step_without_total_steps_throws_exception(): void { + $this->expectException(\LogicException::class); + $this->incrementStep(); + } + + public function test_set_current_step_without_total_steps_throws_exception(): void { + $this->expectException(\LogicException::class); + $this->setCurrentStep(5); + } + + public function test_set_total_steps_invalid_value(): void { + $this->expectException(\InvalidArgumentException::class); + $this->setTotalSteps(0); + } }