microphp/Core/Route.php

296 lines
8.7 KiB
PHP
Raw Normal View History

2023-04-07 01:02:39 +03:00
<?php
include_once "Request.php";
include_once "Helpers.php";
2023-04-30 16:07:14 +03:00
function magicRoute($path,$regexs = [])
2023-04-07 01:02:39 +03:00
{
$regex = [];
$names = [];
$first = true;
$magic = false;
foreach (tstring::from($path)->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]);
2023-04-30 16:07:14 +03:00
$regexng = "[^\/^?]+?";
if(isset($regexs[$symbol->raw()]))
{
$regexng = $regexs[$symbol->raw()];
}
2023-04-07 01:02:39 +03:00
if($symbol->endsWith("?"))
{
$symbol = $symbol->slice(0,-1);
2023-04-30 16:07:14 +03:00
$pattern = "(".$regexng.")?";
2023-04-07 01:02:39 +03:00
}else{
2023-04-30 16:07:14 +03:00
$pattern = "(".$regexng.")";
2023-04-07 01:02:39 +03:00
}
$regex[] = "\/". $matched[1] . $pattern . $matched[3];
$names[] = $symbol;
}
}
return [
"/^" . implode('', $regex) . "$/",
$names,
$magic
];
};
function validateMagicRoute($mroute, $path)
{
2023-04-30 16:07:14 +03:00
list($regex, $names) = $mroute;
2023-04-07 01:02:39 +03:00
$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 = [];
2023-04-11 22:59:27 +03:00
public static $errors = [];
2023-04-11 00:30:15 +03:00
public static $publics = [];
2023-04-07 01:02:39 +03:00
public static $current = null;
2023-04-30 16:07:14 +03:00
public static function post($path, $callback, $regexs = [])
2023-04-07 01:02:39 +03:00
{
2023-04-30 16:07:14 +03:00
$magic = magicRoute($path, $regexs);
2023-04-07 01:02:39 +03:00
$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;
}
2023-04-11 22:59:27 +03:00
public static function error($method, $code, $callback)
{
if(!isset(Route::$errors[$code]))
{
Route::$errors[$code] = [];
}
Route::$errors[$code][$method] = $callback;
}
2023-04-30 16:07:14 +03:00
public static function get($path, $callback, $regexs = [])
2023-04-07 01:02:39 +03:00
{
2023-04-30 16:07:14 +03:00
$magic = magicRoute($path, $regexs);
2023-04-07 01:02:39 +03:00
$textPath = false;
$type = "text";
if($magic[2] == true)
{
$type = "magic";
$textPath = $magic;
}else{
$textPath = $path;
}
$route = Route::from([
"type" => $type,
2023-04-30 16:07:14 +03:00
"path" => $textPath,
2023-04-07 01:02:39 +03:00
"callback" => $callback,
"method" => "get"
]);
Route::$routes[] = $route;
return $route;
}
2023-04-11 00:30:15 +03:00
public static function public($route, $storagepath)
{
Route::$publics[] = Route::from([
"type" => "public",
"path" => preg_quote($route),
"src" => $storagepath,
"method" => "get"
]);
}
2023-04-30 16:07:14 +03:00
public static function any($path, $callback, $regexs = [])
2023-04-07 01:02:39 +03:00
{
2023-04-30 16:07:14 +03:00
$magic = magicRoute($path,$regexs);
2023-04-07 01:02:39 +03:00
$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;
}
2023-04-11 22:59:27 +03:00
public static function ThrowErrorCode($code)
2023-04-07 01:02:39 +03:00
{
2023-04-11 22:59:27 +03:00
$method = Request::$method;
if(isset(Route::$errors[$code][$method]))
2023-04-07 01:02:39 +03:00
{
2023-04-11 22:59:27 +03:00
$callback = Route::$errors[$code][$method];
Route::$errors[$code][$method]();
return;
2023-04-07 01:02:39 +03:00
};
2023-04-11 22:59:27 +03:00
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);
}
2023-04-07 01:02:39 +03:00
return Route::$current;
}
2023-04-08 21:34:10 +03:00
public static function Execute()
{
$route = Route::CheckCurrent();
2023-04-11 22:59:27 +03:00
if($route !== false)
2023-04-08 21:34:10 +03:00
{
2023-04-11 22:59:27 +03:00
$route->call();
2023-04-08 21:34:10 +03:00
};
}
2023-04-07 01:02:39 +03:00
public static function from(...$args)
{
return new Route(...$args);
}
public string $type;
2023-04-30 16:07:14 +03:00
public $path;
2023-04-11 00:30:15 +03:00
public string $src;
2023-04-07 01:02:39 +03:00
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;
}
2023-04-08 21:34:10 +03:00
public function call(...$args)
{
2023-04-11 00:30:15 +03:00
switch ($this->type) {
case 'magic':
case 'text':
$callback = $this->callback;
2023-04-30 16:07:14 +03:00
$callback(new Request(),...$args);
2023-04-11 00:30:15 +03:00
break;
case 'public':
$callback = $this->callback;
Response::File($callback);
break;
}
2023-04-08 21:34:10 +03:00
}
2023-04-07 01:02:39 +03:00
public function Run()
{
$requestUrl = Request::$url;
$method = Request::$method;
if($this->method != $method)
{
return false;
}
$url = parse_url($requestUrl, PHP_URL_PATH);
2023-04-11 00:30:15 +03:00
switch($this->type)
2023-04-07 01:02:39 +03:00
{
2023-04-11 00:30:15 +03:00
case "text":{
if($url == $this->path)
{
return true;
}else{
return false;
}
break;
}
case "magic":{
2023-04-30 16:07:14 +03:00
$t = validateMagicRoute($this->path,$url);
2023-04-11 00:30:15 +03:00
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);
2023-04-11 22:59:27 +03:00
if(file_exists($rpath) && is_file($rpath))
2023-04-11 00:30:15 +03:00
{
$this->callback = $rpath;
return true;
}else{
return false;
}
}else{
return false;
}
break;
2023-04-07 01:02:39 +03:00
}
}
}
}