chore: complete update

This commit is contained in:
2025-07-17 16:24:20 +02:00
parent 899227b0a4
commit 64a7051137
1300 changed files with 85570 additions and 2756 deletions

View File

@@ -0,0 +1,145 @@
<?php
declare(strict_types=1);
namespace App\Framework\Database\Migration;
use App\Framework\Database\ConnectionInterface;
use App\Framework\Database\Exception\DatabaseException;
use App\Framework\Database\Transaction;
final class MigrationRunner
{
private ConnectionInterface $connection;
private string $migrationsTable;
public function __construct(ConnectionInterface $connection, string $migrationsTable = 'migrations')
{
$this->connection = $connection;
$this->migrationsTable = $migrationsTable;
$this->ensureMigrationsTable();
}
/**
* @param Migration[] $migrations
*/
public function migrate(array $migrations): array
{
$executedMigrations = [];
$appliedVersions = $this->getAppliedVersions();
foreach ($migrations as $migration) {
if (in_array($migration->getVersion(), $appliedVersions, true)) {
continue;
}
try {
Transaction::run($this->connection, function() use ($migration) {
echo "Migrating: {$migration->getVersion()} - {$migration->getDescription()}\n";
$migration->up($this->connection);
$this->connection->execute(
"INSERT INTO {$this->migrationsTable} (version, description, executed_at) VALUES (?, ?, ?)",
[$migration->getVersion(), $migration->getDescription(), date('Y-m-d H:i:s')]
);
});
$executedMigrations[] = $migration->getVersion();
echo "Migrated: {$migration->getVersion()}\n";
} catch (\Throwable $e) {
throw new DatabaseException(
"Migration {$migration->getVersion()} failed: {$e->getMessage()}",
0,
$e
);
}
}
return $executedMigrations;
}
/**
* @param Migration[] $migrations
*/
public function rollback(array $migrations, int $steps = 1): array
{
$rolledBackMigrations = [];
$appliedVersions = $this->getAppliedVersions();
$sortedMigrations = $migrations;
usort($sortedMigrations, fn($a, $b) => $b->getVersion() <=> $a->getVersion());
$count = 0;
foreach ($sortedMigrations as $migration) {
if ($count >= $steps) {
break;
}
if (!in_array($migration->getVersion(), $appliedVersions, true)) {
continue;
}
try {
Transaction::run($this->connection, function() use ($migration) {
echo "Rolling back: {$migration->getVersion()} - {$migration->getDescription()}\n";
$migration->down($this->connection);
$this->connection->execute(
"DELETE FROM {$this->migrationsTable} WHERE version = ?",
[$migration->getVersion()]
);
});
$rolledBackMigrations[] = $migration->getVersion();
$count++;
echo "Rolled back: {$migration->getVersion()}\n";
} catch (\Throwable $e) {
throw new DatabaseException(
"Rollback {$migration->getVersion()} failed: {$e->getMessage()}",
0,
$e
);
}
}
return $rolledBackMigrations;
}
public function getStatus(array $migrations): array
{
$appliedVersions = $this->getAppliedVersions();
$status = [];
foreach ($migrations as $migration) {
$status[] = [
'version' => $migration->getVersion(),
'description' => $migration->getDescription(),
'applied' => in_array($migration->getVersion(), $appliedVersions, true),
];
}
return $status;
}
private function getAppliedVersions(): array
{
return $this->connection->queryColumn(
"SELECT version FROM {$this->migrationsTable} ORDER BY executed_at"
);
}
private function ensureMigrationsTable(): void
{
$sql = "CREATE TABLE IF NOT EXISTS {$this->migrationsTable} (
id INT PRIMARY KEY AUTO_INCREMENT,
version VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
executed_at DATETIME NOT NULL,
INDEX idx_version (version)
)";
$this->connection->execute($sql);
}
}