mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-27 00:59:18 +02:00
merge banners into covers: remove banner field, migrate files, add covers to search/home/repertoire cards
This commit is contained in:
@@ -1551,79 +1551,9 @@ class Database
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// BANNER METHODS
|
||||
// COVER METHODS (formerly also BANNER METHODS — banners merged into covers)
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
* Set (or clear) the banner_path for a thesis.
|
||||
*/
|
||||
public function setBannerPath(int $thesisId, ?string $path): void
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
'UPDATE theses SET banner_path = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?'
|
||||
);
|
||||
$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
|
||||
// ========================================================================
|
||||
@@ -1658,20 +1588,6 @@ class Database
|
||||
return $row !== false ? $row : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the banner_path for a thesis, or null.
|
||||
* Used when we need just the banner path without the full view expansion.
|
||||
*/
|
||||
public function getThesisBannerPath(int $thesisId): ?string
|
||||
{
|
||||
$stmt = $this->pdo->prepare(
|
||||
'SELECT banner_path FROM theses WHERE id = ? LIMIT 1'
|
||||
);
|
||||
$stmt->execute([$thesisId]);
|
||||
$val = $stmt->fetchColumn();
|
||||
return ($val !== false && $val !== null) ? (string)$val : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Batch-load cover file paths for a set of thesis IDs.
|
||||
* Returns [thesis_id => file_path] for IDs that have a cover in thesis_files.
|
||||
@@ -1891,19 +1807,10 @@ class Database
|
||||
|
||||
/**
|
||||
* Delete a single thesis and all its related data (cascade via FK).
|
||||
* Also removes the banner file from disk if present.
|
||||
* Removes thesis files from disk (covers are stored in thesis_files and handled here).
|
||||
*/
|
||||
public function deleteThesis(int $thesisId): void
|
||||
{
|
||||
// Clean up banner file
|
||||
$bannerPath = $this->getThesisBannerPath($thesisId);
|
||||
if ($bannerPath !== null) {
|
||||
$fullPath = defined('STORAGE_ROOT') ? STORAGE_ROOT . '/' . $bannerPath : null;
|
||||
if ($fullPath && file_exists($fullPath)) {
|
||||
@unlink($fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up thesis files from disk
|
||||
$files = $this->getThesisFiles($thesisId);
|
||||
foreach ($files as $file) {
|
||||
@@ -1928,13 +1835,6 @@ class Database
|
||||
|
||||
// Clean up files for each thesis
|
||||
foreach ($thesisIds as $id) {
|
||||
$bannerPath = $this->getThesisBannerPath($id);
|
||||
if ($bannerPath !== null) {
|
||||
$fullPath = defined('STORAGE_ROOT') ? STORAGE_ROOT . '/' . $bannerPath : null;
|
||||
if ($fullPath && file_exists($fullPath)) {
|
||||
@unlink($fullPath);
|
||||
}
|
||||
}
|
||||
$files = $this->getThesisFiles($id);
|
||||
foreach ($files as $file) {
|
||||
if (!empty($file['file_path']) && file_exists($file['file_path'])) {
|
||||
@@ -2058,9 +1958,9 @@ class Database
|
||||
return null;
|
||||
}
|
||||
|
||||
$allowedMimes = ['image/jpeg', 'image/png'];
|
||||
$allowedExts = ['jpg', 'jpeg', 'png'];
|
||||
$maxBytes = 10 * 1024 * 1024; // 10 MB
|
||||
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp'];
|
||||
$allowedExts = ['jpg', 'jpeg', 'png', 'webp'];
|
||||
$maxBytes = 20 * 1024 * 1024; // 20 MB
|
||||
|
||||
$finfo = new finfo(FILEINFO_MIME_TYPE);
|
||||
$mimeType = $finfo->file($upload['tmp_name']);
|
||||
|
||||
Reference in New Issue
Block a user