140 lines
5.0 KiB
PHP
140 lines
5.0 KiB
PHP
|
<?php
|
||
|
namespace DatabaseHelper;
|
||
|
|
||
|
use DatabaseHelper\enums\Propagation;
|
||
|
use DatabaseHelper\enums\Type;
|
||
|
use InvalidArgumentException;
|
||
|
|
||
|
class Migration
|
||
|
{
|
||
|
protected Schema $table;
|
||
|
protected array $columnsToAdd = [];
|
||
|
protected array $columnsToModify = [];
|
||
|
protected array $columnsToDrop = [];
|
||
|
protected array $primaryKey = null;
|
||
|
protected array $foreignKeysToAdd = [];
|
||
|
protected array $foreignKeysToDrop = [];
|
||
|
|
||
|
public function __construct(Schema $table) {
|
||
|
$this->table = $table->copy();
|
||
|
}
|
||
|
|
||
|
public function addColumn(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Migration {
|
||
|
$this->table->columns[$name] = [
|
||
|
'name' => $name,
|
||
|
'type' => $type,
|
||
|
'default' => $default,
|
||
|
'isNullable' => $isNullable,
|
||
|
'isUnique' => $isUnique
|
||
|
];
|
||
|
$this->columnsToAdd[] = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function modifyColumn(string $name, Type $type, mixed $default = null, bool $isNullable = false, bool $isUnique = false): Migration {
|
||
|
if (!isset($this->table->columns[$name])) {
|
||
|
throw new InvalidArgumentException("Column $name does not exist.");
|
||
|
}
|
||
|
$this->table->columns[$name] = [
|
||
|
'name' => $name,
|
||
|
'type' => $type,
|
||
|
'default' => $default,
|
||
|
'isNullable' => $isNullable,
|
||
|
'isUnique' => $isUnique
|
||
|
];
|
||
|
$this->columnsToModify[] = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function dropColumn(string $name): Migration {
|
||
|
if (!isset($this->table->columns[$name])) {
|
||
|
throw new InvalidArgumentException("Column $name does not exist.");
|
||
|
}
|
||
|
unset($this->table->columns[$name]);
|
||
|
$this->columnsToDrop[] = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function changePrimaryKey(string $name, bool $autoInc = false): Migration {
|
||
|
if (!isset($this->table->columns[$name])) {
|
||
|
throw new InvalidArgumentException("Column $name does not exist.");
|
||
|
}
|
||
|
$this->table->primaryKey = [
|
||
|
'name' => $name,
|
||
|
'autoInc' => $autoInc
|
||
|
];
|
||
|
$this->primaryKey = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function addForeignKey(string $column, string $referencedTable, string $referencedColumn, Propagation $onDelete, Propagation $onUpdate): Migration {
|
||
|
if (!isset($this->table->columns[$column])) {
|
||
|
throw new InvalidArgumentException("Column $column does not exist.");
|
||
|
}
|
||
|
$this->table->foreignKeys[$column] = [
|
||
|
'referencedTable' => $referencedTable,
|
||
|
'referencedColumn' => $referencedColumn,
|
||
|
'onDelete' => $onDelete,
|
||
|
'onUpdate' => $onUpdate
|
||
|
];
|
||
|
$this->foreignKeysToAdd[] = $column;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function dropForeignKey(string $name): Migration {
|
||
|
if (!isset($this->table->foreignKeys[$name])) {
|
||
|
throw new InvalidArgumentException("Foreign key $name does not exist.");
|
||
|
}
|
||
|
unset($this->table->foreignKeys[$name]);
|
||
|
$this->foreignKeysToDrop[] = $name;
|
||
|
return $this;
|
||
|
}
|
||
|
|
||
|
public function toSql(): string {
|
||
|
$sql = "ALTER TABLE `{$this->table->name}` ";
|
||
|
$statements = [];
|
||
|
|
||
|
foreach ($this->columnsToAdd as $name) {
|
||
|
$col = $this->table->columns[$name];
|
||
|
$statements[] = "ADD COLUMN `{$col['name']}` {$col['type']->toString()}" .
|
||
|
($col['isNullable'] ? "" : " NOT NULL") .
|
||
|
($col['isUnique'] ? " UNIQUE" : "") .
|
||
|
($col['default'] !== null ? " DEFAULT " . (is_string($col['default']) ? "'{$col['default']}'" : $col['default']) : "");
|
||
|
}
|
||
|
|
||
|
foreach ($this->columnsToModify as $name) {
|
||
|
$col = $this->table->columns[$name];
|
||
|
$statements[] = "MODIFY COLUMN `{$col['name']}` {$col['type']->toString()}" .
|
||
|
($col['isNullable'] ? "" : " NOT NULL") .
|
||
|
($col['isUnique'] ? " UNIQUE" : "") .
|
||
|
($col['default'] !== null ? " DEFAULT " . (is_string($col['default']) ? "'{$col['default']}'" : $col['default']) : "");
|
||
|
}
|
||
|
|
||
|
foreach ($this->columnsToDrop as $name) {
|
||
|
$statements[] = "DROP COLUMN `$name`";
|
||
|
}
|
||
|
|
||
|
foreach ($this->foreignKeysToDrop as $name) {
|
||
|
$statements[] = "DROP FOREIGN KEY `$name`";
|
||
|
}
|
||
|
|
||
|
foreach ($this->foreignKeysToAdd as $column) {
|
||
|
$fk = $this->table->foreignKeys[$column];
|
||
|
$statements[] = "ADD CONSTRAINT `fk_{$column}` FOREIGN KEY (`$column`) REFERENCES `{$fk['referencedTable']}` (`{$fk['referencedColumn']}`) ON DELETE {$fk['onDelete']->toString()} ON UPDATE {$fk['onUpdate']->toString()}";
|
||
|
}
|
||
|
|
||
|
return $sql . implode(", ", $statements) . ";";
|
||
|
}
|
||
|
|
||
|
public function drop(): null {
|
||
|
|
||
|
}
|
||
|
|
||
|
public function migrate(): Schema {
|
||
|
global $wpdb;
|
||
|
$sql = $this->toSql();
|
||
|
$wpdb->query($sql);
|
||
|
return $this->table;
|
||
|
}
|
||
|
}
|