128 lines
3.1 KiB
PHP
128 lines
3.1 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Objects\Router;
|
||
|
|
||
|
use Driver\Logger\Logger;
|
||
|
use Objects\User;
|
||
|
|
||
|
class Router {
|
||
|
|
||
|
private User $user;
|
||
|
private Logger $logger;
|
||
|
protected array $routes;
|
||
|
protected array $statusCodeRoutes;
|
||
|
|
||
|
public function __construct(User $user) {
|
||
|
$this->user = $user;
|
||
|
$this->logger = new Logger("Router", $user->getSQL());
|
||
|
$this->routes = [];
|
||
|
$this->statusCodeRoutes = [];
|
||
|
|
||
|
$this->addRoute(new ApiRoute());
|
||
|
}
|
||
|
|
||
|
public function run(string $url): string {
|
||
|
|
||
|
// TODO: do we want a global try cache and return status page 500 on any error?
|
||
|
// or do we want to have a global status page function here?
|
||
|
|
||
|
$url = strtok($url, "?");
|
||
|
foreach ($this->routes as $route) {
|
||
|
$pathParams = $route->match($url);
|
||
|
if ($pathParams !== false) {
|
||
|
return $route->call($this, $pathParams);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $this->returnStatusCode(404);
|
||
|
}
|
||
|
|
||
|
public function returnStatusCode(int $code, array $params = []): string {
|
||
|
http_response_code($code);
|
||
|
$params["status_code"] = $code;
|
||
|
$params["status_description"] = HTTP_STATUS_DESCRIPTIONS[$code] ?? "Unknown Error";
|
||
|
$route = $this->statusCodeRoutes[strval($code)] ?? null;
|
||
|
if ($route) {
|
||
|
return $route->call($this, $params);
|
||
|
} else {
|
||
|
$req = new \Api\Template\Render($this->user);
|
||
|
$res = $req->execute(["file" => "error_document.twig", "parameters" => $params]);
|
||
|
if ($res) {
|
||
|
return $req->getResult()["html"];
|
||
|
} else {
|
||
|
var_dump($req->getLastError());
|
||
|
$description = htmlspecialchars($params["status_description"]);
|
||
|
return "<b>$code - $description</b>";
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function addRoute(AbstractRoute $route) {
|
||
|
if (preg_match("/^\d+$/", $route->getPattern())) {
|
||
|
$this->statusCodeRoutes[$route->getPattern()] = $route;
|
||
|
} else {
|
||
|
$this->routes[] = $route;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public function writeCache(string $file): bool {
|
||
|
|
||
|
$routes = "";
|
||
|
foreach ($this->routes as $route) {
|
||
|
$constructor = $route->generateCache();
|
||
|
$routes .= "\n \$this->addRoute($constructor);";
|
||
|
}
|
||
|
|
||
|
$date = (new \DateTime())->format("Y/m/d H:i:s");
|
||
|
$code = "<?php
|
||
|
|
||
|
/**
|
||
|
* DO NOT EDIT!
|
||
|
* This file is automatically generated by the RoutesAPI on $date.
|
||
|
*/
|
||
|
|
||
|
namespace Cache;
|
||
|
use Objects\User;
|
||
|
use Objects\Router\Router;
|
||
|
|
||
|
class RouterCache extends Router {
|
||
|
|
||
|
public function __construct(User \$user) {
|
||
|
parent::__construct(\$user);$routes
|
||
|
}
|
||
|
}
|
||
|
";
|
||
|
|
||
|
if (@file_put_contents($file, $code) === false) {
|
||
|
$this->logger->severe("Could not write Router cache file: $file");
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public function getUser(): User {
|
||
|
return $this->user;
|
||
|
}
|
||
|
|
||
|
public function getLogger(): Logger {
|
||
|
return $this->logger;
|
||
|
}
|
||
|
|
||
|
public static function cleanURL(string $url, bool $cleanGET = true): string {
|
||
|
// strip GET parameters
|
||
|
if ($cleanGET) {
|
||
|
if (($index = strpos($url, "?")) !== false) {
|
||
|
$url = substr($url, 0, $index);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// strip document reference part
|
||
|
if (($index = strpos($url, "#")) !== false) {
|
||
|
$url = substr($url, 0, $index);
|
||
|
}
|
||
|
|
||
|
// strip leading slash
|
||
|
return preg_replace("/^\/+/", "", $url);
|
||
|
}
|
||
|
}
|