mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
Move all data-fetching and request logic out of the 285-line search page into src/SearchController.php: - SearchController::create() — static factory; builds RateLimit + Database dependencies, sends HTTP 429 (and exits) if rate limit is exceeded, runs probabilistic cleanup, returns ready instance - SearchController::handle() — sanitises GET params (query/year/orientation/ ap_program/keyword), runs all DB queries (searchTheses, countSearchResults, getAvailableYears, getAllOrientations, getAllAPPrograms, getUsedTags, getPublishedAuthors), builds alphabetical author→id map, assembles OG/meta tags, returns a flat array of view variables - Rate-limit 429 HTML response moved into private sendRateLimitResponse() public/search.php is now a 6-line dispatcher: require SearchController; extract(SearchController::create()->handle()); followed by the unchanged view template (162 lines total, was 285). The view template is byte-for-byte equivalent: same HTML, same variable names, same pagination partial include.
163 lines
7.1 KiB
PHP
163 lines
7.1 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../config/bootstrap.php';
|
|
require_once APP_ROOT . '/src/SearchController.php';
|
|
|
|
// Build controller (performs rate-limit check; exits with HTTP 429 if exceeded)
|
|
$ctrl = SearchController::create();
|
|
|
|
// Collect all view variables
|
|
extract($ctrl->handle());
|
|
?>
|
|
<?php include APP_ROOT . '/templates/head.php'; ?>
|
|
<?php include APP_ROOT . '/templates/header.php'; ?>
|
|
|
|
<?php if ($validationError): ?>
|
|
<div class="search-error">⚠ <?= htmlspecialchars($validationError) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($hasSearch): ?>
|
|
<!-- ── RESULTS VIEW ─────────────────────────────────── -->
|
|
|
|
<!-- Filter controls -->
|
|
<form class="search-controls" method="GET" action="search.php">
|
|
<input type="hidden" name="query" value="<?= htmlspecialchars($_GET['query'] ?? '') ?>">
|
|
|
|
<label class="search-filter-label" for="filter-year">Année
|
|
<select class="search-filter-select" name="year" id="filter-year">
|
|
<option value="">Toutes</option>
|
|
<?php foreach ($years as $y): ?>
|
|
<option value="<?= (int)$y ?>" <?= (isset($_GET['year']) && $_GET['year'] == $y) ? 'selected' : '' ?>>
|
|
<?= (int)$y ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="search-filter-label" for="filter-orientation">Orientation
|
|
<select class="search-filter-select" name="orientation" id="filter-orientation">
|
|
<option value="">Toutes</option>
|
|
<?php foreach ($orientations as $o): ?>
|
|
<option value="<?= htmlspecialchars($o['name']) ?>"
|
|
<?= (isset($_GET['orientation']) && $_GET['orientation'] == $o['name']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($o['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
|
|
<label class="search-filter-label" for="filter-ap">AP
|
|
<select class="search-filter-select" name="ap_program" id="filter-ap">
|
|
<option value="">Tous</option>
|
|
<?php foreach ($apPrograms as $ap): ?>
|
|
<option value="<?= htmlspecialchars($ap['name']) ?>"
|
|
<?= (isset($_GET['ap_program']) && $_GET['ap_program'] == $ap['name']) ? 'selected' : '' ?>>
|
|
<?= htmlspecialchars($ap['name']) ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</label>
|
|
|
|
<button type="submit" class="search-apply-btn">Filtrer</button>
|
|
<a href="search.php" class="search-reset-link">Réinitialiser</a>
|
|
</form>
|
|
|
|
<main class="search-main" id="main-content">
|
|
<output class="search-results-header" role="status"><?= $totalItems ?> résultat<?= $totalItems > 1 ? 's' : '' ?></output>
|
|
|
|
<?php if (!empty($results)): ?>
|
|
<ul class="results-grid">
|
|
<?php foreach ($results as $item): ?>
|
|
<li><a href="tfe.php?id=<?= (int)$item['id'] ?>" class="result-card">
|
|
<span class="result-card__authors"><?= htmlspecialchars($item['authors'] ?? '') ?></span>
|
|
<span class="result-card__title"><?= htmlspecialchars($item['title']) ?></span>
|
|
<small class="result-card__meta"><?= htmlspecialchars($item['year']) ?><?php if (!empty($item['orientation'])): ?> · <?= htmlspecialchars($item['orientation']) ?><?php endif; ?></small>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
|
|
<?php include APP_ROOT . '/templates/partials/pagination.php'; ?>
|
|
|
|
<?php else: ?>
|
|
<p class="search-empty">Aucun résultat pour cette recherche.</p>
|
|
<?php endif; ?>
|
|
</main>
|
|
|
|
<?php else: ?>
|
|
<!-- ── RÉPERTOIRE INDEX VIEW ─────────────────────────── -->
|
|
<main class="search-main" id="main-content">
|
|
<h1 class="sr-only">Répertoire</h1>
|
|
<div class="repertoire-index">
|
|
|
|
<!-- ANNÉES -->
|
|
<section class="repertoire-col">
|
|
<h2>Années</h2>
|
|
<ul>
|
|
<?php foreach ($years as $y): ?>
|
|
<li><a href="search.php?year=<?= (int)$y ?>"
|
|
<?= (isset($_GET['year']) && $_GET['year'] == $y) ? 'aria-current="page"' : '' ?>>
|
|
<?= (int)$y ?>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</section>
|
|
|
|
<!-- CATÉGORIES -->
|
|
<section class="repertoire-col">
|
|
<h2>Catégories</h2>
|
|
|
|
<?php if (!empty($orientations)): ?>
|
|
<span class="cat-index-label">Orientation</span>
|
|
<ul>
|
|
<?php foreach ($orientations as $o): ?>
|
|
<li><a href="search.php?orientation=<?= urlencode($o['name']) ?>"
|
|
<?= (isset($_GET['orientation']) && $_GET['orientation'] == $o['name']) ? 'aria-current="page"' : '' ?>>
|
|
<?= htmlspecialchars($o['name']) ?>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($apPrograms)): ?>
|
|
<span class="cat-index-label">Ateliers Pluridisciplinaires</span>
|
|
<ul>
|
|
<?php foreach ($apPrograms as $ap): ?>
|
|
<li><a href="search.php?ap_program=<?= urlencode($ap['name']) ?>"
|
|
<?= (isset($_GET['ap_program']) && $_GET['ap_program'] == $ap['name']) ? 'aria-current="page"' : '' ?>>
|
|
<?= htmlspecialchars($ap['name']) ?>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
<?php endif; ?>
|
|
</section>
|
|
|
|
<!-- ÉTUDIANTES -->
|
|
<section class="repertoire-col">
|
|
<h2>Étudiantes</h2>
|
|
<ul>
|
|
<?php foreach ($authorMap as $name => $id): ?>
|
|
<li><a href="tfe.php?id=<?= (int)$id ?>">
|
|
<?= htmlspecialchars($name) ?>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</section>
|
|
|
|
<!-- MOTS-CLÉS -->
|
|
<section class="repertoire-col">
|
|
<h2>Mots-clés</h2>
|
|
<ul>
|
|
<?php foreach ($keywords as $kw): ?>
|
|
<li><a href="search.php?keyword=<?= urlencode($kw['name']) ?>"
|
|
<?= (isset($_GET['keyword']) && $_GET['keyword'] == $kw['name']) ? 'aria-current="page"' : '' ?>>
|
|
<?= htmlspecialchars($kw['name']) ?>
|
|
</a></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</section>
|
|
|
|
</div>
|
|
</main>
|
|
<?php endif; ?>
|
|
|
|
<?php include APP_ROOT . '/templates/footer.php'; ?>
|