feat: extract MediaController, wire into Dispatcher, delete media.php

This commit is contained in:
Pontoporeia
2026-04-17 11:44:08 +02:00
parent b03be51b92
commit 75f808bee4
157 changed files with 1713 additions and 452 deletions

View File

@@ -0,0 +1,140 @@
<?php
/**
* HomeController
*
* Handles all data-fetching and view-variable assembly for the public home page
* (public/index.php).
*
* Responsibilities:
* - Parse and validate GET parameters (`page`, `year`)
* - Determine the display mode (default random-latest / year-filtered / paginated all)
* - Run the appropriate Database queries
* - Batch-load cover images for theses without a banner_path
* - Assemble OG / meta tag array
* - Return a flat array of view variables ready for template extraction
*
* The class has NO output side-effects; all template rendering stays in
* public/index.php so the view layer remains easy to inspect and modify.
*/
class HomeController
{
private const ITEMS_PER_PAGE = 24;
private Database $db;
public function __construct(Database $db)
{
$this->db = $db;
}
// ── Factory ───────────────────────────────────────────────────────────────
/**
* Convenience factory: loads the Database singleton and returns a ready
* controller instance.
*/
public static function create(): self
{
require_once APP_ROOT . '/src/Database.php';
return new self(Database::getInstance());
}
// ── Main entry point ─────────────────────────────────────────────────────
/**
* Process the current request and return all variables needed by the view.
*
* @return array<string, mixed>
*/
public function handle(): array
{
$page = isset($_GET['page']) ? max(1, (int) $_GET['page']) : 1;
$year = isset($_GET['year']) ? (int) $_GET['year'] : null;
// Normalise zero (e.g. ?year=0) to null so it is treated as "no filter"
if ($year === 0) {
$year = null;
}
// Default home view: random theses from latest year (no year filter, no explicit page)
$isDefaultView = ($year === null && $page === 1);
$itemsToLoad = [];
$totalItems = 0;
$availableYears = [];
$latestYear = null;
$coverMap = [];
try {
$offset = ($page - 1) * self::ITEMS_PER_PAGE;
$availableYears = $this->db->getAvailableYears();
if ($year !== null) {
$itemsToLoad = $this->db->searchTheses(['year' => $year], self::ITEMS_PER_PAGE, $offset);
$totalItems = $this->db->countSearchResults(['year' => $year]);
} elseif ($isDefaultView) {
$latestYear = $this->db->getLatestPublishedYear();
$itemsToLoad = $this->db->getLatestYearTheses(self::ITEMS_PER_PAGE);
$totalItems = count($itemsToLoad); // no multi-page on default view
} else {
$itemsToLoad = $this->db->getPublishedTheses(self::ITEMS_PER_PAGE, $offset);
$totalItems = $this->db->countPublishedTheses();
}
// Batch-load cover images for theses that have no banner_path
if (!empty($itemsToLoad)) {
$needCover = array_column(
array_filter($itemsToLoad, static fn($t) => empty($t['banner_path'])),
'id'
);
if (!empty($needCover)) {
$coverMap = $this->db->getCoverPathsForTheses($needCover);
}
}
} catch (Exception $e) {
error_log('HomeController: ' . $e->getMessage());
// Return safe empty state; view will show "Aucun mémoire trouvé"
$isDefaultView = false;
}
$totalPages = $isDefaultView ? 1 : (int) ceil($totalItems / self::ITEMS_PER_PAGE);
// Avoid division by zero on empty DB
if ($totalPages < 1) {
$totalPages = 0;
}
$baseParams = array_filter(['year' => $year]);
return [
// Pagination / filter state
'page' => $page,
'year' => $year,
'isDefaultView' => $isDefaultView,
'totalItems' => $totalItems,
'totalPages' => $totalPages,
'baseParams' => $baseParams,
// Thesis data
'itemsToLoad' => $itemsToLoad,
'latestYear' => $latestYear,
'availableYears' => $availableYears,
'coverMap' => $coverMap,
// Page meta
'pageTitle' => 'Posterg Mémoires de l\'ERG',
'metaDescription' => 'Posterg répertorie et valorise les mémoires de fin d\'études (TFE) de l\'erg École de Recherches Graphiques de Bruxelles.',
'ogTags' => [
'type' => 'website',
'title' => 'Posterg Mémoires de l\'ERG',
'description' => 'Posterg répertorie et valorise les mémoires de fin d\'études (TFE) de l\'erg École de Recherches Graphiques de Bruxelles.',
'url' => 'https://posterg.erg.be/',
'site_name' => 'Posterg ERG',
],
// Layout
'currentNav' => '',
'extraCss' => ['/assets/css/main.css'],
'bodyClass' => 'home-body',
];
}
}