nulib-base/php/src/db/_private/_migration.php

100 lines
2.8 KiB
PHP

<?php
namespace nulib\db\_private;
use nulib\cl;
use nulib\db\IDatabase;
use nulib\php\func;
abstract class _migration {
const MIGRATION = null;
function __construct($migrations, string $channel="", ?IDatabase $db=null) {
$this->db = $db;
$this->channel = $channel;
if ($migrations === null) $migrations = static::MIGRATION;
if ($migrations === null) $migrations = [];
elseif (is_string($migrations)) $migrations = [$migrations];
elseif (is_callable($migrations)) $migrations = [$migrations];
elseif (!is_array($migrations)) $migrations = [strval($migrations)];
$this->migrations = $migrations;
}
protected ?IDatabase $db;
protected string $channel;
const MIGRATION_TABLE = "_migration";
const MIGRATION_COLS = [
"channel" => "varchar not null",
"name" => "varchar not null",
"done" => "integer not null default 0",
"primary key (channel, name)",
];
protected function ensureTable(): void {
$this->db->exec([
"create table if not exists",
"table" => static::MIGRATION_TABLE,
"cols" => static::MIGRATION_COLS,
]);
}
protected function isMigrated(string $name): bool {
return boolval($this->db->get([
"select 1",
"from" => static::MIGRATION_TABLE,
"where" => [
"channel" => $this->channel,
"name" => $name,
"done" => 1,
],
]));
}
abstract protected function setMigrated(string $name, bool $done): void;
/** @var callable[]|string[] */
protected $migrations;
function migrate(?IDatabase $db=null): void {
$db = ($this->db ??= $db);
$this->ensureTable();
foreach ($this->migrations as $name => $migration) {
if ($this->isMigrated($name)) continue;
$this->setMigrated($name, false);
if (func::is_callable($migration)) {
func::with($migration)->bind($this)->invoke([$db, $name]);
} else {
foreach (cl::with($migration) as $query) {
$db->exec($query);
}
}
$this->setMigrated($name, true);
}
}
protected static function sql_prefix(?string $source=null): string {
$prefix = "-- -*- coding: utf-8 mode: sql -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8\n";
if ($source !== null) $prefix .= "-- autogénéré à partir de $source\n";
return $prefix;
}
function getSql(?string $source=null, ?IDatabase $db=null): string {
$db = ($this->db ??= $db);
$lines = [self::sql_prefix($source)];
foreach ($this->migrations as $name => $migration) {
$lines[] = "-- $name";
if (func::is_callable($migration)) {
$lines[] = "-- <fonction PHP>";
} else {
foreach (cl::with($migration) as $query) {
$sql = $db->getSql($query);
$lines[] = "$sql;";
}
}
$lines[] = "";
}
return implode("\n", $lines);
}
}