MAPG-86 add classes for routing
This commit is contained in:
parent
7a924c5257
commit
6835db5e1f
76
src/Routing/Route.php
Normal file
76
src/Routing/Route.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php namespace MapGuesser\Routing;
|
||||||
|
|
||||||
|
class Route
|
||||||
|
{
|
||||||
|
private string $id;
|
||||||
|
|
||||||
|
private array $pattern;
|
||||||
|
|
||||||
|
private array $handler;
|
||||||
|
|
||||||
|
public function __construct(string $id, array $pattern, array $handler)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
$this->pattern = $pattern;
|
||||||
|
$this->handler = $handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId(): string
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateLink(array $parameters = []): string
|
||||||
|
{
|
||||||
|
$link = [];
|
||||||
|
|
||||||
|
foreach ($this->pattern as $fragment) {
|
||||||
|
if (preg_match('/^{(\\w+)(\\?)?}$/', $fragment, $matches)) {
|
||||||
|
if (isset($parameters[$matches[1]])) {
|
||||||
|
$link[] = $parameters[$matches[1]];
|
||||||
|
unset($parameters[$matches[1]]);
|
||||||
|
} elseif (!isset($matches[2])) {//TODO: why? parameter not found but not optional
|
||||||
|
$link[] = $fragment;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$link[] = $fragment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryParams = [];
|
||||||
|
foreach ($parameters as $key => $value) {
|
||||||
|
if ($value === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$queryParams[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query = count($queryParams) > 0 ? '?' . http_build_query($queryParams) : '';
|
||||||
|
|
||||||
|
return implode('/', $link) . $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function callController(array $parameters)
|
||||||
|
{
|
||||||
|
$controllerName = $this->handler[0];
|
||||||
|
$controller = new $controllerName();
|
||||||
|
|
||||||
|
return call_user_func([$controller, $this->handler[1]], $parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testAgainst(array $path): ?array
|
||||||
|
{
|
||||||
|
$parameters = [];
|
||||||
|
|
||||||
|
foreach ($path as $i => $fragment) {
|
||||||
|
if (preg_match('/^{(\\w+)(?:\\?)?}$/', $this->pattern[$i], $matches)) {
|
||||||
|
$parameters[$matches[1]] = $fragment;
|
||||||
|
} elseif ($fragment != $this->pattern[$i]) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $parameters;
|
||||||
|
}
|
||||||
|
}
|
83
src/Routing/RouteCollection.php
Normal file
83
src/Routing/RouteCollection.php
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?php namespace MapGuesser\Routing;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
|
||||||
|
class RouteCollection
|
||||||
|
{
|
||||||
|
private array $routes = [];
|
||||||
|
|
||||||
|
private array $searchTable = [
|
||||||
|
'get' => [],
|
||||||
|
'post' => []
|
||||||
|
];
|
||||||
|
|
||||||
|
private array $groupStack = [];
|
||||||
|
|
||||||
|
public function get(string $id, string $pattern, array $handler): void
|
||||||
|
{
|
||||||
|
$this->addRoute('get', $id, $pattern, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function post(string $id, string $pattern, array $handler): void
|
||||||
|
{
|
||||||
|
$this->addRoute('post', $id, $pattern, $handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function group(string $pattern, Closure $group): void
|
||||||
|
{
|
||||||
|
$this->groupStack[] = $pattern;
|
||||||
|
|
||||||
|
$group($this);
|
||||||
|
|
||||||
|
array_pop($this->groupStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRoute(string $id): ?Route
|
||||||
|
{
|
||||||
|
if (!isset($this->routes[$id])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->routes[$id];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function match(string $method, array $uri): ?array
|
||||||
|
{
|
||||||
|
$groupNumber = count($uri);
|
||||||
|
|
||||||
|
if (!isset($this->searchTable[$method][$groupNumber])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->searchTable[$method][$groupNumber] as $route) {
|
||||||
|
if (($parameters = $route->testAgainst($uri)) !== null) {
|
||||||
|
return [$route, $parameters];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addRoute(string $method, string $id, string $pattern, array $handler): void
|
||||||
|
{
|
||||||
|
if (isset($this->routes[$id])) {
|
||||||
|
throw new \Exception('Route already exists: ' . $id);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pattern = array_merge($this->groupStack, explode('/', $pattern));
|
||||||
|
$route = new Route($id, $pattern, $handler);
|
||||||
|
|
||||||
|
$groupNumber = count($pattern);
|
||||||
|
|
||||||
|
$this->searchTable[$method][$groupNumber][] = $route;
|
||||||
|
|
||||||
|
while (preg_match('/^{\\w+\\?}$/', end($pattern))) {
|
||||||
|
$groupNumber--;
|
||||||
|
array_pop($pattern);
|
||||||
|
|
||||||
|
$this->searchTable[$method][$groupNumber][] = $route;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->routes[$id] = $route;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user