Files
Woles-Framework/app/Core/Router.php

146 lines
3.6 KiB
PHP
Raw Normal View History

<?php
namespace App\Core;
/**
* NovaCore Router
* Simple FastRoute-like router
*/
class Router
{
private array $routes = [];
private array $patterns = [
'{id}' => '([0-9]+)',
'{slug}' => '([a-zA-Z0-9\-]+)',
'{any}' => '(.+)'
];
/**
* Register a GET route
*/
public function get(string $path, string $handler): void
{
$this->addRoute('GET', $path, $handler);
}
/**
* Register a POST route
*/
public function post(string $path, string $handler): void
{
$this->addRoute('POST', $path, $handler);
}
/**
* Register a PUT route
*/
public function put(string $path, string $handler): void
{
$this->addRoute('PUT', $path, $handler);
}
/**
* Register a DELETE route
*/
public function delete(string $path, string $handler): void
{
$this->addRoute('DELETE', $path, $handler);
}
/**
* Add route to collection
*/
private function addRoute(string $method, string $path, string $handler): void
{
$this->routes[$method][] = [
'path' => $path,
'handler' => $handler,
'pattern' => $this->compilePattern($path),
'params' => $this->extractParams($path)
];
}
/**
* Compile route pattern for regex matching
*/
private function compilePattern(string $path): string
{
// First replace placeholders with regex patterns
$pattern = $path;
foreach ($this->patterns as $placeholder => $regex) {
$pattern = str_replace($placeholder, $regex, $pattern);
}
// Escape only the non-regex parts
$pattern = preg_quote($pattern, '/');
// Restore the regex patterns that were escaped
foreach ($this->patterns as $placeholder => $regex) {
$escapedRegex = preg_quote($regex, '/');
$pattern = str_replace($escapedRegex, $regex, $pattern);
}
return '/^' . $pattern . '$/';
}
/**
* Extract parameter names from route
*/
private function extractParams(string $path): array
{
preg_match_all('/\{([^}]+)\}/', $path, $matches);
return $matches[1] ?? [];
}
/**
* Match request against routes
*/
public function match(string $method, string $uri): ?array
{
if (!isset($this->routes[$method])) {
return null;
}
foreach ($this->routes[$method] as $route) {
if (preg_match($route['pattern'], $uri, $matches)) {
// Remove full match, keep only captured groups
array_shift($matches);
// Map parameters
$params = [];
foreach ($route['params'] as $index => $paramName) {
$params[$paramName] = $matches[$index] ?? null;
}
return [
'handler' => $route['handler'],
'params' => $params,
'module' => $this->extractModule($route['handler'])
];
}
}
return null;
}
/**
* Extract module name from handler
*/
private function extractModule(string $handler): string
{
// Handler formats supported:
// - "Home\\Controller@index" → module "Home"
// - "Controller@index" when module implied by route context
$parts = explode('\\', $handler);
return $parts[0] ?: 'Default';
}
/**
* Get all registered routes
*/
public function getRoutes(): array
{
return $this->routes;
}
}