136 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			3.3 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 = null) {
 | |
|     $this->user = $user;
 | |
|     $this->routes = [];
 | |
|     $this->statusCodeRoutes = [];
 | |
| 
 | |
|     if ($user) {
 | |
|       $this->addRoute(new ApiRoute());
 | |
|       $this->logger = new Logger("Router", $user->getSQL());
 | |
|     } else {
 | |
|       $this->logger = new Logger("Router");
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   public function run(string $url): string {
 | |
| 
 | |
|     // TODO: do we want a global try cache and return status page 500 on any error?
 | |
| 
 | |
|     $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) {
 | |
|       // do not generate cache for static api route
 | |
|       if ($route instanceof ApiRoute) {
 | |
|         continue;
 | |
|       }
 | |
| 
 | |
|       $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);
 | |
|   }
 | |
| } |