summaryrefslogtreecommitdiff
path: root/src/Router.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/Router.php')
-rw-r--r--src/Router.php71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/Router.php b/src/Router.php
index efcccfa..f666fe5 100644
--- a/src/Router.php
+++ b/src/Router.php
@@ -4,6 +4,77 @@ declare(strict_types=1);
namespace Lightscale\Router;
+use Lightscale\Router\Enums\HttpMethod;
+use Lightscale\Router\Enums\PathSegmentType;
+use Lightscale\Router\Exceptions\NotFoundException;
+use Lightscale\Router\Exceptions\UnknownMethodException;
+use Psr\Http\Message\RequestInterface;
+use Psr\Http\Message\ResponseInterface;
+
class Router
{
+ private PathSegment $root;
+
+ public function __construct()
+ {
+ $this->root = new PathSegment(type: PathSegmentType::Root);
+ }
+
+ public function root(): PathSegment
+ {
+ return $this->root;
+ }
+
+ /** @return string[] */
+ private function splitPath(string $path): array
+ {
+ $split = explode('/', rtrim($path, '/'));
+ array_shift($split);
+
+ return $split;
+ }
+
+ public function findSegment(string $path): ?PathSegmentMatch
+ {
+ $pathSplit = $this->splitPath($path);
+ $seg = $this->root();
+ $params = [];
+
+ while (($v = array_shift($pathSplit)) !== null && null !== $seg) {
+ $seg = $seg->findChild($v);
+
+ if (PathSegmentType::Parameter === $seg?->getType()) {
+ $params[$seg->getValue() ?? ''] = $v;
+ }
+ }
+
+ return null === $seg ? null : new PathSegmentMatch(
+ segment: $seg,
+ parameters: $params
+ );
+ }
+
+ public function dispatch(RequestInterface $request): ResponseInterface
+ {
+ $uri = $request->getUri();
+ $match = $this->findSegment($uri->getPath());
+
+ if (null === $match) {
+ throw new NotFoundException();
+ }
+
+ $segment = $match->segment;
+ $method = $request->getMethod();
+ $method = (
+ HttpMethod::tryFrom(strtolower($method)) ??
+ throw new UnknownMethodException()
+ );
+ $route = $segment->getRoute($method);
+
+ if (null === $route) {
+ throw new NotFoundException();
+ }
+
+ return $route($request);
+ }
}