mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
src/TfeController.php (new, 195 lines): - Dedicated controller for the public TFE detail page - create(): Database singleton injection, ready-to-use factory - handle(): validates id param (redirect to index.php on missing/invalid/404), loads thesis via getThesisById(), fetches access type via getThesisAccessTypeId() - buildMetaDescription(): strip_tags + 160-char mb_substr truncation - resolveOgImage(): banner_path → first image file → empty string resolution - buildOgTags(): full og:type/title/description/url/image/image_alt/site_name + article:author / article:published_time assembly - collectCaptionPaths(): ordered list of VTT paths for N-th-video pairing - returns flat array of all view variables including ogTags, captionFiles, pageTitle, metaDescription, isInterdit, bodyClass, extraCss, currentNav public/tfe.php (271 → 206 lines): - Reduced to 9-line dispatcher: require TfeController, create(), handle(), extract() - $db reference removed from view layer entirely - Inline OG tag block (~20 lines) removed - Inline meta-description block (~5 lines) removed - Inline caption-collection loop (~10 lines) removed - $captionFiles replaces $_captionFiles in the video pairing section todo/02-php-components.md: - TfeController extraction marked done - 'Move OG tag construction into controller logic' marked done - Remaining item narrowed to public/index.php home-page controller
207 lines
9.1 KiB
PHP
207 lines
9.1 KiB
PHP
<?php
|
||
require_once __DIR__ . '/../config/bootstrap.php';
|
||
require_once APP_ROOT . '/src/TfeController.php';
|
||
|
||
// Build controller (loads thesis, enforces visibility, builds OG tags; redirects on 404)
|
||
$ctrl = TfeController::create();
|
||
|
||
// Collect all view variables
|
||
extract($ctrl->handle());
|
||
?>
|
||
<?php include APP_ROOT . '/templates/head.php'; ?>
|
||
<?php include APP_ROOT . '/templates/header.php'; ?>
|
||
|
||
<main class="tfe-main" id="main-content">
|
||
<article class="tfe-layout">
|
||
|
||
<!-- LEFT: info — article header -->
|
||
<header class="tfe-left">
|
||
<a href="index.php" class="tfe-back-link">← Retour</a>
|
||
|
||
<!-- Title is the primary heading; author is metadata -->
|
||
<h1 class="tfe-title">
|
||
<?= htmlspecialchars($data['title']) ?>
|
||
<?php if (!empty($data['subtitle'])): ?>
|
||
– <?= htmlspecialchars($data['subtitle']) ?>
|
||
<?php endif; ?>
|
||
</h1>
|
||
|
||
<p class="tfe-author"><?= htmlspecialchars($data['authors'] ?? 'Auteur inconnu') ?></p>
|
||
|
||
<dl>
|
||
<?php if (!empty($data['orientation'])): ?>
|
||
<div>
|
||
<dt>Orientation :</dt>
|
||
<dd><?= htmlspecialchars($data['orientation']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['ap_program'])): ?>
|
||
<div>
|
||
<dt>Atelier pluridisciplinaire :</dt>
|
||
<dd><?= htmlspecialchars($data['ap_program']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['year'])): ?>
|
||
<div>
|
||
<dt>Date :</dt>
|
||
<dd><?= htmlspecialchars($data['year']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['languages'])): ?>
|
||
<div>
|
||
<dt>Langue :</dt>
|
||
<dd><?= htmlspecialchars($data['languages']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['formats'])): ?>
|
||
<div>
|
||
<dt>Format :</dt>
|
||
<dd><?= htmlspecialchars($data['formats']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['file_size_info'])): ?>
|
||
<div>
|
||
<dt>Durée :</dt>
|
||
<dd><?= htmlspecialchars($data['file_size_info']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['keywords'])): ?>
|
||
<div>
|
||
<dt>Mots-clés :</dt>
|
||
<dd><?= htmlspecialchars($data['keywords']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['jury_president'])): ?>
|
||
<div>
|
||
<dt>Président·e du jury :</dt>
|
||
<dd><?= htmlspecialchars($data['jury_president']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['jury_promoteurs'])): ?>
|
||
<div>
|
||
<dt>Promoteur·ice :</dt>
|
||
<dd><?= htmlspecialchars($data['jury_promoteurs']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['jury_lecteurs'])): ?>
|
||
<div>
|
||
<dt>Lecteur·ices :</dt>
|
||
<dd><?= htmlspecialchars($data['jury_lecteurs']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['access_type'])): ?>
|
||
<div>
|
||
<dt>Accès :</dt>
|
||
<dd><?= htmlspecialchars($data['access_type']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['license_type'])): ?>
|
||
<div>
|
||
<dt>Licence :</dt>
|
||
<dd><?= htmlspecialchars($data['license_type']) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['context_note'])): ?>
|
||
<div class="tfe-meta-note">
|
||
<dt>Note :</dt>
|
||
<dd class="tfe-note-value"><?= nl2br(htmlspecialchars($data['context_note'])) ?></dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<?php if (!empty($data['baiu_link'])): ?>
|
||
<div>
|
||
<dt>Contact :</dt>
|
||
<dd>
|
||
<a href="<?= htmlspecialchars($data['baiu_link']) ?>" target="_blank" rel="noopener">
|
||
<?= htmlspecialchars($data['baiu_link']) ?>
|
||
<span class="sr-only">(ouvre dans un nouvel onglet)</span>
|
||
</a>
|
||
</dd>
|
||
</div>
|
||
<?php endif; ?>
|
||
</dl>
|
||
|
||
<?php if (!empty($data['synopsis'])): ?>
|
||
<p class="tfe-synopsis-text">
|
||
<?= nl2br(htmlspecialchars($data['synopsis'])) ?>
|
||
</p>
|
||
<?php endif; ?>
|
||
</header>
|
||
|
||
<!-- RIGHT: media — supplementary aside -->
|
||
<aside class="tfe-right">
|
||
<?php
|
||
// $isInterdit and $captionFiles are resolved by TfeController::handle()
|
||
$_videoIndex = 0;
|
||
?>
|
||
<?php if ($isInterdit): ?>
|
||
<p class="tfe-restricted">
|
||
Ce TFE n'est pas disponible en ligne.
|
||
</p>
|
||
<?php elseif (!empty($data['files'])): ?>
|
||
<?php foreach ($data['files'] as $file): ?>
|
||
<?php
|
||
$ext = strtolower(pathinfo($file['file_path'], PATHINFO_EXTENSION));
|
||
// VTT caption files are consumed inline by <video>; skip standalone rendering.
|
||
if ($ext === 'vtt') continue;
|
||
?>
|
||
<figure>
|
||
<?php if ($ext === 'pdf'): ?>
|
||
<embed src="/media.php?path=<?= urlencode($file['file_path']) ?>"
|
||
type="application/pdf" width="100%" height="700px">
|
||
<p class="tfe-pdf-fallback">
|
||
<a href="/media.php?path=<?= urlencode($file['file_path']) ?>&download=1">
|
||
Télécharger le PDF
|
||
</a>
|
||
</p>
|
||
<?php elseif (in_array($ext, ['jpg','jpeg','png','gif','bmp','webp'])): ?>
|
||
<img src="/media.php?path=<?= urlencode($file['file_path']) ?>"
|
||
alt="<?= htmlspecialchars(
|
||
!empty($file['description'])
|
||
? $file['description']
|
||
: ($data['title'] . ' — ' . ($data['authors'] ?? ''))
|
||
) ?>">
|
||
<?php elseif ($ext === 'mp4'): ?>
|
||
<?php
|
||
// Pair this video with the N-th VTT file (if one was uploaded).
|
||
$_vttPath = $captionFiles[$_videoIndex] ?? null;
|
||
$_videoIndex++;
|
||
?>
|
||
<video width="100%" controls>
|
||
<source src="/media.php?path=<?= urlencode($file['file_path']) ?>" type="video/mp4">
|
||
<?php if ($_vttPath): ?>
|
||
<track kind="captions"
|
||
src="/media.php?path=<?= urlencode($_vttPath) ?>"
|
||
srclang="fr"
|
||
label="Sous-titres"
|
||
default>
|
||
<?php endif; ?>
|
||
</video>
|
||
<?php endif; ?>
|
||
<?php if (!empty($file['description'])): ?>
|
||
<figcaption><?= htmlspecialchars($file['description']) ?></figcaption>
|
||
<?php endif; ?>
|
||
</figure>
|
||
<?php endforeach; ?>
|
||
<?php else: ?>
|
||
<p class="tfe-no-files">Aucun fichier disponible pour ce TFE.</p>
|
||
<?php endif; ?>
|
||
</aside>
|
||
|
||
</article>
|
||
</main>
|
||
|
||
<?php include APP_ROOT . '/templates/footer.php'; ?>
|