mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Fix migrations and deploy issues + errors + linting
- scan both pending/ and applied/ dirs so remote catch-up works - fix remote 500s: run.php handles per-statement errors so VIEW rebuilds run after duplicate columns; replace mb_strimwidth with substr (no mbstring extension on server) - add missing migration: 015_license_custom.sql (column existed in schema.sql but was never migrated) - remote: fgetcsv enclosure single-char + AdminLogger permission-denied guard + deploy always migrates - fix admin-filters wrapping: restore flex-wrap, flex-basis on inputs/selects, shrink-protect buttons - fix phpstan: remove redundant ?? [] after isset guard in ThesisEditController - biome: exclude vendored min.js via includes patterns; lint whole js dir; modernise beforeunload-guard.js
This commit is contained in:
1
app/migrations/applied/015_license_custom.sql
Normal file
1
app/migrations/applied/015_license_custom.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE theses ADD COLUMN license_custom TEXT;
|
||||
@@ -7,8 +7,8 @@
|
||||
*
|
||||
* If no DB_PATH is given, defaults to storage/xamxam.db.
|
||||
*
|
||||
* Each migration in migrations/pending/ is applied in alphabetical order.
|
||||
* After success, the file is moved to migrations/applied/.
|
||||
* Scans both migrations/pending/ and migrations/applied/ for .sql files.
|
||||
* Each is applied in alphabetical order if not already tracked in _migrations.
|
||||
*/
|
||||
|
||||
$root = dirname(__DIR__);
|
||||
@@ -34,17 +34,19 @@ $applied = $pdo->query("SELECT name FROM _migrations")->fetchAll(PDO::FETCH_COLU
|
||||
$pendingDir = $root . '/migrations/pending';
|
||||
$appliedDir = $root . '/migrations/applied';
|
||||
|
||||
if (!is_dir($pendingDir)) {
|
||||
echo "No pending migrations directory.\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!is_dir($appliedDir)) {
|
||||
mkdir($appliedDir, 0755, true);
|
||||
}
|
||||
|
||||
$files = glob($pendingDir . '/*.sql');
|
||||
sort($files);
|
||||
// Collect .sql files from both pending and applied dirs
|
||||
$files = [];
|
||||
foreach ([$pendingDir, $appliedDir] as $dir) {
|
||||
if (!is_dir($dir)) continue;
|
||||
foreach (glob($dir . '/*.sql') as $f) {
|
||||
$files[basename($f)] = $f;
|
||||
}
|
||||
}
|
||||
ksort($files);
|
||||
|
||||
if (empty($files)) {
|
||||
echo "No pending migration files.\n";
|
||||
@@ -52,8 +54,7 @@ if (empty($files)) {
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
foreach ($files as $file) {
|
||||
$name = basename($file);
|
||||
foreach ($files as $name => $file) {
|
||||
|
||||
if (in_array($name, $applied, true)) {
|
||||
echo "Skip (already applied): $name\n";
|
||||
@@ -63,21 +64,36 @@ foreach ($files as $file) {
|
||||
echo "Applying: $name\n";
|
||||
$sql = file_get_contents($file);
|
||||
|
||||
try {
|
||||
$pdo->exec($sql);
|
||||
$pdo->prepare("INSERT INTO _migrations (name) VALUES (?)")->execute([$name]);
|
||||
rename($file, $appliedDir . '/' . $name);
|
||||
$count++;
|
||||
} catch (PDOException $e) {
|
||||
$msg = $e->getMessage();
|
||||
// SQLite: skip if column already exists
|
||||
if (stripos($msg, 'duplicate column name') !== false) {
|
||||
echo " Already exists (skipping): $name\n";
|
||||
$pdo->prepare("INSERT OR REPLACE INTO _migrations (name) VALUES (?)")->execute([$name]);
|
||||
rename($file, $appliedDir . '/' . $name);
|
||||
continue;
|
||||
// Split into individual statements to handle partial failures gracefully
|
||||
// (e.g. ALTER TABLE may fail with "duplicate column" but DROP VIEW must still run)
|
||||
$statements = array_filter(
|
||||
array_map('trim', explode(';', $sql)),
|
||||
fn($s) => $s !== ''
|
||||
);
|
||||
|
||||
$errors = [];
|
||||
foreach ($statements as $stmt) {
|
||||
try {
|
||||
$pdo->exec($stmt . ';');
|
||||
} catch (PDOException $e) {
|
||||
$msg = $e->getMessage();
|
||||
if (stripos($msg, 'duplicate column name') !== false) {
|
||||
echo " Skipping (column exists): " . substr($stmt, 0, 60) . "...\n";
|
||||
continue;
|
||||
}
|
||||
$errors[] = $msg;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
if (empty($errors)) {
|
||||
$pdo->prepare("INSERT OR REPLACE INTO _migrations (name) VALUES (?)")->execute([$name]);
|
||||
if (str_starts_with($file, $pendingDir)) {
|
||||
rename($file, $appliedDir . '/' . $name);
|
||||
}
|
||||
$count++;
|
||||
} else {
|
||||
echo " FAILED: " . implode(' | ', $errors) . "\n";
|
||||
throw new PDOException(implode(' | ', $errors));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user