mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
SQLite performance (Database::__construct): - PRAGMA journal_mode = WAL: eliminates full-DB read locks on write, safe for concurrent PHP-FPM workers - PRAGMA synchronous = NORMAL: durable on commit without full fsync per write - PRAGMA cache_size = -8000: ~8 MB page cache per connection Accessibility foundation (WCAG 2.1 AA): - common.css: add .sr-only utility, .skip-link (hidden until focused), global :focus-visible (2px purple outline, 2px offset), prefers-reduced-motion guard; remove bare outline:none from .site-search__input - admin.css: same :focus-visible, skip-link, and motion guard scoped to admin purple; remove outline:none from .admin-input/.admin-select/ .admin-textarea and .admin-filters select (both had :focus border rules already, so focus is still visually communicated) - search.css: remove outline:none from .search-filter-select (already has :focus border-color rule) - All 5 public pages (index, search, tfe, apropos, licence): add <a href="#main-content" class="skip-link"> as first child of <body>; add id="main-content" to <main> - templates/admin/head.php: same skip link; aria-label="Navigation admin" on <nav>; id="main-content" on all 10 admin <main> elements All 4 test suites pass (unit, integration, security, rate-limit).
162 lines
6.2 KiB
PHP
162 lines
6.2 KiB
PHP
<?php
|
||
// Bootstrap application
|
||
require_once __DIR__ . "/../../config/bootstrap.php";
|
||
require_once __DIR__ . '/../../src/AdminAuth.php';
|
||
|
||
// PHP-level auth guard (defence-in-depth behind nginx Basic Auth)
|
||
AdminAuth::requireLogin();
|
||
|
||
// Configure error reporting
|
||
ini_set('display_errors', 0);
|
||
ini_set('log_errors', 1);
|
||
ini_set('error_log', 'error.log');
|
||
|
||
require_once __DIR__ . '/../../src/Database.php';
|
||
|
||
// Security: Validate thesis ID parameter
|
||
$thesisId = null;
|
||
$thesis = null;
|
||
$files = [];
|
||
$error = null;
|
||
|
||
if (isset($_GET['id'])) {
|
||
$thesisId = filter_var($_GET['id'], FILTER_VALIDATE_INT);
|
||
|
||
if ($thesisId !== false && $thesisId > 0) {
|
||
try {
|
||
$db = new Database();
|
||
$pdo = $db->getPDO();
|
||
|
||
// Get thesis data
|
||
$thesis = $db->getThesis($thesisId);
|
||
|
||
if (!$thesis) {
|
||
$error = "TFE non trouvé.";
|
||
} else {
|
||
// Get associated files
|
||
$stmt = $pdo->prepare("
|
||
SELECT file_type, file_name, file_size, mime_type, uploaded_at
|
||
FROM thesis_files
|
||
WHERE thesis_id = ?
|
||
ORDER BY file_type, uploaded_at
|
||
");
|
||
$stmt->execute([$thesisId]);
|
||
$files = $stmt->fetchAll();
|
||
}
|
||
} catch (Exception $e) {
|
||
error_log("Error loading thesis: " . $e->getMessage());
|
||
$error = "Erreur lors de la lecture des données.";
|
||
}
|
||
} else {
|
||
error_log("Invalid thesis ID: " . $_GET['id']);
|
||
$error = "Identifiant invalide.";
|
||
}
|
||
} else {
|
||
$error = "Aucun identifiant spécifié.";
|
||
}
|
||
|
||
// Helper function to format file size
|
||
function formatFileSize($bytes) {
|
||
if ($bytes >= 1073741824) {
|
||
return number_format($bytes / 1073741824, 2) . ' GB';
|
||
} elseif ($bytes >= 1048576) {
|
||
return number_format($bytes / 1048576, 2) . ' MB';
|
||
} elseif ($bytes >= 1024) {
|
||
return number_format($bytes / 1024, 2) . ' KB';
|
||
} else {
|
||
return $bytes . ' bytes';
|
||
}
|
||
}
|
||
|
||
// Set page title for header
|
||
$pageTitle = "Récapitulatif TFE";
|
||
?>
|
||
<?php require_once APP_ROOT . '/templates/admin/head.php'; ?>
|
||
|
||
<main class="admin-main" id="main-content">
|
||
<h1 class="admin-page-title">Récapitulatif TFE</h1>
|
||
|
||
<?php if ($error): ?>
|
||
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
|
||
<p><a href="/admin/add.php" class="admin-btn-secondary">Retour au formulaire</a></p>
|
||
|
||
<?php elseif ($thesis): ?>
|
||
<div class="admin-thesis-info">
|
||
<h2>Informations de base</h2>
|
||
<dl>
|
||
<dt>Identifiant</dt><dd><?= htmlspecialchars($thesis['identifier']) ?></dd>
|
||
<dt>Titre</dt><dd><?= htmlspecialchars($thesis['title']) ?></dd>
|
||
<?php if ($thesis['subtitle']): ?>
|
||
<dt>Sous-titre</dt><dd><?= htmlspecialchars($thesis['subtitle']) ?></dd>
|
||
<?php endif; ?>
|
||
<dt>Auteur·ice(s)</dt><dd><?= htmlspecialchars($thesis['authors']) ?></dd>
|
||
<dt>Année</dt><dd><?= htmlspecialchars($thesis['year']) ?></dd>
|
||
</dl>
|
||
</div>
|
||
|
||
<div class="admin-thesis-info">
|
||
<h2>Détails académiques</h2>
|
||
<dl>
|
||
<dt>Orientation</dt><dd><?= htmlspecialchars($thesis['orientation'] ?? '–') ?></dd>
|
||
<dt>Atelier pratique</dt><dd><?= htmlspecialchars($thesis['ap_program'] ?? '–') ?></dd>
|
||
<dt>Finalité</dt><dd><?= htmlspecialchars($thesis['finality_type'] ?? '–') ?></dd>
|
||
<?php if ($thesis['supervisors']): ?>
|
||
<dt>Promoteur·ice(s)</dt><dd><?= htmlspecialchars($thesis['supervisors']) ?></dd>
|
||
<?php endif; ?>
|
||
</dl>
|
||
</div>
|
||
|
||
<div class="admin-thesis-info">
|
||
<h2>Contenu</h2>
|
||
<dl>
|
||
<?php if ($thesis['languages']): ?>
|
||
<dt>Langue(s)</dt><dd><?= htmlspecialchars($thesis['languages']) ?></dd>
|
||
<?php endif; ?>
|
||
<?php if ($thesis['formats']): ?>
|
||
<dt>Format(s)</dt><dd><?= htmlspecialchars($thesis['formats']) ?></dd>
|
||
<?php endif; ?>
|
||
<?php if ($thesis['keywords']): ?>
|
||
<dt>Mots-clés</dt><dd><?= htmlspecialchars($thesis['keywords']) ?></dd>
|
||
<?php endif; ?>
|
||
<?php if ($thesis['file_size_info']): ?>
|
||
<dt>Durée / Taille</dt><dd><?= htmlspecialchars($thesis['file_size_info']) ?></dd>
|
||
<?php endif; ?>
|
||
<?php if ($thesis['baiu_link']): ?>
|
||
<dt>Lien</dt><dd><a href="<?= htmlspecialchars($thesis['baiu_link']) ?>" target="_blank" rel="noopener"><?= htmlspecialchars($thesis['baiu_link']) ?></a></dd>
|
||
<?php endif; ?>
|
||
</dl>
|
||
</div>
|
||
|
||
<?php if (!empty($files)): ?>
|
||
<div class="admin-thesis-info">
|
||
<h2>Fichiers</h2>
|
||
<table class="admin-table">
|
||
<thead><tr><th>Type</th><th>Fichier</th><th>Taille</th><th>Date</th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($files as $f): ?>
|
||
<tr>
|
||
<td><?= htmlspecialchars($f['file_type']) ?></td>
|
||
<td><?= htmlspecialchars($f['file_name']) ?></td>
|
||
<td><?= formatFileSize($f['file_size']) ?></td>
|
||
<td><?= date('d/m/Y H:i', strtotime($f['uploaded_at'])) ?></td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
|
||
<div style="margin-top:1.5rem;display:flex;gap:.75rem;flex-wrap:wrap;">
|
||
<a href="/admin/edit.php?id=<?= $thesisId ?>" class="admin-btn">Modifier</a>
|
||
<a href="/admin/add.php" class="admin-btn-secondary">Ajouter un autre TFE</a>
|
||
<a href="/admin/" class="admin-btn-secondary">Retour à la liste</a>
|
||
</div>
|
||
|
||
<?php else: ?>
|
||
<p style="color:var(--admin-text-muted);">Aucune donnée à afficher.</p>
|
||
<p><a href="/admin/add.php" class="admin-btn-secondary">Retour au formulaire</a></p>
|
||
<?php endif; ?>
|
||
</main>
|
||
|
||
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|