mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
- admin.css: remove .admin-hint and .admin-field-hint class rules; add .admin-body form small with the same font-size/color/margin properties plus display:block so it stacks below sibling inputs; stub comment left where .admin-field-hint was to document the change - add.php: 5× <p class="admin-hint"> → <small> - edit.php: 3× <p class="admin-hint"> → <small> - import.php: <div class="admin-hint"> → <small> (block hint below CSV input) - pages-edit.php: class="admin-hint" removed from already-correct <small> - account.php: <p class="admin-field-hint"> → <small> Hint text is now styled purely via the semantic element selector; no class required on any hint element in admin templates.
360 lines
16 KiB
PHP
360 lines
16 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();
|
||
|
||
// Generate CSRF token
|
||
if (empty($_SESSION['csrf_token'])) {
|
||
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
||
}
|
||
|
||
require_once __DIR__ . '/../../src/Database.php';
|
||
|
||
$thesisId = isset($_GET['id']) ? intval($_GET['id']) : 0;
|
||
|
||
if ($thesisId <= 0) {
|
||
die("ID invalide");
|
||
}
|
||
|
||
// Consume flash messages from the edit action
|
||
$error = $_SESSION['edit_error'] ?? null;
|
||
$success = $_SESSION['edit_success'] ?? null;
|
||
unset($_SESSION['edit_error'], $_SESSION['edit_success']);
|
||
|
||
try {
|
||
$db = new Database();
|
||
|
||
// Load thesis data
|
||
$thesis = $db->getThesis($thesisId);
|
||
if (!$thesis) {
|
||
die("TFE non trouvé");
|
||
}
|
||
|
||
// Load current relationships via dedicated DB methods (no raw PDO)
|
||
$currentLanguages = $db->getThesisLanguageIds($thesisId);
|
||
$currentFormats = $db->getThesisFormatIds($thesisId);
|
||
$jury = $db->getThesisJury($thesisId);
|
||
|
||
// Reference / lookup data
|
||
$orientations = $db->getAllOrientations();
|
||
$apPrograms = $db->getAllAPPrograms();
|
||
$finalityTypes = $db->getAllFinalityTypes();
|
||
$languages = $db->getAllLanguages();
|
||
$formatTypes = $db->getAllFormatTypes();
|
||
$licenseTypes = $db->getAllLicenseTypes();
|
||
$accessTypes = $db->getAccessTypes();
|
||
|
||
// Fetch raw FK IDs (view only exposes name strings)
|
||
$rawRow = $db->getThesisRawFields($thesisId);
|
||
$currentLicenseId = $rawRow['license_id'] ?? null;
|
||
$currentAccessTypeId = $rawRow['access_type_id'] ?? null;
|
||
$currentContextNote = $rawRow['context_note'] ?? '';
|
||
|
||
// Set page title for header
|
||
$pageTitle = "Éditer TFE - " . htmlspecialchars($thesis['title']);
|
||
|
||
} catch (Exception $e) {
|
||
error_log("Error loading edit page: " . $e->getMessage());
|
||
die("Erreur lors du chargement: " . $e->getMessage());
|
||
}
|
||
?>
|
||
<?php $isAdmin = true; $bodyClass = 'admin-body'; require_once APP_ROOT . '/templates/head.php'; ?>
|
||
<?php include APP_ROOT . '/templates/header.php'; ?>
|
||
|
||
<main class="admin-main" id="main-content">
|
||
<h1 class="admin-page-title">Modifier un TFE</h1>
|
||
|
||
<?php if ($error): ?>
|
||
<div class="admin-alert admin-alert--error">⚠ <?= htmlspecialchars($error) ?></div>
|
||
<?php endif; ?>
|
||
<?php if ($success): ?>
|
||
<div class="admin-alert admin-alert--success">✓ <?= htmlspecialchars($success) ?></div>
|
||
<?php endif; ?>
|
||
|
||
<form method="post" action="/admin/actions/edit.php" class="admin-form" enctype="multipart/form-data">
|
||
<input type="hidden" name="csrf_token" value="<?= htmlspecialchars($_SESSION['csrf_token']) ?>">
|
||
<input type="hidden" name="thesis_id" value="<?= $thesisId ?>">
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="auteurice">Auteur·ice(s) :</label>
|
||
<input class="admin-input" type="text" id="auteurice" name="auteurice"
|
||
value="<?= htmlspecialchars($thesis['authors']) ?>" required>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="mail">Contact :</label>
|
||
<input class="admin-input" type="text" id="mail" name="mail" value="">
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="année">Année :</label>
|
||
<input class="admin-input" type="number" id="année" name="année"
|
||
value="<?= $thesis['year'] ?>" required>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="orientation">Orientation :</label>
|
||
<select class="admin-select" id="orientation" name="orientation" required>
|
||
<?php foreach ($orientations as $o): ?>
|
||
<option value="<?= $o['id'] ?>"
|
||
<?= ($thesis['orientation'] == $o['name']) ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($o['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="ap">Atelier pluridisciplinaire :</label>
|
||
<select class="admin-select" id="ap" name="ap" required>
|
||
<?php foreach ($apPrograms as $ap): ?>
|
||
<option value="<?= $ap['id'] ?>"
|
||
<?= ($thesis['ap_program'] == $ap['name']) ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($ap['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="finality">Finalité du master :</label>
|
||
<select class="admin-select" id="finality" name="finality" required>
|
||
<?php foreach ($finalityTypes as $f): ?>
|
||
<option value="<?= $f['id'] ?>"
|
||
<?= ($thesis['finality_type'] == $f['name']) ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($f['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<!-- Composition du jury -->
|
||
<?php
|
||
$juryPresident = null;
|
||
$juryPromoteur = null;
|
||
$juryPromoteurExt = 0;
|
||
$juryLecteurs = [];
|
||
foreach ($jury as $jm) {
|
||
if ($jm['role'] === 'president') {
|
||
$juryPresident = $jm['name'];
|
||
} elseif ($jm['role'] === 'promoteur') {
|
||
$juryPromoteur = $jm['name'];
|
||
$juryPromoteurExt = (int)$jm['is_external'];
|
||
} elseif ($jm['role'] === 'lecteur') {
|
||
$juryLecteurs[] = $jm;
|
||
}
|
||
}
|
||
?>
|
||
<fieldset class="admin-fieldset">
|
||
<legend class="admin-fieldset-legend">Composition du jury</legend>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="jury_president">Président·e :</label>
|
||
<input class="admin-input" type="text" id="jury_president" name="jury_president"
|
||
value="<?= htmlspecialchars($juryPresident ?? '') ?>"
|
||
placeholder="Nom (interne)">
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="jury_promoteur">Promoteur·ice :</label>
|
||
<div class="admin-jury-row">
|
||
<input class="admin-input" type="text" id="jury_promoteur" name="jury_promoteur"
|
||
value="<?= htmlspecialchars($juryPromoteur ?? '') ?>" placeholder="Nom">
|
||
<label class="admin-checkbox-label admin-jury-ext">
|
||
<input type="checkbox" name="jury_promoteur_ext" value="1"
|
||
<?= $juryPromoteurExt ? 'checked' : '' ?>> Externe
|
||
</label>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label">Lecteur·ices :</label>
|
||
<div>
|
||
<div id="jury-lecteurs-list" class="admin-jury-list">
|
||
<?php if (empty($juryLecteurs)): ?>
|
||
<div class="admin-jury-entry">
|
||
<input class="admin-input" type="text" name="jury_lecteurs[]" placeholder="Nom">
|
||
<label class="admin-checkbox-label admin-jury-ext">
|
||
<input type="checkbox" name="jury_lecteurs_ext[0]" value="1"> Externe
|
||
</label>
|
||
<button type="button" class="admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer ce lecteur">✕</button>
|
||
</div>
|
||
<?php else: ?>
|
||
<?php foreach ($juryLecteurs as $li => $lm): ?>
|
||
<div class="admin-jury-entry">
|
||
<input class="admin-input" type="text" name="jury_lecteurs[]"
|
||
value="<?= htmlspecialchars($lm['name']) ?>" placeholder="Nom">
|
||
<label class="admin-checkbox-label admin-jury-ext">
|
||
<input type="checkbox" name="jury_lecteurs_ext[<?= $li ?>]" value="1"
|
||
<?= $lm['is_external'] ? 'checked' : '' ?>> Externe
|
||
</label>
|
||
<button type="button" class="admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer ce lecteur">✕</button>
|
||
</div>
|
||
<?php endforeach; ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<button type="button" class="admin-btn-secondary admin-add-jury-btn"
|
||
onclick="addJuryRow()">+ Ajouter un·e lecteur·ice</button>
|
||
</div>
|
||
</div>
|
||
</fieldset>
|
||
<script>
|
||
var juryIdx = <?= max(count($juryLecteurs), 1) ?>;
|
||
function addJuryRow() {
|
||
var list = document.getElementById('jury-lecteurs-list');
|
||
var div = document.createElement('div');
|
||
div.className = 'admin-jury-entry';
|
||
div.innerHTML = '<input class="admin-input" type="text" name="jury_lecteurs[]" placeholder="Nom">'
|
||
+ '<label class="admin-checkbox-label admin-jury-ext">'
|
||
+ '<input type="checkbox" name="jury_lecteurs_ext[' + juryIdx + ']" value="1"> Externe'
|
||
+ '</label>'
|
||
+ '<button type="button" class="admin-btn-remove" onclick="removeJuryRow(this)" aria-label="Supprimer ce lecteur">✕</button>';
|
||
list.appendChild(div);
|
||
juryIdx++;
|
||
}
|
||
function removeJuryRow(btn) {
|
||
btn.closest('.admin-jury-entry').remove();
|
||
}
|
||
</script>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="access_type_id">Visibilité / Accès :</label>
|
||
<select class="admin-select" id="access_type_id" name="access_type_id">
|
||
<option value="">- Non défini -</option>
|
||
<?php foreach ($accessTypes as $at): ?>
|
||
<option value="<?= (int)$at['id'] ?>"
|
||
<?= ($currentAccessTypeId == $at['id']) ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($at['name']) ?>
|
||
<?php if (!empty($at['description'])): ?>
|
||
- <?= htmlspecialchars(mb_strimwidth($at['description'], 0, 60, '...')) ?>
|
||
<?php endif; ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="context_note">Note contextuelle :</label>
|
||
<div>
|
||
<textarea class="admin-textarea" id="context_note" name="context_note"
|
||
rows="4" maxlength="1500"><?= htmlspecialchars($currentContextNote ?? '') ?></textarea>
|
||
<small>Visible publiquement pour les TFE Interne ou Interdit. Max 1 500 caractères.</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="license_id">Licence :</label>
|
||
<select class="admin-select" id="license_id" name="license_id">
|
||
<option value="">- Inconnue -</option>
|
||
<?php foreach ($licenseTypes as $lt): ?>
|
||
<option value="<?= $lt['id'] ?>"
|
||
<?= ($currentLicenseId == $lt['id']) ? 'selected' : '' ?>>
|
||
<?= htmlspecialchars($lt['name']) ?>
|
||
</option>
|
||
<?php endforeach; ?>
|
||
</select>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="titre">Titre :</label>
|
||
<input class="admin-input" type="text" id="titre" name="titre"
|
||
value="<?= htmlspecialchars($thesis['title']) ?>" required>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="subtitle">Sous-titre :</label>
|
||
<input class="admin-input" type="text" id="subtitle" name="subtitle"
|
||
value="<?= htmlspecialchars($thesis['subtitle'] ?? '') ?>">
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="synopsis">Synopsis :</label>
|
||
<textarea class="admin-textarea" id="synopsis" name="synopsis" rows="7" required><?= htmlspecialchars($thesis['synopsis'] ?? '') ?></textarea>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label">Langue(s) :</label>
|
||
<div class="admin-checkbox-list">
|
||
<?php foreach ($languages as $lang): ?>
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="languages[]" value="<?= $lang['id'] ?>"
|
||
<?= in_array($lang['id'], $currentLanguages) ? 'checked' : '' ?>>
|
||
<?= htmlspecialchars($lang['name']) ?>
|
||
</label>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label">Format(s) :</label>
|
||
<div class="admin-checkbox-list">
|
||
<?php foreach ($formatTypes as $fmt): ?>
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="formats[]" value="<?= $fmt['id'] ?>"
|
||
<?= in_array($fmt['id'], $currentFormats) ? 'checked' : '' ?>>
|
||
<?= htmlspecialchars($fmt['name']) ?>
|
||
</label>
|
||
<?php endforeach; ?>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="tag">Mots-clés :</label>
|
||
<div>
|
||
<input class="admin-input" type="text" id="tag" name="tag"
|
||
value="<?= htmlspecialchars($thesis['keywords'] ?? '') ?>">
|
||
<small>Séparer par des virgules. Max 10.</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="duration_info">Durée / Taille :</label>
|
||
<input class="admin-input" type="text" id="duration_info" name="duration_info"
|
||
value="<?= htmlspecialchars($thesis['file_size_info'] ?? '') ?>">
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label" for="lien">Lien externe :</label>
|
||
<input class="admin-input" type="url" id="lien" name="lien"
|
||
value="<?= htmlspecialchars($thesis['baiu_link'] ?? '') ?>">
|
||
</div>
|
||
|
||
<!-- Image bannière -->
|
||
<div class="admin-form-row">
|
||
<label class="admin-label">Image bannière (accueil) :</label>
|
||
<div>
|
||
<?php if (!empty($thesis['banner_path'])): ?>
|
||
<div class="admin-banner-preview">
|
||
<img src="/media.php?path=<?= urlencode($thesis['banner_path']) ?>"
|
||
alt="Bannière actuelle">
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="remove_banner" value="1"> Supprimer la bannière
|
||
</label>
|
||
</div>
|
||
<?php endif; ?>
|
||
<input type="file" name="banner" accept="image/jpeg,image/png,image/webp">
|
||
<small>JPG, PNG ou WEBP. Format paysage recommandé (4:1). Max 5 MB.</small>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="admin-form-row">
|
||
<label class="admin-label">Publication :</label>
|
||
<label class="admin-checkbox-label">
|
||
<input type="checkbox" name="is_published" value="1"
|
||
<?= $thesis['is_published'] ? 'checked' : '' ?>>
|
||
Publier ce TFE sur le site public
|
||
</label>
|
||
</div>
|
||
|
||
<div class="admin-submit-wrap">
|
||
<button type="submit" class="admin-btn">Enregistrer</button>
|
||
<a href="/admin/thanks.php?id=<?= $thesisId ?>" class="admin-btn-secondary admin-cancel-link">Annuler</a>
|
||
</div>
|
||
</form>
|
||
</main>
|
||
|
||
<?php require_once APP_ROOT . '/templates/admin/footer.php'; ?>
|