query(<<rowCount() == 0 ) { if ($connection->exec(<<errorCode()); } } } function getAllMigrations() { $files = scandir(ROOT . "/persistence/migrations/"); $files = array_values(array_filter($files, fn($f) => $f[0] != ".")); sort($files); $migrations = []; foreach ($files as $file) { $delimiterPos = strpos($file, "_"); $migrations[intval(substr($file, 0, $delimiterPos))] = $file; } return $migrations; } function getAppliedMigrations(PDO $connection) { global $MIGRATION_TABLE; $result = $connection->query(<<fetchAll() as $row) { $migrations[$row["id"]] = $row["file"]; } return $migrations; } function getMigrationsToApply(PDO $connection) { $all = getAllMigrations(); $applied = getAppliedMigrations($connection); foreach ($applied as $id => $file) { unset($all[$id]); } return $all; } function executeSqlScript(PDO $connection, string $sql, string $file) { if ($connection->exec($sql) === false) { die("failed to apply migration " . $file . ": " . $connection->errorCode()); } } function applyMigration(PDO $connection, int $id, string $file) { global $MIGRATION_TABLE; $connection->beginTransaction(); $sql = file_get_contents(ROOT . "/persistence/migrations/" . $file); if (!$sql) { die("Unable to read migration file: " . $file); } executeSqlScript($connection, $sql, $file); $statement = $connection->prepare(<<execute([$id, $file]); try { $connection->commit(); } catch (PDOException $e) { // this might happen if the migration script contains a DDL statement // -> ignore } } return function(PDO $connection) { ensureDbStructureForMigrations($connection); $migrations = getMigrationsToApply($connection); foreach ($migrations as $id => $file) { applyMigration($connection, $id, $file); } };