Ajout du dossier api avec la géolocalisation automatique des casernes de pompiers
This commit is contained in:
208
api/src/Core/Router.php
Normal file
208
api/src/Core/Router.php
Normal file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
class Router {
|
||||
// Préfixe fixe de l'API (toujours 'api')
|
||||
private const API_PREFIX = 'api';
|
||||
private array $routes = [];
|
||||
private array $publicEndpoints = [
|
||||
'login',
|
||||
'register',
|
||||
'lostpassword',
|
||||
'log',
|
||||
'villes', // Ajout de la route villes comme endpoint public pour l'autocomplétion du code postal
|
||||
];
|
||||
|
||||
public function __construct() {
|
||||
// Pas besoin de récupérer AppConfig puisque nous utilisons une constante pour le préfixe API
|
||||
$this->configureRoutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure toutes les routes de l'application
|
||||
*/
|
||||
private function configureRoutes(): void {
|
||||
// Routes publiques
|
||||
$this->post('login', ['LoginController', 'login']);
|
||||
$this->post('register', ['LoginController', 'register']);
|
||||
$this->post('lostpassword', ['LoginController', 'lostPassword']);
|
||||
|
||||
// Route pour les logs
|
||||
$this->post('log', ['LogController', 'index']);
|
||||
|
||||
// Routes privées utilisateurs
|
||||
$this->get('users', ['UserController', 'getUsers']);
|
||||
$this->get('users/:id', ['UserController', 'getUserById']);
|
||||
$this->post('users', ['UserController', 'createUser']);
|
||||
$this->put('users/:id', ['UserController', 'updateUser']);
|
||||
$this->delete('users/:id', ['UserController', 'deleteUser']);
|
||||
$this->post('logout', ['LoginController', 'logout']);
|
||||
|
||||
// Routes entités
|
||||
$this->get('entites', ['EntiteController', 'getEntites']);
|
||||
$this->get('entites/:id', ['EntiteController', 'getEntiteById']);
|
||||
$this->get('entites/postal/:code', ['EntiteController', 'getEntiteByPostalCode']);
|
||||
|
||||
// Routes villes
|
||||
$this->get('villes', ['VilleController', 'searchVillesByPostalCode']);
|
||||
}
|
||||
|
||||
public function handle(): void {
|
||||
$method = $_SERVER['REQUEST_METHOD'];
|
||||
$uri = $this->normalizeUri($_SERVER['REQUEST_URI']);
|
||||
|
||||
error_log("Initial URI: $uri");
|
||||
|
||||
// Handle CORS preflight
|
||||
if ($method === 'OPTIONS') {
|
||||
header('HTTP/1.1 200 OK');
|
||||
exit();
|
||||
}
|
||||
|
||||
// Prendre le préfixe API à partir de la constante
|
||||
$apiPrefix = self::API_PREFIX;
|
||||
|
||||
// Vérifier si l'URI commence bien par le préfixe API
|
||||
$prefixMatch = strpos($uri, $apiPrefix) === 0;
|
||||
|
||||
if (!$prefixMatch) {
|
||||
Response::json([
|
||||
'error' => 'Invalid API prefix',
|
||||
'path' => $uri,
|
||||
'expected_prefix' => $apiPrefix
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
// Extraire l'endpoint en retirant le préfixe API
|
||||
$endpoint = substr($uri, strlen($apiPrefix) + 1); // +1 pour le slash
|
||||
$endpoint = trim($endpoint, '/');
|
||||
|
||||
// Check if endpoint is public
|
||||
if ($this->isPublicEndpoint($endpoint)) {
|
||||
error_log("Public endpoint found: $endpoint");
|
||||
$route = $this->findRoute($method, $endpoint);
|
||||
if ($route) {
|
||||
$this->executeRoute($route);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
error_log("Private endpoint: $endpoint");
|
||||
// Private route - check auth first
|
||||
Session::requireAuth();
|
||||
|
||||
$route = $this->findRoute($method, $endpoint);
|
||||
if ($route) {
|
||||
$this->executeRoute($route);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// No route found
|
||||
Response::json([
|
||||
'error' => 'Route not found',
|
||||
'endpoint' => $endpoint,
|
||||
'uri' => $uri
|
||||
], 404);
|
||||
}
|
||||
|
||||
private function normalizeUri(string $uri): string {
|
||||
return trim(preg_replace('#/+#', '/', parse_url($uri, PHP_URL_PATH)), '/');
|
||||
}
|
||||
|
||||
private function isPublicEndpoint(string $endpoint): bool {
|
||||
return in_array($endpoint, $this->publicEndpoints);
|
||||
}
|
||||
|
||||
private function executeRoute(array $route): void {
|
||||
[$controllerName, $method] = $route['handler'];
|
||||
|
||||
// Essayer de trouver le contrôleur en tenant compte des namespaces possibles
|
||||
$classNames = [
|
||||
$controllerName, // Sans namespace
|
||||
"\\App\\Controllers\\$controllerName", // Avec namespace complet
|
||||
"\\$controllerName" // Avec namespace racine
|
||||
];
|
||||
|
||||
$controllerClass = null;
|
||||
foreach ($classNames as $className) {
|
||||
if (class_exists($className)) {
|
||||
$controllerClass = $className;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($controllerClass === null) {
|
||||
// Classe non trouvée, gérer l'erreur
|
||||
Response::json([
|
||||
'error' => 'Controller not found',
|
||||
'controller' => $controllerName,
|
||||
'status' => 'error',
|
||||
'message' => 'Controller not found',
|
||||
'tried_namespaces' => implode(', ', $classNames)
|
||||
], 404);
|
||||
return;
|
||||
}
|
||||
|
||||
$controller = new $controllerClass();
|
||||
|
||||
if (!empty($route['params'])) {
|
||||
$controller->$method(...$route['params']);
|
||||
} else {
|
||||
$controller->$method();
|
||||
}
|
||||
}
|
||||
|
||||
public function get(string $path, array $handler): void {
|
||||
$this->addRoute('GET', $path, $handler);
|
||||
}
|
||||
|
||||
public function post(string $path, array $handler): void {
|
||||
$this->addRoute('POST', $path, $handler);
|
||||
}
|
||||
|
||||
public function put(string $path, array $handler): void {
|
||||
$this->addRoute('PUT', $path, $handler);
|
||||
}
|
||||
|
||||
public function delete(string $path, array $handler): void {
|
||||
$this->addRoute('DELETE', $path, $handler);
|
||||
}
|
||||
|
||||
private function addRoute(string $method, string $path, array $handler): void {
|
||||
// Normalize the path
|
||||
$path = trim($path, '/');
|
||||
$this->routes[$method][$path] = $handler;
|
||||
}
|
||||
|
||||
private function findRoute(string $method, string $uri): ?array {
|
||||
if (!isset($this->routes[$method])) {
|
||||
error_log("Méthode $method non trouvée dans les routes");
|
||||
return null;
|
||||
}
|
||||
|
||||
$uri = trim($uri, '/');
|
||||
error_log("Recherche de route pour: méthode=$method, uri=$uri");
|
||||
error_log("Routes disponibles pour $method: " . implode(', ', array_keys($this->routes[$method])));
|
||||
|
||||
foreach ($this->routes[$method] as $route => $handler) {
|
||||
$pattern = preg_replace('/{[^}]+}/', '([^/]+)', $route);
|
||||
$pattern = "@^" . $pattern . "$@D";
|
||||
error_log("Test pattern: $pattern contre uri: $uri");
|
||||
|
||||
if (preg_match($pattern, $uri, $matches)) {
|
||||
error_log("Route trouvée! Pattern: $pattern, Handler: {$handler[0]}::{$handler[1]}");
|
||||
array_shift($matches);
|
||||
return [
|
||||
'handler' => $handler,
|
||||
'params' => $matches
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
error_log("Aucune route trouvée pour $method $uri");
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user