From d8aa3b748a038123438f7a7ae3aa9c2225e6b647 Mon Sep 17 00:00:00 2001 From: gaoflow Date: Tue, 28 Jul 2026 16:53:03 +0200 Subject: [PATCH] Clamp negative alpha to zero in AlphaTrait The alpha() setter clamped only the upper bound, so a negative value passed through and serialized to a string the constructor rejects (Rgba/Hsla, and garbage hex for Hexa). Clamp the lower bound too, as the sibling red/green/hue/saturation/lightness setters already do. --- src/Traits/AlphaTrait.php | 2 +- tests/Color/AlphaTest.php | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Traits/AlphaTrait.php b/src/Traits/AlphaTrait.php index 585a52f..8723075 100644 --- a/src/Traits/AlphaTrait.php +++ b/src/Traits/AlphaTrait.php @@ -17,7 +17,7 @@ trait AlphaTrait public function alpha($alpha = null): float|static { if ($alpha !== null) { - $this->alpha = min((float) $alpha, 1.0); + $this->alpha = max(0.0, min((float) $alpha, 1.0)); return $this; } return round($this->alpha, 2); diff --git a/tests/Color/AlphaTest.php b/tests/Color/AlphaTest.php index 966bc20..40e4553 100644 --- a/tests/Color/AlphaTest.php +++ b/tests/Color/AlphaTest.php @@ -57,6 +57,45 @@ public function testIssueValues() } + #[Group('alpha')] + public function testNegativeAlphaIsClampedToZero() + { + foreach ($this->alphaColors() as $color) { + $color->alpha(-0.3); + $this->assertEquals(0.0, $color->alpha(), get_class($color)); + // the serialized string must be a valid input to its own constructor + $class = get_class($color); + $this->assertEquals(0.0, (new $class((string) $color))->alpha()); + } + } + + #[Group('alpha')] + public function testAlphaAboveOneStillClampsToOne() + { + foreach ($this->alphaColors() as $color) { + $color->alpha(1.7); + $this->assertEquals(1.0, $color->alpha(), get_class($color)); + $class = get_class($color); + $this->assertEquals(1.0, (new $class((string) $color))->alpha()); + } + } + + #[Group('alpha')] + public function testInRangeAlphaPassesThroughUnchanged() + { + foreach ([0.0, 0.5, 1.0] as $value) { + foreach ($this->alphaColors() as $color) { + $color->alpha($value); + $this->assertEquals($value, $color->alpha(), get_class($color)); + } + } + } + + protected function alphaColors(): array + { + return [new Rgba('10,20,30,0.5'), new Hsla('120,50%,50%,0.5'), new Hexa('112233ff')]; + } + protected function getBaseValues(): array { return [new Rgba('rgba(102, 102, 102, 0.5)'), new Hex('b2b2b2')];