97 lines
3.5 KiB
PHP
97 lines
3.5 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace App;
|
||
|
|
||
|
use App\Utils\Debug;
|
||
|
use Cocur\Slugify\Slugify;
|
||
|
|
||
|
class Router {
|
||
|
private $routes = array();
|
||
|
private $match;
|
||
|
private $requestUrl;
|
||
|
private $config;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Maps a URL pattern to a target controller/action with a specific HTTP method
|
||
|
*
|
||
|
* @param string $method The HTTP method
|
||
|
* @param string $url The URL pattern to match
|
||
|
* @param string $target The target controller/action that should handle the route
|
||
|
* @return void
|
||
|
*/
|
||
|
public function map(string $method, string $url, string $target): void {
|
||
|
$url = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '(?P<\1>[a-zA-Z0-9_-]+)', $url);
|
||
|
$this->routes[] = array($method, '#^' . $url . '$#', $target);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Matches the current request against defined routes and returns the target and parameters.
|
||
|
*
|
||
|
* @param array $config The configuration array
|
||
|
* @return array|false Returns an array containing the target and parameters
|
||
|
*/
|
||
|
public function match(array $config): array|false {
|
||
|
$requestMethod = $_SERVER['REQUEST_METHOD'];
|
||
|
$this->requestUrl = $requestUrl = strtok($_SERVER['REQUEST_URI'], '?');
|
||
|
|
||
|
parse_str(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY), $extraParams);
|
||
|
|
||
|
foreach ($this->routes as $route) {
|
||
|
list($method, $url, $target) = $route;
|
||
|
|
||
|
if ($requestMethod === $method) {
|
||
|
if (preg_match($url, $requestUrl, $params)) {
|
||
|
$slug = new Slugify();
|
||
|
if ($requestUrl === '/') {
|
||
|
$requestUrl = 'home';
|
||
|
}
|
||
|
$params = array_filter($params, 'is_string', ARRAY_FILTER_USE_KEY);
|
||
|
$params['requestUrl'] = $requestUrl;
|
||
|
$params['cacheName'] = $slug->slugify($requestUrl . '_' . implode('-', $extraParams)) . '.html';
|
||
|
$params['type'] = $this->getType($target);
|
||
|
$params['config'] = $config;
|
||
|
$params['extraParams'] = $extraParams;
|
||
|
$this->match['requestUrl'] = $requestUrl;
|
||
|
$this->match = array('target' => $target, 'params' => $params);
|
||
|
return $this->match;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves the type of the target by extracting and normalizing its name
|
||
|
*
|
||
|
* @param string $target The fully qualified name of the target
|
||
|
* @return string The lowercase name of the target without its namespace
|
||
|
*/
|
||
|
private function getType(string $target): string {
|
||
|
return strtolower(basename(str_replace('\\', '/', $target)));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renders the content by invoking the matched target's index method
|
||
|
*
|
||
|
* @return string The rendered content as a string
|
||
|
*/
|
||
|
public function render(): string {
|
||
|
$target = $this->match['target'];
|
||
|
$params = [$this->match['params']];
|
||
|
$author = $params[0]['config']['author'];
|
||
|
$siteName = $params[0]['config']['siteName'];
|
||
|
$navLinks = $params[0]['config']['navLinks'];
|
||
|
$className = '\\' . $target;
|
||
|
$controller_instance = new $className();
|
||
|
$content = call_user_func_array(array($controller_instance, 'index'), $params);
|
||
|
$title = $controller_instance->title();
|
||
|
ob_start();
|
||
|
require_once __DIR__ . '/../template/bone.php';
|
||
|
|
||
|
$contentFinal = ob_get_contents();
|
||
|
ob_end_clean();
|
||
|
return $contentFinal;
|
||
|
}
|
||
|
}
|