Extract HomeController from public/index.php

Move all data-fetching and view-variable assembly out of public/index.php
into a new src/HomeController.php, following the same pattern as
SearchController, TfeController, SystemController, and ThesisEditController.

HomeController::create() builds the Database singleton dependency.
HomeController::handle() encapsulates:
- GET param parsing (page, year) with safe type coercion
- Display-mode detection: default random-latest view / year-filtered /
  paginated-all theses
- All DB calls: getLatestPublishedYear, getLatestYearTheses, searchTheses,
  countSearchResults, getPublishedTheses, countPublishedTheses,
  getCoverPathsForTheses, getAvailableYears
- Batch cover-image loading for theses without a banner_path
- baseParams assembly for the pagination partial
- OG / meta tag array construction
- Graceful error handling (logs exception, returns safe empty state)
- Returns a flat array of view variables

public/index.php is now a 6-line dispatcher (require + create + handle +
extract) followed by a pure view template. Reduced from 100 to 71 lines.
All error-handling and data logic removed from the view layer entirely.
This commit is contained in:
Pontoporeia
2026-04-06 14:29:17 +02:00
parent 89067a521f
commit b1e70a2bf1
4 changed files with 148 additions and 64 deletions

View File

@@ -1,66 +1,11 @@
<?php
// Load configuration
require_once __DIR__ . '/../config/bootstrap.php';
require_once APP_ROOT . '/src/Database.php';
require_once APP_ROOT . '/src/HomeController.php';
$page = isset($_GET["page"]) ? max(1, intval($_GET["page"])) : 1;
$year = isset($_GET["year"]) ? intval($_GET["year"]) : null;
$itemsPerPage = 24;
// Default home view: random theses from latest year (no year filter, no explicit page)
$isDefaultView = (!$year && $page === 1);
try {
$db = Database::getInstance();
$offset = ($page - 1) * $itemsPerPage;
$availableYears = $db->getAvailableYears();
if ($year) {
$itemsToLoad = $db->searchTheses(['year' => $year], $itemsPerPage, $offset);
$totalItems = $db->countSearchResults(['year' => $year]);
} elseif ($isDefaultView) {
$latestYear = $db->getLatestPublishedYear();
$itemsToLoad = $db->getLatestYearTheses($itemsPerPage);
$totalItems = count($itemsToLoad); // no pagination on default view
} else {
$itemsToLoad = $db->getPublishedTheses($itemsPerPage, $offset);
$totalItems = $db->countPublishedTheses();
}
$totalPages = $isDefaultView ? 1 : (int)ceil($totalItems / $itemsPerPage);
// Batch-load cover images for theses that have no banner_path
$coverMap = [];
if (!empty($itemsToLoad)) {
$needCover = array_column(
array_filter($itemsToLoad, fn($t) => empty($t['banner_path'])),
'id'
);
$coverMap = $db->getCoverPathsForTheses($needCover);
}
} catch (Exception $e) {
error_log("Error loading theses: " . $e->getMessage());
$itemsToLoad = [];
$totalPages = 0;
$availableYears = [];
$totalItems = 0;
$latestYear = null;
$isDefaultView = false;
$coverMap = [];
}
$currentNav = '';
$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' => $pageTitle,
'description' => $metaDescription,
'url' => 'https://posterg.erg.be/',
'site_name' => 'Posterg ERG',
];
$extraCss = ['/assets/css/main.css'];
$bodyClass = 'home-body';
$controller = HomeController::create();
$vars = $controller->handle();
extract($vars);
?>
<?php include APP_ROOT . '/templates/head.php'; ?>
<?php include APP_ROOT . '/templates/header.php'; ?>
@@ -126,10 +71,7 @@ $bodyClass = 'home-body';
<?php endif; ?>
</ul>
<?php
$baseParams = array_filter(['year' => $year]);
include APP_ROOT . '/templates/partials/pagination.php';
?>
<?php include APP_ROOT . '/templates/partials/pagination.php'; ?>
</main>
<?php include APP_ROOT . '/templates/footer.php'; ?>