diff --git a/src/Exceptions/HexTooLongException.php b/src/Exceptions/HexTooLongException.php index 0828d1e..5e9e5fb 100644 --- a/src/Exceptions/HexTooLongException.php +++ b/src/Exceptions/HexTooLongException.php @@ -1,5 +1,7 @@ -hex = $hex; - $this->brightnessModifier = new HexBrightnessModifier(); - - $this->validateHex(); - } - - /** - * @param integer $percentage - * - * @return string - */ - public function lighten( $percentage = 0 ) - { - $this->validatePercentage($percentage); - - if ( $percentage === 0 ) - { - return $this->hex; - } - - return $this->brightnessModifier->adjustBrightness( $this->hex, $percentage ); - } - - /** - * @param integer $percentage - * - * @return string - */ - public function darken( $percentage = 0 ) - { - $this->validatePercentage($percentage); - - if ( $percentage === 0 ) - { - return $this->hex; - } - - return $this->brightnessModifier->adjustBrightness( $this->hex, $percentage * -1 ); - } - - private function validatePercentage( $percentage ) - { - if ( $percentage < 0 ) - { - throw new PercentageTooLowException( "The percentage ({$percentage}) is below zero (0)" ); - } - - if ( $percentage > 100 ) - { - throw new PercentageTooHighException( "The percentage ({$percentage}) is above 100" ); - } - } - - private function validateHex() { - $hex = str_replace( '#', '', $this->hex ); - - if ( strlen( $hex ) < self::HEX_MIN_LENGTH ) - { - throw new HexTooShortException( "The hex ({$hex}) was too short. Minimum length is: " . self::HEX_MIN_LENGTH . " characters, without hashtag." ); - } - - if ( strlen( $hex ) > self::HEX_MAX_LENGTH ) - { - throw new HexTooLongException( "The hex ({$hex}) was too long. Maximum length is: " . self::HEX_MAX_LENGTH . " characters, without hashtag." ); - } - } + private $hex; + private $brightnessModifier; + + const HEX_MIN_LENGTH = 3; + const HEX_MAX_LENGTH = 6; + + public function __construct($hex) + { + $this->hex = $hex; + $this->brightnessModifier = new HexBrightnessModifier(); + + $this->validateHex(); + } + + /** + * @param int $percentage + * + * @return string + */ + public function lighten($percentage = 0) + { + $this->validatePercentage($percentage); + + if ($percentage === 0) { + return $this->hex; + } + + return $this->brightnessModifier->adjustBrightness($this->hex, $percentage); + } + + /** + * @param int $percentage + * + * @return string + */ + public function darken($percentage = 0) + { + $this->validatePercentage($percentage); + + if ($percentage === 0) { + return $this->hex; + } + + return $this->brightnessModifier->adjustBrightness($this->hex, $percentage * -1); + } + + private function validatePercentage($percentage) + { + if ($percentage < 0) { + throw new PercentageTooLowException("The percentage ({$percentage}) is below zero (0)"); + } + + if ($percentage > 100) { + throw new PercentageTooHighException("The percentage ({$percentage}) is above 100"); + } + } + + private function validateHex() + { + $hex = str_replace('#', '', $this->hex); + + if (strlen($hex) < self::HEX_MIN_LENGTH) { + throw new HexTooShortException("The hex ({$hex}) was too short. Minimum length is: ".self::HEX_MIN_LENGTH.' characters, without hashtag.'); + } + + if (strlen($hex) > self::HEX_MAX_LENGTH) { + throw new HexTooLongException("The hex ({$hex}) was too long. Maximum length is: ".self::HEX_MAX_LENGTH.' characters, without hashtag.'); + } + } } diff --git a/src/HexBrightnessModifier.php b/src/HexBrightnessModifier.php index b5151fa..b943691 100644 --- a/src/HexBrightnessModifier.php +++ b/src/HexBrightnessModifier.php @@ -4,88 +4,85 @@ class HexBrightnessModifier { - const STEPS = 255; - const STEPS_MAX = 255; - const STEPS_MIN = -255; - - private $hadHashtag = false; - - /** - * @param string $hex - * @param integer $percentage - * - * @return string - */ - public function adjustBrightness( $hex, $percentage ) - { - $steps = $this->generateSteps( $percentage ); - - $hex = $this->parseHex( $hex ); - $hex = $this->adjustHex( $hex, $steps ); - - // Append hashtag if was inputted with a hashtag - if ( $this->hadHashtag ) - { - $hex = "#{$hex}"; - } - - return $hex; - } - - /** - * @param integer $percentage - * - * @return integer - */ - private function generateSteps( $percentage ) - { - $steps = (int) round( ( $percentage / 100 ) * self::STEPS ); - $steps = max( self::STEPS_MIN, min( self::STEPS_MAX, $steps ) ); - - return $steps; - } - - /** - * @param string $hex - * - * @return mixed|string - */ - private function parseHex( $hex ) - { - $this->hadHashtag = $hex[0] === '#'; - - $hex = str_replace( '#', '', $hex ); - $hex = strtolower( $hex ); - - if ( strlen( $hex ) === 3 ) - { - $hex = str_repeat( substr( $hex, 0, 1 ), 2 ) . str_repeat( substr( $hex, 1, 1 ), 2 ) . str_repeat( substr( $hex, 2, 1 ), 2 ); - } - - return $hex; - } - - /** - * @param string $hex - * @param integer $steps - * - * @return string - */ - private function adjustHex( $hex, $steps ) - { - $return = ''; - $parts = str_split( $hex, 2 ); - - foreach ( $parts as $color ) - { - $color = hexdec( $color ); - $color = max( 0, min( 255, $color + $steps ) ); - - $return .= str_pad( dechex( $color ), 2, '0', STR_PAD_LEFT ); - } - - $return = strtolower( $return ); - - return $return; - } + const STEPS = 255; + const STEPS_MAX = 255; + const STEPS_MIN = -255; + + private $hadHashtag = false; + + /** + * @param string $hex + * @param int $percentage + * + * @return string + */ + public function adjustBrightness($hex, $percentage) + { + $steps = $this->generateSteps($percentage); + + $hex = $this->parseHex($hex); + $hex = $this->adjustHex($hex, $steps); + + // Append hashtag if was inputted with a hashtag + if ($this->hadHashtag) { + $hex = "#{$hex}"; + } + + return $hex; + } + + /** + * @param int $percentage + * + * @return int + */ + private function generateSteps($percentage) + { + $steps = (int) round(($percentage / 100) * self::STEPS); + $steps = max(self::STEPS_MIN, min(self::STEPS_MAX, $steps)); + + return $steps; + } + + /** + * @param string $hex + * + * @return mixed|string + */ + private function parseHex($hex) + { + $this->hadHashtag = $hex[0] === '#'; + + $hex = str_replace('#', '', $hex); + $hex = strtolower($hex); + + if (strlen($hex) === 3) { + $hex = str_repeat(substr($hex, 0, 1), 2).str_repeat(substr($hex, 1, 1), 2).str_repeat(substr($hex, 2, 1), 2); + } + + return $hex; + } + + /** + * @param string $hex + * @param int $steps + * + * @return string + */ + private function adjustHex($hex, $steps) + { + $return = ''; + $parts = str_split($hex, 2); + + foreach ($parts as $color) { + $color = hexdec($color); + $color = max(0, min(255, $color + $steps)); + + $return .= str_pad(dechex($color), 2, '0', STR_PAD_LEFT); + } + + $return = strtolower($return); + + return $return; + } } diff --git a/tests/HexModifierTest.php b/tests/HexModifierTest.php index 87589d2..18dde5b 100644 --- a/tests/HexModifierTest.php +++ b/tests/HexModifierTest.php @@ -4,104 +4,107 @@ class HexModifierTest extends TestCase { - public function test_can_darken_color() - { - // Regular - $hex = new \LasseRafn\Hexer\Hex( '#fff' ); + public function test_can_darken_color() + { + // Regular + $hex = new \LasseRafn\Hexer\Hex('#fff'); - $this->assertEquals( '#d9d9d9', $hex->darken( 15 ) ); + $this->assertEquals('#d9d9d9', $hex->darken(15)); - // With uppercase - $hex = new \LasseRafn\Hexer\Hex( '#FFF' ); + // With uppercase + $hex = new \LasseRafn\Hexer\Hex('#FFF'); - $this->assertEquals( '#d9d9d9', $hex->darken( 15 ) ); + $this->assertEquals('#d9d9d9', $hex->darken(15)); - // With 6 characters - $hex = new \LasseRafn\Hexer\Hex( '#ffffff' ); + // With 6 characters + $hex = new \LasseRafn\Hexer\Hex('#ffffff'); - $this->assertEquals( '#d9d9d9', $hex->darken( 15 ) ); + $this->assertEquals('#d9d9d9', $hex->darken(15)); - // Without hashtag - $hex = new \LasseRafn\Hexer\Hex( 'fff' ); + // Without hashtag + $hex = new \LasseRafn\Hexer\Hex('fff'); - $this->assertEquals( 'd9d9d9', $hex->darken( 15 ) ); - } + $this->assertEquals('d9d9d9', $hex->darken(15)); + } - public function test_can_lighten_color() - { - // Regular - $hex = new \LasseRafn\Hexer\Hex( '#333' ); + public function test_can_lighten_color() + { + // Regular + $hex = new \LasseRafn\Hexer\Hex('#333'); - $this->assertEquals( '#595959', $hex->lighten( 15 ) ); + $this->assertEquals('#595959', $hex->lighten(15)); - // With uppercase - $hex = new \LasseRafn\Hexer\Hex( '#333' ); + // With uppercase + $hex = new \LasseRafn\Hexer\Hex('#333'); - $this->assertEquals( '#595959', $hex->lighten( 15 ) ); + $this->assertEquals('#595959', $hex->lighten(15)); - // With 6 characters - $hex = new \LasseRafn\Hexer\Hex( '#333333' ); + // With 6 characters + $hex = new \LasseRafn\Hexer\Hex('#333333'); - $this->assertEquals( '#595959', $hex->lighten( 15 ) ); + $this->assertEquals('#595959', $hex->lighten(15)); - // Without hashtag - $hex = new \LasseRafn\Hexer\Hex( '333' ); + // Without hashtag + $hex = new \LasseRafn\Hexer\Hex('333'); - $this->assertEquals( '595959', $hex->lighten( 15 ) ); - } + $this->assertEquals('595959', $hex->lighten(15)); + } - public function test_can_modify_colors_beside_black_and_white() - { - // Regular - $hex = new \LasseRafn\Hexer\Hex( '#ff000' ); + public function test_can_modify_colors_beside_black_and_white() + { + // Regular + $hex = new \LasseRafn\Hexer\Hex('#ff000'); - $this->assertEquals( '#ff2626', $hex->lighten( 15 ) ); + $this->assertEquals('#ff2626', $hex->lighten(15)); - // With uppercase - $hex = new \LasseRafn\Hexer\Hex( '#5e77b0' ); + // With uppercase + $hex = new \LasseRafn\Hexer\Hex('#5e77b0'); - $this->assertEquals( '#2b447d', $hex->darken( 20 ) ); + $this->assertEquals('#2b447d', $hex->darken(20)); - // With large percentages - $hex = new \LasseRafn\Hexer\Hex( '21ed4a' ); + // With large percentages + $hex = new \LasseRafn\Hexer\Hex('21ed4a'); - $this->assertEquals( 'd4fffd', $hex->lighten( 70 ) ); - } + $this->assertEquals('d4fffd', $hex->lighten(70)); + } - public function test_will_fail_with_too_long_hex_input() { - $this->expectException(\LasseRafn\Hexer\Exceptions\HexTooLongException::class); + public function test_will_fail_with_too_long_hex_input() + { + $this->expectException(\LasseRafn\Hexer\Exceptions\HexTooLongException::class); - new \LasseRafn\Hexer\Hex( '#fffffff' ); - new \LasseRafn\Hexer\Hex( 'fffffff' ); - } + new \LasseRafn\Hexer\Hex('#fffffff'); + new \LasseRafn\Hexer\Hex('fffffff'); + } - public function test_will_fail_with_too_short_hex_input() { - $this->expectException(\LasseRafn\Hexer\Exceptions\HexTooShortException::class); + public function test_will_fail_with_too_short_hex_input() + { + $this->expectException(\LasseRafn\Hexer\Exceptions\HexTooShortException::class); - new \LasseRafn\Hexer\Hex( '#22' ); - new \LasseRafn\Hexer\Hex( '22' ); - } + new \LasseRafn\Hexer\Hex('#22'); + new \LasseRafn\Hexer\Hex('22'); + } - public function test_will_fail_with_too_low_percentage_input() - { - $this->expectException( \LasseRafn\Hexer\Exceptions\PercentageTooLowException::class ); + public function test_will_fail_with_too_low_percentage_input() + { + $this->expectException(\LasseRafn\Hexer\Exceptions\PercentageTooLowException::class); - $hex = new \LasseRafn\Hexer\Hex( '#fff' ); - $hex->lighten(-10); - } + $hex = new \LasseRafn\Hexer\Hex('#fff'); + $hex->lighten(-10); + } - public function test_will_fail_with_too_high_percentage_input() - { - $this->expectException( \LasseRafn\Hexer\Exceptions\PercentageTooHighException::class ); + public function test_will_fail_with_too_high_percentage_input() + { + $this->expectException(\LasseRafn\Hexer\Exceptions\PercentageTooHighException::class); - $hex = new \LasseRafn\Hexer\Hex( '#fff' ); - $hex->lighten(101); - } + $hex = new \LasseRafn\Hexer\Hex('#fff'); + $hex->lighten(101); + } - public function test_will_return_initial_hex_with_zero_percentage() { - $hex = new \LasseRafn\Hexer\Hex('#fff'); + public function test_will_return_initial_hex_with_zero_percentage() + { + $hex = new \LasseRafn\Hexer\Hex('#fff'); - $this->assertEquals('#fff', $hex->lighten()); - $this->assertEquals('#fff', $hex->darken()); - } + $this->assertEquals('#fff', $hex->lighten()); + $this->assertEquals('#fff', $hex->darken()); + } }