refactor: use encapsulated Database methods in formulaire.php and edit.php

This commit is contained in:
Pontoporeia
2026-03-28 13:47:26 +01:00
parent 71167b2cdf
commit e126e1a3b0
5 changed files with 135 additions and 90 deletions

View File

@@ -869,6 +869,71 @@ class Database {
}
}
// ========================================================================
// JUNCTION-TABLE HELPERS (delete-then-reinsert pattern)
// ========================================================================
/**
* Replace all language associations for a thesis.
* @param int $thesisId
* @param int[] $languageIds IDs from the languages table
*/
public function setThesisLanguages(int $thesisId, array $languageIds): void {
$this->pdo->prepare("DELETE FROM thesis_languages WHERE thesis_id = ?")->execute([$thesisId]);
$stmt = $this->pdo->prepare(
"INSERT INTO thesis_languages (thesis_id, language_id) VALUES (?, ?)"
);
foreach ($languageIds as $langId) {
$id = (int)$langId;
if ($id > 0) {
$stmt->execute([$thesisId, $id]);
}
}
}
/**
* Replace all format associations for a thesis.
* @param int $thesisId
* @param int[] $formatIds IDs from the format_types table
*/
public function setThesisFormats(int $thesisId, array $formatIds): void {
$this->pdo->prepare("DELETE FROM thesis_formats WHERE thesis_id = ?")->execute([$thesisId]);
$stmt = $this->pdo->prepare(
"INSERT INTO thesis_formats (thesis_id, format_id) VALUES (?, ?)"
);
foreach ($formatIds as $fmtId) {
$id = (int)$fmtId;
if ($id > 0) {
$stmt->execute([$thesisId, $id]);
}
}
}
/**
* Replace all tag associations for a thesis.
* Tags are identified by name (findOrCreateTag is called for each).
* Empty / whitespace-only names are silently skipped.
* Maximum 10 tags are accepted; extras are ignored.
*
* @param int $thesisId
* @param string[] $tagNames
*/
public function setThesisTags(int $thesisId, array $tagNames): void {
$this->pdo->prepare("DELETE FROM thesis_tags WHERE thesis_id = ?")->execute([$thesisId]);
$stmt = $this->pdo->prepare(
"INSERT OR IGNORE INTO thesis_tags (tag_id, thesis_id) VALUES (?, ?)"
);
$count = 0;
foreach ($tagNames as $name) {
if ($count >= 10) break;
$tagId = $this->findOrCreateTag($name); // trims, returns null for empty
if ($tagId !== null) {
$stmt->execute([$tagId, $thesisId]);
$count++;
}
}
}
// ========================================================================
// BANNER METHODS
// ========================================================================
@@ -883,6 +948,64 @@ class Database {
$stmt->execute([$path, $thesisId]);
}
/**
* Process a banner image upload for a thesis.
*
* Validates MIME type, extension, and file size, then saves the file to the
* banners/ directory under STORAGE_ROOT and calls setBannerPath().
*
* Returns the relative path (e.g. "banners/abc123.jpg") on success,
* or null if the file array is absent, has an error, fails validation,
* or cannot be moved.
*
* @param int $thesisId Target thesis ID
* @param array|null $uploadedFile Entry from $_FILES (e.g. $_FILES['banner'])
* @return string|null Relative path stored in the DB, or null
*/
public function handleBannerUpload(int $thesisId, ?array $uploadedFile): ?string {
if (!$uploadedFile || ($uploadedFile['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
return null;
}
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp'];
$allowedExts = ['jpg', 'jpeg', 'png', 'webp'];
$maxBytes = 5 * 1024 * 1024; // 5 MB
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($uploadedFile['tmp_name']);
$ext = strtolower(pathinfo($uploadedFile['name'], PATHINFO_EXTENSION));
if (!in_array($mimeType, $allowedMimes, true) ||
!in_array($ext, $allowedExts, true) ||
$uploadedFile['size'] > $maxBytes) {
error_log("handleBannerUpload: rejected " . $uploadedFile['name'] . " ($mimeType, {$uploadedFile['size']} bytes)");
return null;
}
$bannerDir = defined('STORAGE_ROOT') ? STORAGE_ROOT . '/banners/' : null;
if (!$bannerDir) {
error_log("handleBannerUpload: STORAGE_ROOT not defined");
return null;
}
if (!file_exists($bannerDir)) {
mkdir($bannerDir, 0755, true);
}
$safeName = bin2hex(random_bytes(16)) . '.' . $ext;
$targetPath = $bannerDir . $safeName;
if (!move_uploaded_file($uploadedFile['tmp_name'], $targetPath)) {
error_log("handleBannerUpload: move_uploaded_file failed for " . $uploadedFile['name']);
return null;
}
chmod($targetPath, 0644);
$relativePath = 'banners/' . $safeName;
$this->setBannerPath($thesisId, $relativePath);
error_log("handleBannerUpload: saved $relativePath");
return $relativePath;
}
// ========================================================================
// ENCAPSULATED QUERY HELPERS
// ========================================================================