From 97ff846cff6f1bd8f5ccf0ea84832ebdeff08fc1 Mon Sep 17 00:00:00 2001 From: Alain Schlesser Date: Mon, 9 Oct 2023 10:22:33 +0200 Subject: [PATCH] Add HTTP status helper class --- src/Utility/HttpStatus.php | 150 +++++++++++++++++++ tests/Utility/HttpStatus/GetTextTest.php | 108 +++++++++++++ tests/Utility/HttpStatus/IsValidCodeTest.php | 98 ++++++++++++ 3 files changed, 356 insertions(+) create mode 100644 src/Utility/HttpStatus.php create mode 100644 tests/Utility/HttpStatus/GetTextTest.php create mode 100644 tests/Utility/HttpStatus/IsValidCodeTest.php diff --git a/src/Utility/HttpStatus.php b/src/Utility/HttpStatus.php new file mode 100644 index 000000000..972413feb --- /dev/null +++ b/src/Utility/HttpStatus.php @@ -0,0 +1,150 @@ + + */ + const MAP = [ + 100 => self::TEXT_100, + 101 => self::TEXT_101, + 200 => self::TEXT_200, + 201 => self::TEXT_201, + 202 => self::TEXT_202, + 203 => self::TEXT_203, + 204 => self::TEXT_204, + 205 => self::TEXT_205, + 206 => self::TEXT_206, + 300 => self::TEXT_300, + 301 => self::TEXT_301, + 302 => self::TEXT_302, + 303 => self::TEXT_303, + 304 => self::TEXT_304, + 305 => self::TEXT_305, + 306 => self::TEXT_306, + 307 => self::TEXT_307, + 400 => self::TEXT_400, + 401 => self::TEXT_401, + 402 => self::TEXT_402, + 403 => self::TEXT_403, + 404 => self::TEXT_404, + 405 => self::TEXT_405, + 406 => self::TEXT_406, + 407 => self::TEXT_407, + 408 => self::TEXT_408, + 409 => self::TEXT_409, + 410 => self::TEXT_410, + 411 => self::TEXT_411, + 412 => self::TEXT_412, + 413 => self::TEXT_413, + 414 => self::TEXT_414, + 415 => self::TEXT_415, + 416 => self::TEXT_416, + 417 => self::TEXT_417, + 418 => self::TEXT_418, + 428 => self::TEXT_428, + 429 => self::TEXT_429, + 431 => self::TEXT_431, + 500 => self::TEXT_500, + 501 => self::TEXT_501, + 502 => self::TEXT_502, + 503 => self::TEXT_503, + 504 => self::TEXT_504, + 505 => self::TEXT_505, + 511 => self::TEXT_511, + ]; + + /** + * Get the status message from a status code. + * + * @param int|string $code Status code. + * @return string Status message. + */ + public static function get_text($code) { + if (self::is_valid_code($code) === false) { + // When the type is correct, add the value to the error message to help debugging. + $type = gettype($code) . ((is_int($code) || is_string($code)) ? " ($code)" : ''); + + throw InvalidArgument::create(1, '$code', 'a valid HTTP status code as an int or numeric string', $type); + } + + return self::MAP[$code]; + } + + /** + * Verify whether a status code is valid. + * + * @param int|string $code Status code to check. + * @return bool Whether the status code is valid. + */ + public static function is_valid_code($code) { + if (!is_int($code) && !is_string($code)) { + return false; + } + + return array_key_exists($code, self::MAP); + } +} diff --git a/tests/Utility/HttpStatus/GetTextTest.php b/tests/Utility/HttpStatus/GetTextTest.php new file mode 100644 index 000000000..9028438be --- /dev/null +++ b/tests/Utility/HttpStatus/GetTextTest.php @@ -0,0 +1,108 @@ + [404, 'Not Found'], + 'string key' => ['502', 'Bad Gateway'], + ]; + } + + /** + * Test retrieving a valid status code. + * + * @dataProvider dataAccessValidEntry + * + * @covers ::get_text + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessValidEntry($code, $text) { + $this->assertSame($text, HttpStatus::get_text($code)); + } + + /** + * Data provider. + * + * @return array + */ + public static function dataAccessInvalidType() { + return TypeProviderHelper::getAllExcept(TypeProviderHelper::GROUP_INT, TypeProviderHelper::GROUP_STRING); + } + + /** + * Test retrieving a status code with an invalid type. + * + * @dataProvider dataAccessInvalidType + * + * @covers ::get_text + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessInvalidType($code) { + $this->expectException(InvalidArgument::class); + $this->expectExceptionMessage('a valid HTTP status code as an int or numeric string'); + HttpStatus::get_text($code); + } + + /** + * Data provider. + * + * @return array + */ + public static function dataAccessInvalidCode() { + return [ + 'negative integer' => [-1], + 'zero integer' => [0], + 'too low integer' => [42], + 'too high integer' => [1000], + 'negative string' => ['-1'], + 'zero string' => ['0'], + 'too low string' => ['42'], + 'too high string' => ['1000'], + ]; + } + + /** + * Test retrieving a status code with a matching type but an invalid code. + * + * @dataProvider dataAccessInvalidCode + * + * @covers ::get_text + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessInvalidCode($code) { + $this->expectException(InvalidArgument::class); + $this->expectExceptionMessage( + sprintf( + 'a valid HTTP status code as an int or numeric string, %s (%s) given', + gettype($code), + $code + ) + ); + HttpStatus::get_text($code); + } +} diff --git a/tests/Utility/HttpStatus/IsValidCodeTest.php b/tests/Utility/HttpStatus/IsValidCodeTest.php new file mode 100644 index 000000000..ec375afef --- /dev/null +++ b/tests/Utility/HttpStatus/IsValidCodeTest.php @@ -0,0 +1,98 @@ + [404], + 'string key' => ['502'], + ]; + } + + /** + * Test a valid status code. + * + * @dataProvider dataAccessValidEntry + * + * @covers ::is_valid_code + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessValidEntry($code) { + $this->assertTrue(HttpStatus::is_valid_code($code)); + } + + /** + * Data provider. + * + * @return array + */ + public static function dataAccessInvalidType() { + return TypeProviderHelper::getAllExcept(TypeProviderHelper::GROUP_INT, TypeProviderHelper::GROUP_STRING); + } + + /** + * Test retrieving a status code with an invalid type. + * + * @dataProvider dataAccessInvalidType + * + * @covers ::is_valid_code + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessInvalidType($code) { + $this->assertFalse(HttpStatus::is_valid_code($code)); + } + + /** + * Data provider. + * + * @return array + */ + public static function dataAccessInvalidCode() { + return [ + 'negative integer' => [-1], + 'zero integer' => [0], + 'too low integer' => [42], + 'too high integer' => [1000], + 'negative string' => ['-1'], + 'zero string' => ['0'], + 'too low string' => ['42'], + 'too high string' => ['1000'], + ]; + } + + /** + * Test retrieving a status code with a matching type but an invalid code. + * + * @dataProvider dataAccessInvalidCode + * + * @covers ::is_valid_code + * + * @param mixed $code Status code value to test. + * + * @return void + */ + public function testAccessInvalidCode($code) { + $this->assertFalse(HttpStatus::is_valid_code($code)); + } +}