fix: fiabiliser les fiches animales et vaccinations

This commit is contained in:
Alexandre NOEL 2026-09-15 21:11:21 +02:00
commit 361bef8561
20 changed files with 157 additions and 65 deletions

View file

@ -91,13 +91,21 @@ final class Migrations
}
}
$relaxesForeignKeys = $name === '093_room_rules_and_care_periods.sql';
$relaxesForeignKeys = in_array(
$name,
['093_room_rules_and_care_periods.sql', '097_remove_legacy_room_constraint.sql'],
true,
);
if ($relaxesForeignKeys) {
$db->exec('PRAGMA foreign_keys = OFF');
}
$db->beginTransaction();
try {
$db->exec($sql);
if ($name === '097_remove_legacy_room_constraint.sql') {
self::modernizeAnimalConstraints($db);
} else {
$db->exec($sql);
}
$ins = $db->prepare("INSERT INTO _migrations(name, applied_at) VALUES(:n, datetime('now'))");
$ins->execute([':n' => $name]);
if ($relaxesForeignKeys && $db->query('PRAGMA foreign_key_check')->fetchColumn() !== false) {
@ -116,4 +124,62 @@ final class Migrations
}
}
}
private static function modernizeAnimalConstraints(PDO $db): void
{
$createSql = (string) $db
->query("SELECT sql FROM sqlite_master WHERE type='table' AND name='animals'")
->fetchColumn();
$constraint = "/refuge_room\\s+TEXT\\s+CHECK\\s*\\(\\s*refuge_room\\s+IN\\s*\\(\\s*'silver'\\s*,\\s*'twix'\\s*\\)\\s+OR\\s+refuge_room\\s+IS\\s+NULL\\s*\\)/i";
$registrationConstraint = "/identification_registration_status\\s+TEXT\\s+NOT\\s+NULL\\s+DEFAULT\\s+'unknown'\\s+CHECK\\s*\\(\\s*identification_registration_status\\s+IN\\s*\\(\\s*'unknown'\\s*,\\s*'pending'\\s*,\\s*'registered'\\s*\\)\\s*\\)/i";
if (
$createSql === ''
|| (!preg_match($constraint, $createSql) && !preg_match($registrationConstraint, $createSql))
) {
return;
}
$newSql = preg_replace(
'/^CREATE TABLE\\s+(?:IF NOT EXISTS\\s+)?["`\[]?animals["`\]]?/i',
'CREATE TABLE animals_room_unrestricted',
$createSql,
1,
);
$newSql = preg_replace($constraint, 'refuge_room TEXT', (string) $newSql, 1);
$newSql = preg_replace(
$registrationConstraint,
"identification_registration_status TEXT NOT NULL DEFAULT 'unknown' " .
"CHECK(identification_registration_status IN ('unknown','registered','change_pending','owner_changed','pending'))",
(string) $newSql,
1,
);
if (!$newSql || preg_match($constraint, $newSql)) {
throw new RuntimeException('Unable to remove the legacy shelter-room constraint.');
}
$objects = $db
->query("SELECT sql FROM sqlite_master WHERE tbl_name='animals' AND type IN ('index','trigger') AND sql IS NOT NULL")
->fetchAll(PDO::FETCH_COLUMN);
$views = $db
->query("SELECT name,sql FROM sqlite_master WHERE type='view' AND sql IS NOT NULL ORDER BY rowid")
->fetchAll(PDO::FETCH_ASSOC);
$columns = array_column($db->query('PRAGMA table_info(animals)')->fetchAll(PDO::FETCH_ASSOC), 'name');
$quotedColumns = implode(',', array_map(static fn(string $column): string => '"' . str_replace('"', '""', $column) . '"', $columns));
foreach ($views as $view) {
$viewName = '"' . str_replace('"', '""', (string) $view['name']) . '"';
$db->exec('DROP VIEW ' . $viewName);
}
$db->exec($newSql);
$db->exec("INSERT INTO animals_room_unrestricted ($quotedColumns) SELECT $quotedColumns FROM animals");
$db->exec("UPDATE animals_room_unrestricted SET identification_registration_status='change_pending' WHERE identification_registration_status='pending'");
$db->exec('DROP TABLE animals');
$db->exec('ALTER TABLE animals_room_unrestricted RENAME TO animals');
foreach ($objects as $objectSql) {
$db->exec((string) $objectSql);
}
foreach ($views as $view) {
$db->exec((string) $view['sql']);
}
}
}