Files
xamxam/app/templates/admin/recapitulatif.php
Pontoporeia 3016c199bd Fix edit form: is_published reset, contact decoupling, note label, author name case
- Fix #1: Add is_published to getThesisRawFields() SELECT so the publish
  checkbox stays checked when editing an already-published TFE.
- Fix #2: Rename 'Note contextuelle' → 'Note contextuelle relative à
  soutenance' in all templates and StudentEmail.
- Fix #3: Update findOrCreateAuthor to also UPDATE the author name when
  a record is found by name (fixes inability to capitalise names).
- Fix #4/#5: Decouple contact_interne (private author email) from
  contact_visible (public contact on TFE page). Add migration 037 to
  add contact_visible TEXT column to theses table and rebuild
  v_theses_full view. Update all controllers, templates, and DB methods
  to treat them independently.
- Fix #6: Investigated libre→interne restriction — no code barrier
  found; likely resolved by is_published fix.
2026-06-10 00:17:00 +02:00

280 lines
15 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<main id="main-content" class="admin-main--recap">
<?php if ($studentMode): ?>
<!-- ═══════════════════ STUDENT MODE: Thank you page ═══════════════════ -->
<div class="thanks-student-page">
<?php if ($error): ?>
<div class="thanks-error">
<h1>⚠ Oups…</h1>
<p><?= htmlspecialchars($error) ?></p>
<a href="/admin/add.php?mode=student" class="btn btn--primary btn--lg btn-new-form">← Retour au formulaire</a>
</div>
<?php elseif ($thesis): ?>
<div class="thanks-success">
<h1>Merci 🎉</h1>
<p class="thanks-message">
Ton TFE <strong><?= htmlspecialchars($thesis['title']) ?></strong> a bien été soumis.
</p>
<a href="/admin/add.php?mode=student" class="btn btn--primary btn--lg btn-new-form">+ Ajouter un nouveau TFE</a>
</div>
<?php else: ?>
<div class="thanks-error">
<h1>Erreur</h1>
<p>Aucune donnée à afficher.</p>
<a href="/admin/add.php?mode=student" class="btn btn--primary btn--lg btn-new-form">← Retour au formulaire</a>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<!-- ═══════════════════ ADMIN MODE: Recap page ═══════════════════ -->
<h1><a href="/admin/" class="admin-back-btn" title="Retour à la liste"><svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="currentColor" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48-88a8,8,0,0,1-8,8H107.31l18.35,18.34a8,8,0,0,1-11.32,11.32l-32-32a8,8,0,0,1,0-11.32l32-32a8,8,0,0,1,11.32,11.32L107.31,120H168A8,8,0,0,1,176,128Z"></path></svg></a> Récapitulatif TFE</h1>
<?php if ($error): ?>
<p class="toast" role="alert" data-type="error">⚠ <?= htmlspecialchars($error) ?></p>
<p><a href="/admin/add.php" class="btn btn--secondary">Retour au formulaire</a></p>
<?php elseif ($thesis): ?>
<!-- ═══════════ Identité ═══════════ -->
<fieldset>
<legend>Identité</legend>
<dl class="recap-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>
<?php if (!empty($thesis['contact_visible'])): ?>
<dt>Contact visible</dt><dd><?= htmlspecialchars($thesis['contact_visible']) ?></dd>
<?php endif; ?>
<?php if (!empty($thesis['contact_interne'])): ?>
<dt>Contact interne (privé)</dt><dd><?= htmlspecialchars($thesis['contact_interne']) ?></dd>
<?php endif; ?>
<dt>Année</dt><dd><?= htmlspecialchars((string)$thesis['year']) ?></dd>
<dt>Objet</dt><dd><?= htmlspecialchars($thesis['objet'] ?? 'tfe') ?></dd>
<?php if ($thesis['is_doctoral']): ?>
<dt>Doctoral</dt><dd>Oui</dd>
<?php endif; ?>
</dl>
</fieldset>
<!-- ═══════════ Cadre académique ═══════════ -->
<fieldset>
<legend>Cadre académique</legend>
<dl class="recap-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>
</dl>
</fieldset>
<!-- ═══════════ Jury ═══════════ -->
<?php
$hasJury = $thesis['jury_president']
|| $thesis['jury_promoteurs']
|| $thesis['jury_promoteurs_ulb']
|| $thesis['jury_lecteurs_internes']
|| $thesis['jury_lecteurs_externes']
|| $thesis['supervisors'];
?>
<?php if ($hasJury): ?>
<fieldset>
<legend>Jury</legend>
<dl class="recap-dl">
<?php if ($thesis['jury_president']): ?>
<dt>Président·e</dt><dd><?= htmlspecialchars($thesis['jury_president']) ?></dd>
<?php endif; ?>
<?php if ($thesis['jury_promoteurs']): ?>
<dt>Promoteur·ice(s)</dt><dd><?= htmlspecialchars($thesis['jury_promoteurs']) ?></dd>
<?php endif; ?>
<?php if ($thesis['jury_promoteurs_ulb']): ?>
<dt>Promoteur·ice(s) ULB</dt><dd><?= htmlspecialchars($thesis['jury_promoteurs_ulb']) ?></dd>
<?php endif; ?>
<?php if ($thesis['jury_lecteurs_internes']): ?>
<dt>Lecteur·ice(s) interne</dt><dd><?= htmlspecialchars($thesis['jury_lecteurs_internes']) ?></dd>
<?php endif; ?>
<?php if ($thesis['jury_lecteurs_externes']): ?>
<dt>Lecteur·ice(s) externe</dt><dd><?= htmlspecialchars($thesis['jury_lecteurs_externes']) ?></dd>
<?php endif; ?>
<?php if ($thesis['supervisors'] && !$thesis['jury_promoteurs']): ?>
<dt>Promoteur·ice(s)</dt><dd><?= htmlspecialchars($thesis['supervisors']) ?></dd>
<?php endif; ?>
<?php if ($thesis['jury_points'] !== null): ?>
<dt>Note du jury</dt><dd><?= htmlspecialchars($thesis['jury_points']) ?>/20</dd>
<?php endif; ?>
</dl>
</fieldset>
<?php endif; ?>
<!-- ═══════════ Contenu ═══════════ -->
<fieldset>
<legend>Contenu</legend>
<dl class="recap-dl">
<dt>Synopsis</dt>
<dd class="recap-synopsis"><?= nl2br(htmlspecialchars($thesis['synopsis'] ?? '')) ?></dd>
<?php if ($thesis['context_note']): ?>
<dt>Note contextuelle relative à soutenance</dt>
<dd class="recap-long-text"><?= nl2br(htmlspecialchars($thesis['context_note'])) ?></dd>
<?php endif; ?>
<?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['baiu_link']): ?>
<dt>Lien BAIU</dt><dd><a href="<?= htmlspecialchars($thesis['baiu_link']) ?>" target="_blank" rel="noopener"><?= htmlspecialchars($thesis['baiu_link']) ?></a></dd>
<?php endif; ?>
</dl>
</fieldset>
<!-- ═══════════ Accès et licence ═══════════ -->
<fieldset>
<legend>Accès et licence</legend>
<dl class="recap-dl">
<dt>Degré d'ouverture</dt><dd><?= htmlspecialchars($thesis['access_type'] ?? '') ?></dd>
<?php if ($thesis['license_type']): ?>
<dt>Licence</dt><dd><?= htmlspecialchars($thesis['license_type']) ?></dd>
<?php endif; ?>
<?php if ($thesis['license_custom']): ?>
<dt>Licence personnalisée</dt><dd><?= htmlspecialchars($thesis['license_custom']) ?></dd>
<?php endif; ?>
<dt>CC2r</dt><dd><?= !empty($thesis['cc2r']) ? 'Acceptée' : 'Non' ?></dd>
<dt>Exemplaire BAIU</dt><dd><?= !empty($thesis['exemplaire_baiu']) ? 'Oui' : 'Non' ?></dd>
<dt>Exemplaire ERG</dt><dd><?= !empty($thesis['exemplaire_erg']) ? 'Oui' : 'Non' ?></dd>
</dl>
</fieldset>
<!-- ═══════════ Dates et publication ═══════════ -->
<fieldset>
<legend>Dates et publication</legend>
<dl class="recap-dl">
<?php if ($thesis['submitted_at']): ?>
<dt>Soumis le</dt><dd><?= date('d/m/Y à H:i', strtotime($thesis['submitted_at'])) ?></dd>
<?php endif; ?>
<?php if ($thesis['defense_date']): ?>
<dt>Date de défense</dt><dd><?= date('d/m/Y', strtotime($thesis['defense_date'])) ?></dd>
<?php endif; ?>
<?php if ($thesis['published_at']): ?>
<dt>Publié le</dt><dd><?= date('d/m/Y à H:i', strtotime($thesis['published_at'])) ?></dd>
<?php endif; ?>
<dt>Publié</dt><dd><?= !empty($thesis['is_published']) ? 'Oui' : 'Non' ?></dd>
<?php if ($thesis['jury_note_added']): ?>
<dt>Note du jury ajoutée</dt><dd><?= date('d/m/Y', strtotime($thesis['jury_note_added'])) ?></dd>
<?php endif; ?>
</dl>
</fieldset>
<!-- ═══════════ Remarques ═══════════ -->
<?php if (!empty($thesis['remarks'])): ?>
<fieldset>
<legend>Remarques</legend>
<p class="recap-long-text"><?= nl2br(htmlspecialchars($thesis['remarks'])) ?></p>
</fieldset>
<?php endif; ?>
<!-- ═══════════ Fichiers ═══════════ -->
<?php if (!empty($files)): ?>
<fieldset>
<legend>Fichiers (<?= count($files) ?>)</legend>
<table class="recap-files-table">
<thead>
<tr>
<th></th>
<th>Nom</th>
<th>Type</th>
<th>Taille</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<?php foreach ($files as $f): ?>
<?php
$mime = $f['mime_type'] ?? '';
$filePath = $f['file_path'] ?? '';
$fileName = htmlspecialchars($f['file_name'] ?? basename($filePath));
$fileType = $f['file_type'] ?? 'other';
$displayLabel = $f['display_label'] ?? '';
$fileExt = strtolower(pathinfo($filePath, PATHINFO_EXTENSION));
$isImage = str_starts_with($mime, 'image/') || in_array($fileExt, ['jpg','jpeg','png','gif','webp']);
$isPeerTube = str_starts_with($filePath, 'peertube_ids:');
$isExternal = str_starts_with($filePath, 'http://') || str_starts_with($filePath, 'https://');
if ($isPeerTube) {
require_once APP_ROOT . '/src/PeerTubeService.php';
$_ptDb = new Database();
$_ptUuid = substr($filePath, strlen('peertube_ids:'));
$_ptS = PeerTubeService::getSettings($_ptDb);
$mediaUrl = ((int)$_ptS['privacy'] <= 2)
? PeerTubeService::getWatchUrl($_ptDb, $_ptUuid)
: '#';
} elseif ($isExternal) {
$mediaUrl = htmlspecialchars($filePath);
} else {
$mediaUrl = '/media?path=' . urlencode($filePath);
}
$typeIcon = match (true) {
$isPeerTube && $fileType === 'video' => '🎬',
$isPeerTube && $fileType === 'audio' => '🔊',
$fileType === 'cover' => '🖼️',
$fileType === 'note_intention' => '📝',
$fileType === 'main' || ($mime === 'application/pdf') || $fileExt === 'pdf' => '📄',
$fileType === 'video' || str_starts_with($mime, 'video/') || in_array($fileExt, ['mp4','webm','mov','ogv']) => '🎬',
$fileType === 'audio' || str_starts_with($mime, 'audio/') || in_array($fileExt, ['mp3','ogg','wav','flac','aac','m4a']) => '🔊',
$isImage => '🖼️',
$fileType === 'caption' || $fileExt === 'vtt' => '💬',
$fileType === 'annex' => '📎',
$fileType === 'website' => '🌐',
default => '📎',
};
?>
<tr>
<td class="recap-files-icon">
<span class="recap-files-icon-emoji"><?= $typeIcon ?></span>
</td>
<td class="recap-files-name">
<a href="<?= $mediaUrl ?>" target="_blank" rel="noopener"><?= $fileName ?></a>
<?php if ($isPeerTube): ?>
<span class="recap-files-peertube-id">ID: <?= htmlspecialchars($_ptUuid) ?></span>
<?php endif; ?>
<?php if ($displayLabel): ?>
<span class="recap-files-label"><?= htmlspecialchars($displayLabel) ?></span>
<?php endif; ?>
</td>
<td class="recap-files-type"><?= htmlspecialchars($fileType) ?></td>
<td class="recap-files-size"><?= !empty($f['file_size']) && $f['file_size'] > 0 ? formatFileSize($f['file_size']) : '' ?></td>
<td class="recap-files-date"><?= !empty($f['uploaded_at']) ? date('d/m/Y H:i', strtotime($f['uploaded_at'])) : '' ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</fieldset>
<?php endif; ?>
<div class="admin-action-bar">
<a href="/admin/edit.php?id=<?= $thesisId ?>" class="btn btn--primary">Modifier</a>
<a href="/admin/" class="btn btn--secondary">Retour à la liste</a>
</div>
<?php else: ?>
<p class="admin-muted">Aucune donnée à afficher.</p>
<p><a href="/admin/add.php" class="btn btn--secondary">Retour au formulaire</a></p>
<?php endif; ?>
<?php endif; ?>
</main>