diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/BasicStrategy.php | 23 | ||||
| -rw-r--r-- | src/Contracts/Strategy.php | 15 | ||||
| -rw-r--r-- | src/Route.php | 11 | ||||
| -rw-r--r-- | src/RouteCall.php | 17 | ||||
| -rw-r--r-- | src/Router.php | 77 |
5 files changed, 130 insertions, 13 deletions
diff --git a/src/BasicStrategy.php b/src/BasicStrategy.php new file mode 100644 index 0000000..62bc48e --- /dev/null +++ b/src/BasicStrategy.php @@ -0,0 +1,23 @@ +<?php + +declare(strict_types=1); + +namespace Lightscale\Router; + +use Lightscale\Router\Contracts\Strategy; +use Lightscale\Router\Exceptions\NotFoundException; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +class BasicStrategy implements Strategy +{ + public function runRoute(RouteCall $call): ResponseInterface + { + return ($call->route->getHandler())($call); + } + + public function notFound(RequestInterface $request): ResponseInterface + { + throw new NotFoundException(); + } +} diff --git a/src/Contracts/Strategy.php b/src/Contracts/Strategy.php new file mode 100644 index 0000000..81d6ec3 --- /dev/null +++ b/src/Contracts/Strategy.php @@ -0,0 +1,15 @@ +<?php + +declare(strict_types=1); + +namespace Lightscale\Router\Contracts; + +use Lightscale\Router\RouteCall; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; + +interface Strategy +{ + public function runRoute(RouteCall $call): ResponseInterface; + public function notFound(RequestInterface $request): ResponseInterface; +} diff --git a/src/Route.php b/src/Route.php index aeb3f66..af08ded 100644 --- a/src/Route.php +++ b/src/Route.php @@ -6,7 +6,6 @@ namespace Lightscale\Router; use Closure; use Lightscale\Router\Enums\HttpMethod; -use Psr\Http\Message\RequestInterface; class Route { @@ -26,11 +25,6 @@ class Route } } - public function __invoke(RequestInterface $request): mixed - { - return ($this->handler)($request); - } - public function getMethod(): HttpMethod { return $this->method; @@ -50,4 +44,9 @@ class Route { return $this->segment->getPath(); } + + public function getHandler(): Closure + { + return $this->handler; + } } diff --git a/src/RouteCall.php b/src/RouteCall.php new file mode 100644 index 0000000..b76a780 --- /dev/null +++ b/src/RouteCall.php @@ -0,0 +1,17 @@ +<?php + +declare(strict_types=1); + +namespace Lightscale\Router; + +use Psr\Http\Message\RequestInterface; + +class RouteCall +{ + /** @param array<string, string> $parameters */ + public function __construct( + public RequestInterface $request, + public Route $route, + public array $parameters, + ) {} +} diff --git a/src/Router.php b/src/Router.php index f666fe5..ddd3220 100644 --- a/src/Router.php +++ b/src/Router.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace Lightscale\Router; +use Lightscale\Router\Contracts\Strategy; use Lightscale\Router\Enums\HttpMethod; use Lightscale\Router\Enums\PathSegmentType; use Lightscale\Router\Exceptions\NotFoundException; @@ -14,10 +15,22 @@ use Psr\Http\Message\ResponseInterface; class Router { private PathSegment $root; + private Strategy $strategy; public function __construct() { $this->root = new PathSegment(type: PathSegmentType::Root); + $this->strategy = new BasicStrategy; + } + + public function getStrategy(): Strategy + { + return $this->strategy; + } + + public function setStrategy(Strategy $strategy): void + { + $this->strategy = $strategy; } public function root(): PathSegment @@ -60,21 +73,71 @@ class Router $match = $this->findSegment($uri->getPath()); if (null === $match) { - throw new NotFoundException(); + return $this->strategy->notFound($request); } $segment = $match->segment; $method = $request->getMethod(); - $method = ( - HttpMethod::tryFrom(strtolower($method)) ?? - throw new UnknownMethodException() - ); + $method = HttpMethod::tryFrom(strtolower($method)); + + if ($method === null) { + return $this->strategy->notFound($request); + } + $route = $segment->getRoute($method); if (null === $route) { - throw new NotFoundException(); + return $this->strategy->notFound($request); + } + + $call = new RouteCall( + $request, + $route, + $match->parameters, + ); + + return $this->strategy->runRoute($call); + } + + public function route(HttpMethod $method, string $path, callable $handler): void + { + $pathSplit = $this->splitPath($path); + + $seg = $this->root(); + while(($v = array_shift($pathSplit)) !== null) { + $seg = $seg->child($v); } - return $route($request); + $seg->addRoute(new Route($method, $handler)); + } + + public function get(string $path, callable $handler): void + { + $this->route(HttpMethod::Get, $path, $handler); + } + + public function post(string $path, callable $handler): void + { + $this->route(HttpMethod::Post, $path, $handler); + } + + public function put(string $path, callable $handler): void + { + $this->route(HttpMethod::Put, $path, $handler); + } + + public function patch(string $path, callable $handler): void + { + $this->route(HttpMethod::Patch, $path, $handler); + } + + public function delete(string $path, callable $handler): void + { + $this->route(HttpMethod::Delete, $path, $handler); + } + + public function any(string $path, callable $handler): void + { + $this->route(HttpMethod::Any, $path, $handler); } } |
