diff --git a/.gitignore b/.gitignore index e00353f..283692e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ # VSCode .vscode/* -tools/HttpExceptionGeneration/HttpExceptions.md \ No newline at end of file +tools/HttpExceptionGeneration/HttpExceptions.md + +index.php +tools/HttpExceptions/HttpExceptions.md \ No newline at end of file diff --git a/README.md b/README.md index 5d59c12..d71558b 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ Totally Not Another PHP Framework's Route Component # Table of Contents +- [Tnapf/Router](#tnapfrouter) +- [Table of Contents](#table-of-contents) - [Installation](#installation) -- [Basic Usage](#basic-usage) - [Routing](#routing) - [Routing Shorthands](#routing-shorthands) - [Route Patterns](#route-patterns) @@ -13,8 +14,6 @@ Totally Not Another PHP Framework's Route Component - [Dynamic Placeholder-based Route Patterns](#dynamic-placeholder-based-route-patterns) - [Dynamic PCRE-based Route Patterns](#dynamic-pcre-based-route-patterns) - [Controllers](#controllers) - - [Anonymous Function Controller](#anonymous-function-controller) - - [Class Controller](#class-controller) - [Template Engine Integration](#template-engine-integration) - [Responding to requests](#responding-to-requests) - [Catchable Routes](#catchable-routes) @@ -23,9 +22,8 @@ Totally Not Another PHP Framework's Route Component - [Custom Catchables](#custom-catchables) - [Available HttpExceptions](#available-httpexceptions) - [Middleware](#middleware) - - [Before Middleware](#before-middleware) - - [After Middleware](#after-middleware) -- [Mounting routes (Group routes)](#mounting-routes-group-routes) +- [Postware](#postware) +- [Group routes](#group-routes) # Installation @@ -33,51 +31,12 @@ Totally Not Another PHP Framework's Route Component composer require tnapf/router ``` -# Basic Usage - -```php -username, $users)) { - throw new HttpNotFound($req); - } - - return new TextResponse("Viewing {$args->username}'s Profile"); -})->setParameter("username", "[a-zA-Z_]+"); - -Router::catch(HttpNotFound::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface { - return new TextResponse("{$args->username} is not registered!"); -}, "/user/{username}")->setParameter("username", "[a-zA-Z_]+"); - -Router::catch(HttpInternalServerError::class, function () { - return new TextResponse("An internal server error has occurred"); -}); - -Router::catch(HttpNotFound::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface { - return new TextResponse("{$req->getRequestTarget()} is not a valid URI"); -}); - -Router::run(); -``` - # Routing You can manually create a route and then store it with the addRoute method ```php -$route = new Route("pattern", function() { /* ... */ }, Methods::GET); +$route = new Route("pattern", RequestHandlerInterfaceImplementation::class, Methods::GET); Router::addRoute($route); ``` @@ -87,7 +46,7 @@ If you want the same controller to be used for multiple methods you can do the f ```php use Tnapf\Router\Enums\Methods; -$route = new Route("pattern", function() { /* ... */ }, Methods::GET, Methods::POST, Methods::HEAD, ...); +$route = new Route("pattern", RequestHandlerInterfaceImplementation::class, Methods::GET, Methods::POST, Methods::HEAD, ...); Router::addRoute($route); ``` @@ -97,19 +56,19 @@ Router::addRoute($route); Shorthands for single request methods are provided ```php -Router::get('pattern', function() { /* ... */ }); -Router::post('pattern', function() { /* ... */ }); -Router::put('pattern', function() { /* ... */ }); -Router::delete('pattern', function() { /* ... */ }); -Router::options('pattern', function() { /* ... */ }); -Router::patch('pattern', function() { /* ... */ }); -Router::head('pattern', function() { /* ... */ }); +Router::get('pattern', RequestHandlerInterfaceImplementation::class); +Router::post('pattern', RequestHandlerInterfaceImplementation::class); +Router::put('pattern', RequestHandlerInterfaceImplementation::class); +Router::delete('pattern', RequestHandlerInterfaceImplementation::class); +Router::options('pattern', RequestHandlerInterfaceImplementation::class); +Router::patch('pattern', RequestHandlerInterfaceImplementation::class); +Router::head('pattern', RequestHandlerInterfaceImplementation::class); ``` You can use this shorthand for a route that can be accessed using any method: ```php -Router::all('pattern', function() { /* ... */ }); +Router::all('pattern', RequestHandlerInterfaceImplementation::class); ``` # Route Patterns @@ -131,10 +90,15 @@ Examples: Usage Examples: ```php -Router::get('/about', function(ServerRequestInterface $req, ResponseInterface $res) { - $res->getBody()->write("Hello World"); - return $res; -}); +class AboutController implements RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $response->getBody()->write("Hello World"); + return $response; + } +} + +Router::get('/about', AboutController::class); ``` ## Dynamic Placeholder-based Route Patterns @@ -152,10 +116,15 @@ Examples: Placeholders are easier to use than PRCEs, but offer you less control as they internally get translated to a PRCE that matches any character (`.*`). ```php -Router::get('/movies/{movieId}/photos/{photoId}', function(ServerRequestInterface $req, ResponseInterface $res, stdClass $args) { - $res->getBody()->write('Movie #'.$args->movieId.', photo #'.$args->photoId); - return $res; -}); +class MovieController implements \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $res->getBody()->write('Movie #'.$args->movieId.', photo #'.$args->photoId); + return $res; + } +} + +Router::get('/movies/{movieId}/photos/{photoId}', MovieController::class); ``` ## Dynamic PCRE-based Route Patterns @@ -175,54 +144,33 @@ Note: The [PHP PCRE Cheat Sheet](https://courses.cs.washington.edu/courses/cse15 The __subpatterns__ defined in Dynamic PCRE-based Route Patterns are passed into the route's controller like __dynamic placeholders__. ```php -Router::get('/hello/{name}', function(ServerRequestInterface $req, ResponseInterface $res, stdClass $args) { - $res->getBody()->write('Hello '.htmlentities($args->name)); - return $res; -})->setParameter("name", "\w+"); -``` - -Note: The leading `/` at the very beginning of a route pattern is not mandatory, but is recommended. - -When multiple subpatterns are defined, the resulting __route handling parameters__ are passed into the route handling function in the order they are defined: +class HelloController implements \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $response->getBody()->write('Hello '.htmlentities($args->name)); + return $response; + } +} -```php -Router::get('/movies/{movieId}/photos/{photoId}', function(ServerRequestInterface $req, ServerResponseInterface $res, stdClass $args) { - $res->getBody()->write('Movie #'.$args->movieId.', photo #'.$args->photoId); - return $res; -})->setParameter("movieId", "\d+")->setParameter("photoId", "\d+"); +Router::get('/hello/{name}', HelloController::class)->setParameter("name", "\w+"); ``` - +] # Controllers -When defining a route you can either pass an anonymous function or an array that contains a class along with a static method to invoke. Additionally, your controller must return an implementation of the PSR7 Response Interface - -## Anonymous Function Controller +When defining a route you pass a string of a class that implements `Tnapf\Router\Interfaces\RequestHandlerInterface` ```php -Router::get("/home", function (ServerRequestInterface $req, ResponseInterface $res) { - $res->getBody()->write("Welcome home!"); - return $res; -}); -``` - -## Class Controller - -Create a class with a static method to handle the route - -```php -class HomeController extends Controller { - public static function handle(ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface +class HomeController implements \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface { - $res->getBody()->write("Welcome home!"); - return $res; + $response->getBody()->write('Welcome Home!'); + return $response; } } ``` -Then insert the class string into an array the first key is the class string and the second is the name of the method - ```php -Router::get("/home", [HomeController::class, "handle"]); +Router::get("/home", HomeController::class); ``` # Template Engine Integration @@ -237,13 +185,21 @@ $env->twig = new Environment(new \Twig\Loader\FilesystemLoader("/path/to/views") // ... -Router::get("/home", function (ServerRequestInterface $req, ResponseInterface $res): ResponseInterface { - return new HtmlResponse($env->get("twig")->render("home.html")); -}); +class HomeController implements \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + return new HtmlResponse($env->get("twig")->render("home.html")); + return $response; + } +} + +// ... + +Router::get("/home", HomeController::class); ``` # Responding to requests -All controllers **MUST** return an implementation of `\Psr\Http\Message\ResponseInterface`. You can use the premade response object passed into the controller *or* instantiate your own. I recommend taking a look at [HttpSoft/Response](https://httpsoft.org/docs/response/v1/#usage) for prebuilt response types. This is also included with the route as it's used for the dev mode +All controllers **MUST** return an implementation of `\Psr\Http\Message\ResponseInterface`. You can use the premade response object passed into the controller *or* instantiate your own. I recommend taking a look at [HttpSoft/Response](https://httpsoft.org/docs/response/v1/#usage) for prebuilt response types. ```php $response = new HttpSoft\Response\HtmlResponse('

HTML

'); $response = new HttpSoft\Response\JsonResponse(['key' => 'value']); @@ -260,30 +216,61 @@ Catchable routes are routes that are only invoked when exceptions are thrown whi ## Catching ```php -Router::catch(HttpException::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args) { - return new TextResponse("An internal server error has occurred"); -}); +class CatchInternalServerError implements \Tnapf\Router\Interfaces\RequestHandlerInterface +{ + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, ?Next $next = null): ResponseInterface + { + $logs = fopen("./error.log", "w+"); + fwrite($logs, $args->exception->__toString()); + fclose($logs); + + return HttpInternalServerError::buildHtmlResponse(); + } +} + +Router::catch(HttpInternalServerError::class, CatchInternalServerError::class); ``` -*Note that `$args->exception` will be the exception throw* +*Note that `$args->exception` will be the exception thrown* ## Specific URI's ```php -Router::catch(HttpNotFound::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface { - return new TextResponse("{$req->getRequestTarget()} is not a valid URI"); -}, "/users/{username}"); +class CatchInternalServerError implements \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, ?Next $next = null): ResponseInterface + { + return new TextResponse("{$req->getRequestTarget()} is not a valid URI"); + } +} + + +Router::catch(HttpNotFound::class, CatchInternalServerError::class, "/users/{username}"); ``` -**Note: Catchers are treated just like routes meaning they can have custom parameters as shown in [Basic Usage](#basic-usage)** +**Note: Catchers are treated just like routes meaning they can have custom parameters** ## Custom Catchables -By default, you can only catch the exceptions shown below but let's say you make a custom exception named `UserNotFound` and want to have a custom response emitted when it's thrown...well you can... +By default, you can only catch the exceptions shown below but you can create a custom exception by implementing `Tnapf\Router\Exceptions\HttpException` ```php -Router::makeCatchable(UserNotFound::class) -``` +class UserNotFound extends \Tnapf\Router\Exceptions\HttpException { + public const CODE = 403; + public const PHRASE = "User Not Found"; + public const DESCRIPTION = "Indicates that the information provided does not link to an existing user."; + public const HREF = "https://docs.example.com/errors/UserNotFound"; +} -and then catch it like a regular HttpException. +class CatchUserNotFound extends \Tnapf\Router\Interfaces\RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, ?Next $next = null): ResponseInterface + { + return new JsonResponse([ + "errors" => ["UserNotFound"], + "data" => [/* a dump of the data received in the request */] + ]); + } +} + +Router::catch(UserNotFound::class, CatchUserNotFound::class); +``` ## Available HttpExceptions @@ -307,7 +294,7 @@ and then catch it like a regular HttpException. |415|[Unsupported Media Type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/415)|[HttpUnsupportedMediaType](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpUnsupportedMediaType.php) |416|[Range Not Satisfiable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/416)|[HttpRangeNotSatisfiable](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpRangeNotSatisfiable.php) |417|[Expectation Failed](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/417)|[HttpExpectationFailed](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpExpectationFailed.php) -|418|[I'm a teapot](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418)|[HttpImateapot](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpImateapot.php) +|418|[I'm A Teapot](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/418)|[HttpImATeapot](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpImATeapot.php) |422|[Unprocessable Entity](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/422)|[HttpUnprocessableEntity](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpUnprocessableEntity.php) |423|[Locked](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/423)|[HttpLocked](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpLocked.php) |424|[Failed Dependency](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/424)|[HttpFailedDependency](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpFailedDependency.php) @@ -321,115 +308,112 @@ and then catch it like a regular HttpException. |502|[Bad Gateway](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/502)|[HttpBadGateway](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpBadGateway.php) |503|[Service Unavailable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503)|[HttpServiceUnavailable](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpServiceUnavailable.php) |504|[Gateway Time-out](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504)|[HttpGatewayTimeout](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpGatewayTimeout.php) -|505|[HTTP Version Not Supported](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/505)|[HttpHTTPVersionNotSupported](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpHTTPVersionNotSupported.php) +|505|[Version Not Supported](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/505)|[HttpVersionNotSupported](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpVersionNotSupported.php) |506|[Variant Also Negotiates](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/506)|[HttpVariantAlsoNegotiates](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpVariantAlsoNegotiates.php) |507|[Insufficient Storage](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/507)|[HttpInsufficientStorage](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpInsufficientStorage.php) |511|[Network Authentication Required](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/511)|[HttpNetworkAuthenticationRequired](https://github.com/tnapf/Router/blob/main/src/Exceptions/HttpNetworkAuthenticationRequired.php) # Middleware -Middleware is software that connects the model and view in an MVC application, facilitating the communication and data flow between these two components while also providing a layer of abstraction, decoupling the model and view and allowing them to interact without needing to know the details of how the other component operates. - -A good example is having before middleware that makes sure the user is an administrator before they go to a restricted page. You could do this in your routes controller for every admin page but that would be redundant. Or for after middleware, you may have a REST API that returns a JSON response. You can have after middleware to make sure the JSON response isn't malformed. +Middleware is part of the request handling process that comes before the route controller is invoked. -## Before Middleware +A good example of middleware is making sure the user is an administrator before they go to a restricted page. You could do this in your routes controller for every admin page sure but, that would be redundant. -You can add middleware to a route by invoking the before method and supply controller(s). +You can add middleware to a route by invoking the addMiddleware method and supply controller(s). **NOTE: The controllers will be invoked in the order they're appended!** ```php -Router::get("/user/{username}", function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface { - $users = ["cmdstr", "realdiegopoptart"]; +class UserExists implements RequestHandlerInterface +{ + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $users = ["command_string", "realdiegopoptart"]; - if (!in_array($args->username, $users)) { - throw new HttpNotFound($req); - } + if (!in_array(strtolower($args->username), $users)) { + throw new HttpNotFound($request); + } - $res->getBody()->write(" {$args->username}'s profile"); + return $next->next($request, $response, $args); + } +} - return $res; -})->setParameter("username", "[a-zA-Z_]+")->before(function (ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Closure $next): ResponseInterface +class Handler implements RequestHandlerInterface { - $res = new TextResponse("Viewing"); + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $response = $response->withAddedHeader("content-type", "text/plain"); + $response->getBody()->write("You're viewing {$args->username}'s profile!"); - $res->getBody()->seek(0, SEEK_END); + return $response; + } +} - return $next($res); // will go to the next part of middleware -}); -``` +Router::get("/profile/{username}", Handler::class)->addMiddleware(UserExists::class)->setParameter("username", "[a-zA-Z_ 0-9]+"); -*Note: If you don't want to proceed to the next part of middleware just return a `ResponseInterface` instead of passing response to the `$next` closure* +Router::emitHttpExceptions(Router::EMIT_HTML_RESPONSE); +Router::run(); +``` -You can also include a class string just like the controller +*Note: If you don't want to proceed to the next part of middleware just return a `ResponseInterface` instead of invoking `Next::Next` -*Special note about middleware, you can pass variables from beforeMiddleware to the main route or from the main route to afterMiddleware by supplying it as the second argument in the next closure. These variables will be added as an additional argument in the next piece of middleware* +# Postware -## After Middleware +Postware is a type of middleware that operates on the response generated by the Controller and can modify the response data before it is sent to the client. While it doesn't sit between the Controller and the View, it does operate on the response after the View has been generated. -Adding after middleware is just like before middleware, just with a different method. +Adding postware is just like middleware, just with a different method. ```php -Router::get("/user/{username}", function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args, Closure $next): ResponseInterface { - $users = ["cmdstr", "realdiegopoptart"]; +class UserExists implements RequestHandlerInterface +{ + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $users = ["command_string", "realdiegopoptart"]; + + if (!in_array(strtolower($args->username), $users)) { + throw new HttpNotFound($request); + } - if (!in_array($args->username, $users)) { - throw new HttpNotFound($req); + return $next->next($request, $response, $args); } +} - $res = new TextResponse("Viewing {$args->username}'s "); +class Handler implements RequestHandlerInterface +{ + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $response = $response->withAddedHeader("content-type", "text/plain"); + $response->getBody()->write("You're viewing "); - $res->getBody()->seek(0, SEEK_END); + return $next->next($request, $response, $args); + } +} - return $next($res); -})->setParameter("username", "[a-zA-Z_]+")->after(function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args): ResponseInterface -{ - $res->getBody()->write("profile"); +class AppendUsername implements RequestHandlerInterface { + public static function handle(ServerRequestInterface $request, ResponseInterface $response, stdClass $args, Next $next): ResponseInterface + { + $response->getBody()->write("{$args->username}'s profile"); + + return $response; + } +} - return $res; -}); +Router::get("/profile/{username}", Handler::class)->addMiddleware(UserExists::class)->addPostware(AppendUsername::class)->setParameter("username", "[a-zA-Z_ 0-9]+"); + +Router::emitHttpExceptions(Router::EMIT_HTML_RESPONSE); +Router::run(); ``` -# Mounting routes (Group routes) +# Group routes -If you would multiple routes to inherit the same prefix URI and before/after middleware then you can define them inside the mount method... +If you would multiple routes to inherit the same prefix URI and before/after middleware then you can define them inside the group method... ```php -Router::mount("/app", function () { - Router::get("/", function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args, int $userId) { - return new TextResponse("Welcome Home!\nUserId: $userId"); - }); - - Router::get("/channel/{channel}", function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args, int $userId) { - return new TextResponse("Looking at channelId {$args->channel} as UserId $userId"); - })->setParameter("channel", "\d+"); - - // You can now mount inside of a mount - Router::mount("/api", function () { - Router::get("/channel/{channel}", function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args, int $userId) { - return new JsonResponse(["Looking at channelId {$args->channel} as UserId $userId"]); - })->setParameter("channel", "\d+"); - - Router::catch(HttpNotFound::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args) { - return new JsonResponse(["Channel id {$args->channel} is invalid"]); - }, "/channel/{channel}")->setParameter("channel", "[a-zA-Z]+"); - - Router::catch(HttpNotFound::class, function () { - return new JsonResponse(["Api Endpoint Not Found"]); - }); - }, [ /* added to the end of already established before/after middleware */ ]); - - Router::catch(HttpNotFound::class, function () { - return new TextResponse("App Route Not Found"); - }); - - Router::catch(HttpNotFound::class, function (ServerRequestInterface $req, ResponseInterface $res, stdClass $args) { - return new TextResponse("Channel id {$args->channel} is invalid"); - }, "/channel/{channel}")->setParameter("channel", "[a-zA-Z]+"); -}, [ // before middleware here - function (ServerRequestInterface $request, ResponseInterface $response, stdClass $args, ?Closure $next = null): ResponseInterface - { - return $next($response, mt_rand(0, 100)); - } -], [ /* after middleware here */ ]); +Router::group("/app", function () { + // Routes that will after /app prepending their declared uri + + Router::group("/api", function () { + // Routes will have /app/api prepending their declared uri + },); +}, [ /* middleware here */ ], [ /* postware here */ ]); ``` diff --git a/composer.json b/composer.json index 2295b92..f742426 100644 --- a/composer.json +++ b/composer.json @@ -15,10 +15,19 @@ } ], "require": { - "httpsoft/http-response": "^1.0", "httpsoft/http-server-request": "^1.0", "php": ">=8.1", "commandstring/utils": "^1.4", - "httpsoft/http-emitter": "^1.0" + "httpsoft/http-emitter": "^1.0", + "httpsoft/http-response": "^1.0" + }, + "require-dev": { + "squizlabs/php_codesniffer": "^3.7" + }, + "scripts": { + "generate-exception-docs": "php tools/HttpExceptions/GenerateDocs.php", + "generate-exception-classes": "php tools/HttpExceptions/GenerateClasses.php", + "cs": "./vendor/bin/phpcs ./src ./examples --standard=psr12", + "csf": "./vendor/bin/phpcbf ./src ./examples --standard=psr12" } } diff --git a/composer.lock b/composer.lock index 5c8642b..e293015 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a16db080b51304861df27441b837a4c5", + "content-hash": "8fc62dea589708ca03b8376e6fe27f06", "packages": [ { "name": "commandstring/utils", @@ -391,7 +391,65 @@ "time": "2016-08-06T14:39:51+00:00" } ], - "packages-dev": [], + "packages-dev": [ + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": [ + "bin/phpcs", + "bin/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2023-02-22T23:07:41+00:00" + } + ], "aliases": [], "minimum-stability": "stable", "stability-flags": [], diff --git a/examples/HttpCodesApi.php b/examples/HttpCodesApi.php deleted file mode 100644 index 50bf522..0000000 --- a/examples/HttpCodesApi.php +++ /dev/null @@ -1,75 +0,0 @@ -code === $code->code) { - if ($args->type === "json") { - return new JsonResponse($code); - } else { - $html = <<