web-base/core/Objects/Router/Router.class.php
2022-06-01 09:47:31 +02:00

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);
}
}