Passed
Push — main ( 1fab42...a42753 )
by Nelson
01:31
created

Router::dispatch()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 37
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 17
nc 5
nop 1
dl 0
loc 37
rs 9.0777
c 0
b 0
f 0
1
<?php
2
3
namespace Pin\Libs;
4
5
use App\Handlers\Handler;
6
7
/**
8
 * Router
9
 * Gestiona el enrutamiento de la aplicación
10
 */
11
class Router
12
{
13
    /**
14
     * Array de rutas registradas
15
     * Formato: ['GET|POST|PUT|DELETE /path' => 'Handler\Class']
16
     */
17
    private $routes = [];
18
19
    /**
20
     * Registra una ruta
21
     * @param string $method Método HTTP (GET, POST, PUT, DELETE)
22
     * @param string $path Ruta (ej: /page, /page/show)
23
     * @param string $handler Clase handler (ej: PageHandler)
24
     */
25
    public function register($method, $path, $handler)
26
    {
27
        $key = "$method $path";
28
        $this->routes[$key] = $handler;
29
    }
30
31
    /**
32
     * Registra múltiples rutas
33
     * @param array $routes Array de rutas
34
     */
35
    public function registerRoutes(array $routes)
36
    {
37
        foreach ($routes as $key => $handler) {
38
            list($method, $path) = explode(' ', $key, 2);
39
            $this->register($method, $path, $handler);
40
        }
41
    }
42
43
    /**
44
     * Procesa la URL actual y ejecuta el handler correspondiente
45
     * @param string $url URL a procesar (ej: /page/show/contactenos)
46
     */
47
    public function dispatch($url)
48
    {
49
        // Normalizar URL
50
        $url = parse_url($url, PHP_URL_PATH);
51
        $url = rtrim($url, '/') ?: '/';
52
53
        $method = $_SERVER['REQUEST_METHOD'];
54
55
        // Intentar encontrar una ruta exacta
56
        $key = "$method $url";
57
        if (isset($this->routes[$key])) {
58
            return $this->executeHandler($this->routes[$key], []);
59
        }
60
61
        // Intentar coincidencias con parámetros
62
        foreach ($this->routes as $route_key => $handler) {
63
            list($route_method, $route_path) = explode(' ', $route_key, 2);
64
            
65
            if ($route_method !== $method) {
66
                continue;
67
            }
68
69
            // Convertir ruta a regex para capturar parámetros
70
            // /page/{slug} -> /page/(.+)
71
            $pattern = preg_replace('/{[^}]+}/', '([^/]+)', $route_path);
72
            $pattern = '#^' . $pattern . '$#';
73
74
            if (preg_match($pattern, $url, $matches)) {
75
                // Remover el primer elemento que es la URL completa
76
                array_shift($matches);
77
                return $this->executeHandler($handler, $matches);
78
            }
79
        }
80
81
        // Si llegamos aquí, la ruta no existe
82
        http_response_code(404);
83
        throw new \Exception("Ruta no encontrada: $method $url", 404);
84
    }
85
86
    /**
87
     * Ejecuta un handler
88
     * @param string $handler_class Nombre de la clase handler
89
     * @param array $params Parámetros extraídos de la URL
90
     */
91
    private function executeHandler($handler_class, array $params = [])
92
    {
93
        $class_name = 'App\\Handlers\\' . $handler_class;
94
95
        if (!class_exists($class_name)) {
96
            throw new \Exception("Handler no existe: $class_name", 500);
97
        }
98
99
        $handler = new $class_name();
100
101
        if (!$handler instanceof Handler) {
102
            throw new \Exception("$class_name no extiende Handler", 500);
103
        }
104
105
        return $handler->handle($params);
106
    }
107
}
108