split("/") as $value) { $matched = $value->match("/^(.*?)\{(.+?)\}(.*?)$/"); if($first){ $first = false; continue; }; if($matched === false) { $regex[] = "\/" . preg_quote($value); }else{ $magic = true; $symbol = tstring::from($matched[2]); $regexng = "[^\/^?]+?"; if(isset($regexs[$symbol->raw()])) { $regexng = $regexs[$symbol->raw()]; } if($symbol->endsWith("?")) { $symbol = $symbol->slice(0,-1); $pattern = "(".$regexng.")?"; }else{ $pattern = "(".$regexng.")"; } $regex[] = "\/". $matched[1] . $pattern . $matched[3]; $names[] = $symbol; } } return [ "/^" . implode('', $regex) . "$/", $names, $magic ]; }; function validateMagicRoute($mroute, $path) { list($regex, $names) = $mroute; $matches = tstring::from($path)->match($regex); if($matches !== false) { array_shift($matches); $matcher = new stdClass; $index = 0; foreach ($matches as $value) { $matcher->{ $names[$index]->raw() } = $matches[ $index ]; $index++; }; return $matcher; }else{ return false; } }; class Route { public static $routes = []; public static $errors = []; public static $publics = []; public static $current = null; public static function post($path, $callback, $regexs = []) { $magic = magicRoute($path, $regexs); $textPath = false; $type = "text"; if($magic[2] == true) { $type = "magic"; $textPath = $magic; }else{ $textPath = $path; } $route = Route::from([ "type" => $type, "path" => $path, "callback" => $callback, "method" => "post" ]); Route::$routes[] = $route; return $route; } public static function error($method, $code, $callback) { if(!isset(Route::$errors[$code])) { Route::$errors[$code] = []; } Route::$errors[$code][$method] = $callback; } public static function get($path, $callback, $regexs = []) { $magic = magicRoute($path, $regexs); $textPath = false; $type = "text"; if($magic[2] == true) { $type = "magic"; $textPath = $magic; }else{ $textPath = $path; } $route = Route::from([ "type" => $type, "path" => $textPath, "callback" => $callback, "method" => "get" ]); Route::$routes[] = $route; return $route; } public static function public($route, $storagepath) { Route::$publics[] = Route::from([ "type" => "public", "path" => preg_quote($route), "src" => $storagepath, "method" => "get" ]); } public static function any($path, $callback, $regexs = []) { $magic = magicRoute($path,$regexs); $textPath = false; $type = "text"; if($magic[2] == true) { $type = "magic"; $textPath = $magic; }else{ $textPath = $path; } $route = Route::from([ "type" => $type, "path" => $path, "callback" => $callback, "method" => "*" ]); Route::$routes[] = $route; return $route; } public static function ThrowErrorCode($code) { $method = Request::$method; if(isset(Route::$errors[$code][$method])) { $callback = Route::$errors[$code][$method]; Route::$errors[$code][$method](); return; }; Response::Code($code); } public static function CheckCurrent() { try{ if(Route::$current == null) { foreach (Route::$routes as $route) { $route->clear(); if($route->Run()) { Route::$current = $route; return $route; } }; foreach (Route::$publics as $route) { $route->clear(); if($route->Run()) { Route::$current = $route; return $route; } }; Route::ThrowErrorCode(404); return false; }; } catch(Exception $e) { Route::ThrowErrorCode(500); } return Route::$current; } public static function Execute() { $route = Route::CheckCurrent(); if($route !== false) { $route->call(); }; } public static function from(...$args) { return new Route(...$args); } public string $type; public $path; public string $src; public $callback; public string $method; public $match = null; public function __construct($obj) { foreach ($obj as $name => $value) { $this->{$name} = $value; } } public function clear() { $this->match = null; } public function call(...$args) { switch ($this->type) { case 'magic': case 'text': $callback = $this->callback; $callback(new Request(),...$args); break; case 'public': $callback = $this->callback; Response::File($callback); break; } } public function Run() { $requestUrl = Request::$url; $method = Request::$method; if($this->method != $method) { return false; } $url = parse_url($requestUrl, PHP_URL_PATH); switch($this->type) { case "text":{ if($url == $this->path) { return true; }else{ return false; } break; } case "magic":{ $t = validateMagicRoute($this->path,$url); if($t === false) { return false; }else{ $this->match = $t; return true; } break; } case "public":{ $path = tstring::from($this->path); $url = tstring::from($url); if($url->startsWith($path)) { $filename = $url->slice(strlen($path)); // remove first / char $rpath = realpath($this->src . $filename); if(file_exists($rpath) && is_file($rpath)) { $this->callback = $rpath; return true; }else{ return false; } }else{ return false; } break; } } } }