mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-07 11:39:18 +02:00
edit.php was a 530-line file mixing form display, POST handling, file
uploads, and reference-data loading. This refactor splits it along the
same action-file pattern already used by formulaire.php, tag.php, and
page.php.
Changes:
- public/admin/actions/edit.php (new): standalone POST handler; auth
guard, CSRF check, transaction, redirect with session flash messages
- public/admin/edit.php: display-only; reads edit_success/edit_error
flash keys from session; form action points to actions/edit.php via
a hidden thesis_id field instead of a query-string self-post
- src/Database.php: four new methods to remove all raw PDO from both
files:
- updateThesis(int, array): void — UPDATE theses core fields
- setThesisAuthors(int, array): void — delete-then-reinsert authors
- getThesisLanguageIds(int): array — SELECT language_id for form
- getThesisFormatIds(int): array — SELECT format_id for form
142 lines
4.7 KiB
PHP
142 lines
4.7 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();
|
|
|
|
// Only handle POST requests
|
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
|
header('Location: ../index.php');
|
|
exit();
|
|
}
|
|
|
|
// Verify CSRF token
|
|
if (!isset($_POST['csrf_token']) || !isset($_SESSION['csrf_token']) ||
|
|
!hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
|
|
error_log("CSRF token validation failed in edit action");
|
|
die("Erreur de sécurité : token invalide. Veuillez recharger le formulaire.");
|
|
}
|
|
|
|
$thesisId = isset($_POST['thesis_id']) ? intval($_POST['thesis_id']) : 0;
|
|
if ($thesisId <= 0) {
|
|
die("ID de TFE invalide.");
|
|
}
|
|
|
|
require_once __DIR__ . '/../../../src/Database.php';
|
|
|
|
try {
|
|
$db = new Database();
|
|
|
|
$db->beginTransaction();
|
|
|
|
// Thesis metadata
|
|
$db->updateThesis($thesisId, [
|
|
'title' => trim($_POST['titre']),
|
|
'subtitle' => trim($_POST['subtitle'] ?? ''),
|
|
'year' => intval($_POST['année']),
|
|
'orientation_id' => intval($_POST['orientation']),
|
|
'ap_program_id' => intval($_POST['ap']),
|
|
'finality_id' => intval($_POST['finality']),
|
|
'synopsis' => trim($_POST['synopsis']),
|
|
'context_note' => trim($_POST['context_note'] ?? ''),
|
|
'file_size_info' => trim($_POST['duration_info'] ?? ''),
|
|
'baiu_link' => trim($_POST['lien'] ?? ''),
|
|
'license_id' => filter_var($_POST['license_id'] ?? '', FILTER_VALIDATE_INT) ?: null,
|
|
'access_type_id' => filter_var($_POST['access_type_id'] ?? '', FILTER_VALIDATE_INT) ?: null,
|
|
'is_published' => isset($_POST['is_published']),
|
|
]);
|
|
|
|
// Authors
|
|
$authorsRaw = trim($_POST['auteurice'] ?? '');
|
|
$authorEntries = [];
|
|
if (!empty($authorsRaw)) {
|
|
$names = array_map('trim', explode(',', $authorsRaw));
|
|
foreach ($names as $index => $name) {
|
|
if ($name !== '') {
|
|
$authorEntries[] = [
|
|
'name' => $name,
|
|
'email' => $index === 0 ? ($_POST['mail'] ?? null) : null,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
$db->setThesisAuthors($thesisId, $authorEntries);
|
|
|
|
// Jury
|
|
$juryMembers = [];
|
|
if (!empty(trim($_POST['jury_president'] ?? ''))) {
|
|
$juryMembers[] = ['name' => trim($_POST['jury_president']), 'role' => 'president', 'is_external' => 0];
|
|
}
|
|
if (!empty(trim($_POST['jury_promoteur'] ?? ''))) {
|
|
$juryMembers[] = [
|
|
'name' => trim($_POST['jury_promoteur']),
|
|
'role' => 'promoteur',
|
|
'is_external' => isset($_POST['jury_promoteur_ext']) ? 1 : 0,
|
|
];
|
|
}
|
|
foreach ($_POST['jury_lecteurs'] ?? [] as $i => $name) {
|
|
$name = trim($name);
|
|
if ($name !== '') {
|
|
$juryMembers[] = [
|
|
'name' => $name,
|
|
'role' => 'lecteur',
|
|
'is_external' => isset($_POST['jury_lecteurs_ext'][$i]) ? 1 : 0,
|
|
];
|
|
}
|
|
}
|
|
$db->setThesisJury($thesisId, $juryMembers);
|
|
|
|
// Languages
|
|
$db->setThesisLanguages(
|
|
$thesisId,
|
|
isset($_POST['languages']) && is_array($_POST['languages']) ? $_POST['languages'] : []
|
|
);
|
|
|
|
// Formats
|
|
$db->setThesisFormats(
|
|
$thesisId,
|
|
isset($_POST['formats']) && is_array($_POST['formats']) ? $_POST['formats'] : []
|
|
);
|
|
|
|
// Tags
|
|
$keywordsRaw = trim($_POST['tag'] ?? '');
|
|
$editKeywords = !empty($keywordsRaw) ? array_map('trim', explode(',', $keywordsRaw)) : [];
|
|
$db->setThesisTags($thesisId, $editKeywords);
|
|
|
|
$db->commit();
|
|
|
|
// Banner upload/removal (after commit, outside transaction)
|
|
if (isset($_POST['remove_banner'])) {
|
|
$currentBannerPath = $db->getThesisBannerPath($thesisId);
|
|
if ($currentBannerPath && defined('STORAGE_ROOT')) {
|
|
$absPath = STORAGE_ROOT . '/' . $currentBannerPath;
|
|
if (file_exists($absPath)) {
|
|
unlink($absPath);
|
|
}
|
|
}
|
|
$db->setBannerPath($thesisId, null);
|
|
} else {
|
|
$db->handleBannerUpload($thesisId, $_FILES['banner'] ?? null);
|
|
}
|
|
|
|
// Regenerate CSRF token
|
|
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
|
|
|
|
// Flash success and redirect back to edit form
|
|
$_SESSION['edit_success'] = "TFE mis à jour avec succès!";
|
|
header('Location: ../edit.php?id=' . $thesisId);
|
|
exit();
|
|
|
|
} catch (Exception $e) {
|
|
if (isset($db)) {
|
|
$db->rollback();
|
|
}
|
|
error_log("Edit action error: " . $e->getMessage());
|
|
|
|
$_SESSION['edit_error'] = $e->getMessage();
|
|
header('Location: ../edit.php?id=' . $thesisId);
|
|
exit();
|
|
}
|