mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 03:29:19 +02:00
feat: extract MediaController, wire into Dispatcher, delete media.php
This commit is contained in:
151
app/src/Dispatcher.php
Normal file
151
app/src/Dispatcher.php
Normal file
@@ -0,0 +1,151 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-controller Dispatcher
|
||||
*
|
||||
* Routes all public-page requests through a single entry point.
|
||||
* Admin panel (/admin/*) and static assets bypass the dispatcher.
|
||||
*
|
||||
* Routes:
|
||||
* / → HomeController → home view
|
||||
* /search.php → SearchController → search view
|
||||
* /repertoire → SearchController → repertoire view
|
||||
* /tfe/<id> → TfeController → tfe view
|
||||
* /apropos → AboutController → about view
|
||||
* /licence → LicenceController → licence view
|
||||
* /media.php → MediaController (direct output)
|
||||
* /live-reload → LiveReloadController (direct output)
|
||||
* /partage/<slug> → share-link flow
|
||||
* /maintenance.php → static maintenance page
|
||||
*/
|
||||
class Dispatcher {
|
||||
private const ROUTES = [
|
||||
'' => ['controller' => 'HomeController', 'action' => 'handle', 'view' => 'public/home'],
|
||||
'/' => ['controller' => 'HomeController', 'action' => 'handle', 'view' => 'public/home'],
|
||||
'/index.php' => ['controller' => 'HomeController', 'action' => 'handle', 'view' => 'public/home'],
|
||||
'/search.php' => ['controller' => 'SearchController', 'action' => 'handle', 'view' => 'public/search'],
|
||||
'/repertoire' => ['controller' => 'SearchController', 'action' => 'handleRepertoire', 'view' => 'public/repertoire'],
|
||||
'/repertoire.php' => ['controller' => 'SearchController', 'action' => 'handleRepertoire', 'view' => 'public/repertoire'],
|
||||
'/tfe.php' => ['controller' => 'TfeController', 'action' => 'handle', 'view' => 'public/tfe'],
|
||||
'/apropos' => ['controller' => 'AboutController', 'action' => 'handle', 'view' => 'public/about'],
|
||||
'/apropos.php' => ['controller' => 'AboutController', 'action' => 'handle', 'view' => 'public/about'],
|
||||
'/licence' => ['controller' => 'LicenceController', 'action' => 'handle', 'view' => 'public/licence'],
|
||||
'/licence.php' => ['controller' => 'LicenceController', 'action' => 'handle', 'view' => 'public/licence'],
|
||||
];
|
||||
|
||||
private string $path;
|
||||
private array $queryParams;
|
||||
|
||||
public function __construct() {
|
||||
$uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
|
||||
$this->path = $uri;
|
||||
$this->queryParams = $_GET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the URI to a route, instantiate the controller,
|
||||
* execute the action, and render the view.
|
||||
*/
|
||||
public function dispatch(): void {
|
||||
// 1. Direct-response endpoints (render their own output)
|
||||
$direct = $this->matchDirect();
|
||||
if ($direct) {
|
||||
$direct();
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Routed pages (controller + view)
|
||||
$route = $this->matchRoute();
|
||||
if (!$route) {
|
||||
http_response_code(404);
|
||||
echo '<h1>404 — Page non trouvée</h1>';
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. Load controller
|
||||
$ctrlClass = $route['controller'];
|
||||
require_once APP_ROOT . '/src/Controllers/' . $ctrlClass . '.php';
|
||||
|
||||
$controller = $ctrlClass::create();
|
||||
$vars = $controller->{$route['action']}();
|
||||
|
||||
// 4. Render view
|
||||
$this->render($route['view'], $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match endpoints that render their own response (no view layer).
|
||||
*/
|
||||
private function matchDirect(): ?callable {
|
||||
$path = $this->path;
|
||||
|
||||
// /live-reload
|
||||
if ($path === '/live-reload' || $path === '/live-reload.php') {
|
||||
return function() {
|
||||
require_once APP_ROOT . '/src/Controllers/LiveReloadController.php';
|
||||
$controller = new LiveReloadController(APP_ROOT);
|
||||
$result = $controller->handle();
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode($result['body']);
|
||||
};
|
||||
}
|
||||
|
||||
// /media.php
|
||||
if ($path === '/media' || $path === '/media.php') {
|
||||
return function() {
|
||||
require_once APP_ROOT . '/src/Controllers/MediaController.php';
|
||||
$controller = new MediaController();
|
||||
$controller->handle();
|
||||
};
|
||||
}
|
||||
|
||||
// /maintenance.php
|
||||
if ($path === '/maintenance' || $path === '/maintenance.php') {
|
||||
return function() {
|
||||
require APP_ROOT . '/public/maintenance.php';
|
||||
};
|
||||
}
|
||||
|
||||
// /partage/*
|
||||
if (preg_match('#^/partage(/.*)?$#', $path)) {
|
||||
return function() {
|
||||
require APP_ROOT . '/public/partage/index.php';
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the current path against the static route table.
|
||||
* Supports exact match and prefix-based (for /tfe?id=).
|
||||
*/
|
||||
private function matchRoute(): ?array {
|
||||
$path = $this->path;
|
||||
|
||||
// Exact match first
|
||||
if (isset(self::ROUTES[$path])) {
|
||||
return self::ROUTES[$path];
|
||||
}
|
||||
|
||||
// /tfe?id= pattern (TFeController handles the id param internally)
|
||||
if (preg_match('#^/tfe$#', $path) && isset($_GET['id'])) {
|
||||
return self::ROUTES['/tfe.php'];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a view template, passing controller data through extract().
|
||||
*/
|
||||
private function render(string $view, array $vars): void {
|
||||
$viewPath = APP_ROOT . '/templates/' . $view . '.php';
|
||||
if (!file_exists($viewPath)) {
|
||||
http_response_code(500);
|
||||
echo "View not found: {$viewPath}";
|
||||
return;
|
||||
}
|
||||
extract($vars);
|
||||
include $viewPath;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user