111 lines
3.3 KiB
PHP
111 lines
3.3 KiB
PHP
<?php
|
|
|
|
|
|
namespace Venom\Routing;
|
|
|
|
|
|
use Exception;
|
|
|
|
class Router
|
|
{
|
|
protected string $id = 'defaultRouter';
|
|
protected int $version;
|
|
protected string $prefix = '';
|
|
protected array $routes = [];
|
|
|
|
public function __construct(string $id, int $version, string $prefix = '')
|
|
{
|
|
$this->id = $id;
|
|
$this->version = $version;
|
|
$this->prefix = $prefix;
|
|
}
|
|
|
|
public function addRoutes(array $routes): void
|
|
{
|
|
$this->routes = $routes;
|
|
}
|
|
|
|
public function addRoute(string $path, array $route): void
|
|
{
|
|
$this->routes[$path] = $route;
|
|
}
|
|
|
|
/*
|
|
* return matched route or null
|
|
*/
|
|
public function findRoute($url, $method): ?array
|
|
{
|
|
$url = $this->removeIfFirst($url, $this->prefix);
|
|
// check if full match... this can easily done if the url isset select the empty!
|
|
$method = strtoupper($method);
|
|
$route = $this->getRouteByName($url, $method);
|
|
if ($route !== null) {
|
|
return $route;
|
|
}
|
|
$url = $this->removeIfFirst($url, '/');
|
|
$baseRoute = $this->getNearestBaseRoute(explode("/", $url));
|
|
if ($baseRoute !== null) {
|
|
$count = count($baseRoute['params']);
|
|
return $this->getRouteByName($baseRoute['url'], $method, $count, $baseRoute['params']) ?? $this->getRouteByName($baseRoute['url'], $method);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private function removeIfFirst($rawString, $string)
|
|
{
|
|
if ($string !== '' && 0 === strpos($rawString, $string)) {
|
|
return substr($rawString, strlen($string));
|
|
}
|
|
return $rawString;
|
|
}
|
|
|
|
/* @todo implement Security Check if SecurityModule is used */
|
|
private function getRouteByName($url, $method, $subRoute = '*', $params = []): ?array
|
|
{
|
|
$routeAvailable = isset($this->routes[$url]);
|
|
$subRouteFound = isset($this->routes[$url]['routes'][$subRoute]);
|
|
$methodFound = isset($this->routes[$url]['routes'][$subRoute][$method]);
|
|
if ($routeAvailable && $subRouteFound && $methodFound) {
|
|
return [
|
|
'cl' => $this->routes[$url]['cl'],
|
|
'fnc' => $this->routes[$url]['routes'][$subRoute][$method],
|
|
'params' => $params
|
|
];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private function getNearestBaseRoute(array $params): ?array
|
|
{
|
|
$count = count($params);
|
|
$baseUrlArray = [];
|
|
$newParams = [];
|
|
foreach ($params as $value) {
|
|
$baseUrlArray[] = $value;
|
|
}
|
|
for ($i = 0; $i < $count; $i++) {
|
|
$newParams[] = array_pop($baseUrlArray);
|
|
$url = '/' . implode('/', $baseUrlArray);
|
|
if (isset($this->routes[$url])) {
|
|
return ['url' => $url, 'params' => $newParams];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function tryFunctionCall(?array $aRoute): bool
|
|
{
|
|
if ($aRoute === null || !is_callable(array($aRoute['cl'], $aRoute['fnc']))) {
|
|
return false;
|
|
}
|
|
$route = new $aRoute['cl']();
|
|
try {
|
|
$fnc = $aRoute['fnc'];
|
|
$params = $aRoute['params'] ?? [];
|
|
$route->$fnc(...$params);
|
|
return true;
|
|
} catch (Exception $ex) {
|
|
return false;
|
|
}
|
|
}
|
|
} |