From 80b56b26e6e50cf6632c898fd11edb4b3fc922db Mon Sep 17 00:00:00 2001 From: pigolitsyn_m <56753446+mpa12@users.noreply.github.com> Date: Tue, 16 Jul 2024 02:06:43 +1000 Subject: [PATCH] feat: Added enumeration of HTTP response status codes (#303) Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jonah Lawrence --- CONTRIBUTING.md | 2 +- composer.json | 9 +- src/controllers/RendererController.php | 14 ++- src/enums/ResponseEnum.php | 90 +++++++++++++++++++ .../UnprocessableEntityException.php | 9 ++ src/interfaces/IStatusException.php | 6 ++ src/models/ErrorModel.php | 6 +- src/models/GoogleFontConverter.php | 8 +- src/models/RendererModel.php | 6 +- 9 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 src/enums/ResponseEnum.php create mode 100644 src/exceptions/UnprocessableEntityException.php create mode 100644 src/interfaces/IStatusException.php diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32bbadc..031cf33 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Make sure your request is meaningful and you have tested the app locally before #### Requirements -- [PHP 7.4+](https://www.apachefriends.org/index.html) +- [PHP 8.1+](https://www.apachefriends.org/index.html) - [Composer](https://getcomposer.org) #### Linux diff --git a/composer.json b/composer.json index dad2ad8..4742f34 100644 --- a/composer.json +++ b/composer.json @@ -16,18 +16,21 @@ "classmap": [ "src/models/", "src/views/", - "src/controllers/" + "src/controllers/", + "src/enums/", + "src/exceptions/", + "src/interfaces/" ] }, "require": { - "php": "^7.4|^8.0", + "php": "^8.1", "vlucas/phpdotenv": "^5.3" }, "require-dev": { "phpunit/phpunit": "^11" }, "scripts": { - "start": "php7 -S localhost:8000 -t src || php -S localhost:8000 -t src", + "start": "php8 -S localhost:8000 -t src || php -S localhost:8000 -t src", "test": "./vendor/bin/phpunit --testdox tests", "format:check": "prettier --check *.md **/**/*.{php,md,js,css} --print-width 120", "format": "prettier --write *.md **/**/*.{php,md,js,css} --print-width 120" diff --git a/src/controllers/RendererController.php b/src/controllers/RendererController.php index 5cf5dcd..3a68a7b 100644 --- a/src/controllers/RendererController.php +++ b/src/controllers/RendererController.php @@ -20,12 +20,17 @@ class RendererController */ private $params; + /** + * @var ResponseEnum $statusCode Response status code + */ + private ResponseEnum $statusCode = ResponseEnum::HTTP_OK; + /** * Construct RendererController * * @param array $params request parameters */ - public function __construct($params) + public function __construct(array $params) { $this->params = $params; @@ -40,6 +45,10 @@ class RendererController $this->model = new ErrorModel(__DIR__ . "/../templates/error.php", $error->getMessage()); // create error rendering view $this->view = new ErrorView($this->model); + + // set status code + $this->statusCode = + $error instanceof IStatusException ? $error->getStatus() : ResponseEnum::HTTP_INTERNAL_SERVER_ERROR; } } @@ -89,6 +98,9 @@ class RendererController // set cache headers $this->setCacheRefreshDaily(); + + // set status code + http_response_code($this->statusCode->value); } /** diff --git a/src/enums/ResponseEnum.php b/src/enums/ResponseEnum.php new file mode 100644 index 0000000..0328d3e --- /dev/null +++ b/src/enums/ResponseEnum.php @@ -0,0 +1,90 @@ +value === 200) { + * echo "Request was successful."; + * } + */ +enum ResponseEnum: int +{ + // 1xx: Informational + case HTTP_CONTINUE = 100; + case HTTP_SWITCHING_PROTOCOLS = 101; + case HTTP_PROCESSING = 102; + + // 2xx: Success + case HTTP_OK = 200; + case HTTP_CREATED = 201; + case HTTP_ACCEPTED = 202; + case HTTP_NON_AUTHORITATIVE_INFORMATION = 203; + case HTTP_NO_CONTENT = 204; + case HTTP_RESET_CONTENT = 205; + case HTTP_PARTIAL_CONTENT = 206; + case HTTP_MULTI_STATUS = 207; + case HTTP_ALREADY_REPORTED = 208; + case HTTP_IM_USED = 226; + + // 3xx: Redirection + case HTTP_MULTIPLE_CHOICES = 300; + case HTTP_MOVED_PERMANENTLY = 301; + case HTTP_FOUND = 302; + case HTTP_SEE_OTHER = 303; + case HTTP_NOT_MODIFIED = 304; + case HTTP_USE_PROXY = 305; + case HTTP_SWITCH_PROXY = 306; // No longer used + case HTTP_TEMPORARY_REDIRECT = 307; + case HTTP_PERMANENT_REDIRECT = 308; + + // 4xx: Client Error + case HTTP_BAD_REQUEST = 400; + case HTTP_UNAUTHORIZED = 401; + case HTTP_PAYMENT_REQUIRED = 402; + case HTTP_FORBIDDEN = 403; + case HTTP_NOT_FOUND = 404; + case HTTP_METHOD_NOT_ALLOWED = 405; + case HTTP_NOT_ACCEPTABLE = 406; + case HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; + case HTTP_REQUEST_TIMEOUT = 408; + case HTTP_CONFLICT = 409; + case HTTP_GONE = 410; + case HTTP_LENGTH_REQUIRED = 411; + case HTTP_PRECONDITION_FAILED = 412; + case HTTP_PAYLOAD_TOO_LARGE = 413; + case HTTP_URI_TOO_LONG = 414; + case HTTP_UNSUPPORTED_MEDIA_TYPE = 415; + case HTTP_RANGE_NOT_SATISFIABLE = 416; + case HTTP_EXPECTATION_FAILED = 417; + case HTTP_IM_A_TEAPOT = 418; + case HTTP_MISDIRECTED_REQUEST = 421; + case HTTP_UNPROCESSABLE_ENTITY = 422; + case HTTP_LOCKED = 423; + case HTTP_FAILED_DEPENDENCY = 424; + case HTTP_TOO_EARLY = 425; + case HTTP_UPGRADE_REQUIRED = 426; + case HTTP_PRECONDITION_REQUIRED = 428; + case HTTP_TOO_MANY_REQUESTS = 429; + case HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431; + case HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451; + + // 5xx: Server Error + case HTTP_INTERNAL_SERVER_ERROR = 500; + case HTTP_NOT_IMPLEMENTED = 501; + case HTTP_BAD_GATEWAY = 502; + case HTTP_SERVICE_UNAVAILABLE = 503; + case HTTP_GATEWAY_TIMEOUT = 504; + case HTTP_HTTP_VERSION_NOT_SUPPORTED = 505; + case HTTP_VARIANT_ALSO_NEGOTIATES = 506; + case HTTP_INSUFFICIENT_STORAGE = 507; + case HTTP_LOOP_DETECTED = 508; + case HTTP_NOT_EXTENDED = 510; + case HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; +} diff --git a/src/exceptions/UnprocessableEntityException.php b/src/exceptions/UnprocessableEntityException.php new file mode 100644 index 0000000..275b731 --- /dev/null +++ b/src/exceptions/UnprocessableEntityException.php @@ -0,0 +1,9 @@ +message = $message; $this->template = $template; diff --git a/src/models/GoogleFontConverter.php b/src/models/GoogleFontConverter.php index affea3b..552d2f0 100644 --- a/src/models/GoogleFontConverter.php +++ b/src/models/GoogleFontConverter.php @@ -1,5 +1,7 @@ value) { throw new InvalidArgumentException("Failed to fetch Google Font from API."); } return $response; diff --git a/src/models/RendererModel.php b/src/models/RendererModel.php index a8d47e3..ea2ee66 100644 --- a/src/models/RendererModel.php +++ b/src/models/RendererModel.php @@ -122,7 +122,7 @@ class RendererModel private function checkLines($lines) { if (!$lines) { - throw new InvalidArgumentException("Lines parameter must be set."); + throw new UnprocessableEntityException("Lines parameter must be set."); } if (strlen($this->separator) === 1) { $lines = rtrim($lines, $this->separator); @@ -176,7 +176,7 @@ class RendererModel { $digits = intval(preg_replace("/[^0-9\-]/", "", $num)); if ($digits <= 0) { - throw new InvalidArgumentException("$field must be a positive number."); + throw new UnprocessableEntityException("$field must be a positive number."); } return $digits; } @@ -192,7 +192,7 @@ class RendererModel { $digits = intval(preg_replace("/[^0-9\-]/", "", $num)); if ($digits < 0) { - throw new InvalidArgumentException("$field must be a non-negative number."); + throw new UnprocessableEntityException("$field must be a non-negative number."); } return $digits; }