mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
131 lines
4.7 KiB
PHP
131 lines
4.7 KiB
PHP
<?php
|
|
/**
|
|
* Migration 016 — merge banners into covers
|
|
*
|
|
* 1. For every thesis that has a banner_path:
|
|
* a. Copy the file from storage/banners/<file> to storage/covers/<file>
|
|
* b. Insert a thesis_files row with file_type='cover'
|
|
* c. Clear theses.banner_path
|
|
* 2. Remove the now-empty storage/banners/ directory (best-effort).
|
|
*
|
|
* Safe to re-run: if a cover record already exists for a thesis, the banner
|
|
* migration for that thesis is skipped.
|
|
*/
|
|
|
|
defined('APP_ROOT') || define('APP_ROOT', dirname(__DIR__, 2));
|
|
defined('STORAGE_ROOT') || define('STORAGE_ROOT', APP_ROOT . '/storage');
|
|
|
|
$dbPath = APP_ROOT . '/storage/xamxam.db';
|
|
if (!file_exists($dbPath)) {
|
|
echo "ERROR: database not found at $dbPath\n";
|
|
exit(1);
|
|
}
|
|
|
|
$pdo = new PDO('sqlite:' . $dbPath);
|
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
|
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
|
|
$pdo->exec('PRAGMA foreign_keys = ON');
|
|
|
|
$coverDir = STORAGE_ROOT . '/covers/';
|
|
$bannerDir = STORAGE_ROOT . '/banners/';
|
|
|
|
if (!is_dir($coverDir)) {
|
|
mkdir($coverDir, 0755, true);
|
|
echo "Created covers/ directory.\n";
|
|
}
|
|
|
|
// Fetch all theses with a non-null banner_path
|
|
$stmt = $pdo->query("SELECT id, banner_path FROM theses WHERE banner_path IS NOT NULL");
|
|
$rows = $stmt->fetchAll();
|
|
|
|
if (empty($rows)) {
|
|
echo "No banners to migrate.\n";
|
|
} else {
|
|
foreach ($rows as $row) {
|
|
$thesisId = (int)$row['id'];
|
|
$bannerPath = $row['banner_path']; // e.g. "banners/abc123.png"
|
|
|
|
// Skip if a cover record already exists for this thesis
|
|
$check = $pdo->prepare("SELECT id FROM thesis_files WHERE thesis_id = ? AND file_type = 'cover' LIMIT 1");
|
|
$check->execute([$thesisId]);
|
|
if ($check->fetch()) {
|
|
echo " Thesis $thesisId: cover record already exists — skipping banner migration.\n";
|
|
// Still clear banner_path so UI stays clean
|
|
$pdo->prepare("UPDATE theses SET banner_path = NULL WHERE id = ?")->execute([$thesisId]);
|
|
continue;
|
|
}
|
|
|
|
$srcAbs = STORAGE_ROOT . '/' . $bannerPath;
|
|
$filename = basename($bannerPath);
|
|
$dstAbs = $coverDir . $filename;
|
|
$dstRel = 'covers/' . $filename;
|
|
|
|
if (!file_exists($srcAbs)) {
|
|
echo " Thesis $thesisId: source file missing ($srcAbs) — inserting DB record with new path anyway, skipping file copy.\n";
|
|
} else {
|
|
if (!copy($srcAbs, $dstAbs)) {
|
|
echo " ERROR: could not copy $srcAbs → $dstAbs — skipping thesis $thesisId.\n";
|
|
continue;
|
|
}
|
|
chmod($dstAbs, 0644);
|
|
echo " Thesis $thesisId: copied $bannerPath → $dstRel\n";
|
|
}
|
|
|
|
// Determine MIME from extension
|
|
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
$mime = match($ext) {
|
|
'jpg', 'jpeg' => 'image/jpeg',
|
|
'png' => 'image/png',
|
|
'webp' => 'image/webp',
|
|
default => 'image/jpeg',
|
|
};
|
|
|
|
// Get file size
|
|
$size = file_exists($dstAbs) ? filesize($dstAbs) : 0;
|
|
|
|
// Insert cover record
|
|
$ins = $pdo->prepare(
|
|
"INSERT INTO thesis_files (thesis_id, file_type, file_path, file_name, file_size, mime_type, sort_order)
|
|
VALUES (?, 'cover', ?, ?, ?, ?, 0)"
|
|
);
|
|
$ins->execute([$thesisId, $dstRel, $filename, $size, $mime]);
|
|
echo " Thesis $thesisId: inserted cover record → $dstRel\n";
|
|
|
|
// Clear banner_path
|
|
$pdo->prepare("UPDATE theses SET banner_path = NULL WHERE id = ?")->execute([$thesisId]);
|
|
echo " Thesis $thesisId: cleared banner_path.\n";
|
|
}
|
|
}
|
|
|
|
// Remove old banner files that were successfully copied
|
|
$remaining = glob($bannerDir . '*') ?: [];
|
|
$allClear = true;
|
|
foreach ($remaining as $f) {
|
|
$basename = basename($f);
|
|
if (file_exists($coverDir . $basename)) {
|
|
@unlink($f);
|
|
echo "Removed migrated banner file: banners/$basename\n";
|
|
} else {
|
|
echo "WARNING: banners/$basename has no corresponding cover — leaving in place.\n";
|
|
$allClear = false;
|
|
}
|
|
}
|
|
|
|
// Remove the now-empty banners/ directory (best-effort, ignoring .gitkeep)
|
|
if ($allClear && is_dir($bannerDir)) {
|
|
$leftovers = array_diff(scandir($bannerDir), ['.', '..', '.gitkeep']);
|
|
if (empty($leftovers)) {
|
|
// Remove .gitkeep if present, then the dir
|
|
$gitkeep = $bannerDir . '.gitkeep';
|
|
if (file_exists($gitkeep)) {
|
|
@unlink($gitkeep);
|
|
}
|
|
@rmdir($bannerDir);
|
|
echo "Removed banners/ directory.\n";
|
|
} else {
|
|
echo "WARNING: banners/ directory still has files after migration — leaving in place.\n";
|
|
}
|
|
}
|
|
|
|
echo "\nMigration 016 complete.\n";
|