KT-personal-website/app/Router.php
2024-12-03 16:57:27 +01:00

99 lines
3.6 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 {
$extraParams = [];
$requestMethod = $_SERVER['REQUEST_METHOD'];
$this->requestUrl = $requestUrl = strtok($_SERVER['REQUEST_URI'], '?');
if (!empty(parse_url($_SERVER['REQUEST_URI'], PHP_URL_QUERY))) {
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;
}
}