commit 39d2e8cbcf63c4e7e8108aac6b4379de7709f1c4 Author: User Date: Mon May 29 02:15:58 2023 +0300 Init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31dc5a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea/ +/vendor +composer.lock \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..9fec503 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +### Rmphp/Router + +PSR-7 router for **Rmphp** + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a20ad44 --- /dev/null +++ b/composer.json @@ -0,0 +1,20 @@ +{ + "name": "rmphp/router", + "license": "proprietary", + "authors": [ + { + "name": "Yuri Zuev", + "email": "y_zuev@mail.ru" + } + ], + "require": { + "php": "^8.1", + "rmphp/foundation": "1.0.x-dev" + }, + "autoload": { + "psr-4": { + "Rmphp\\Router\\": "src/" + } + } + +} diff --git a/src/Router.php b/src/Router.php new file mode 100644 index 0000000..7cc3b9a --- /dev/null +++ b/src/Router.php @@ -0,0 +1,94 @@ +startPoint = $startPoint; + } + + /** + * @param array $rules + */ + public function withRules(array $rules): void + { + $this->rules = []; + foreach ($rules as $rulesKey => $rulesNode) { + // проверка формата + if (!isset($rulesNode['key'], $rulesNode['routes'])) continue; + // удаляем спецсимволы + $realPattern = preg_replace("'[()\'\"]'", "", $rulesNode['key']); + // преобразуем псевдомаску в реальную маску + $realPattern = preg_replace("'<([A-z0-9]+?):(.+?)>'", "(?P<$1>$2)", $realPattern); + // заменяем алиасы на регвыражения + $realPattern = str_replace(array("[num]", "[pth]", "[any]"), array("[0-9]+", "[^/]+", ".*"), $realPattern); + // при наличии слеша в конце правила url должно строго ему соответствовать + $end = (preg_match("'/$'", $realPattern)) ? "$" : ""; + // меняем запись на паттерн + $this->rules[$rulesKey] = $rulesNode; + $this->rules[$rulesKey]['key'] = "'^".$realPattern.$end."'"; + } + } + + public function match(RequestInterface $request): ?array { + + foreach ($this->rules as $rule) { + // если для правила определен метод и он не совпал смотри далее + if(!empty($rule['withMethod']) && is_array($rule['withMethod']) && false === (array_search($request->getMethod(), $rule['withMethod']))) continue; + if(!empty($rule['withoutMethod']) && is_array($rule['withoutMethod']) && false !== (array_search($request->getMethod(), $rule['withoutMethod']))) continue; + + // вычисляем рабочий url + $currentUrlString = preg_replace("'^".preg_quote($this->startPoint)."'", "/", $request->getUri()->getPath()); + + // в цикле проверяем совпадения текущей строки с правилами + if (preg_match($rule['key'], $currentUrlString, $matches)) { + $routes = []; + foreach ($rule['routes'] as $route) { + // если в результате есть именные ключи от ?P, пытаемся произвести замену в части inc + foreach ($matches as $matchesKey => $matchesVal) { + if (!is_numeric($matchesKey)) { + $route['action'] = str_replace("<".ucfirst($matchesKey).">", ucfirst($matchesVal), $route['action']); + $route['action'] = str_replace("<".$matchesKey.">", $matchesVal, $route['action']); + + $route['method'] = str_replace("<".ucfirst($matchesKey).">", ucfirst($matchesVal), $route['method']); + $route['method'] = str_replace("<".$matchesKey.">", $matchesVal, $route['method']); + if (!empty($route['params'])) { + $route['params'] = str_replace("<".$matchesKey.">", $matchesVal, $route['params']); + } + } + } + // чистка маркеров + $route['action'] = preg_replace("'<.+>'", "", $route['action']); + $route['method'] = preg_replace("'<.+>'", "", $route['method']); + if (!empty($route['params'])) { + $route['params'] = preg_replace("'<.+>'", "", $route['params']); + } + + $className = (!empty($route['action'])) ? $route['action'] : ""; + $methodName = (!empty($route['method'])) ? $route['method'] : ""; + $paramSet = (!empty($route['params'])) ? explode(",",str_replace(" ", "", $route['params'])) : []; + + $params = []; + foreach ($paramSet as $key => $param){ + if(empty($param)) continue; + $params[$key] = (preg_match("'^[0-9]+$'", $param)) ? (int) $param : $param; + } + $routes[] = new MatchObject($className, $methodName, $params); + } + return $routes; + } + } + return null; + } +} \ No newline at end of file