Files
michaelschiemer/src/Framework/Database/Migration/Commands/MakeMigrationFromDiffCommand.php
Michael Schiemer 55a330b223 Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
2025-08-11 20:13:26 +02:00

131 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Framework\Database\Migration\Commands;
use App\Framework\Console\ConsoleCommand;
use App\Framework\Console\ExitCode;
use App\Framework\Core\PathProvider;
use App\Framework\Database\DatabaseManager;
use App\Framework\Database\Migration\MigrationVersion;
use App\Framework\Database\Schema\Comparison\MigrationGenerator;
use App\Framework\Database\Schema\Comparison\SchemaComparator;
/**
* Command to generate a migration from schema differences between two databases
*/
final readonly class MakeMigrationFromDiffCommand
{
public function __construct(
private DatabaseManager $databaseManager,
private MigrationGenerator $migrationGenerator,
private PathProvider $pathProvider
) {
}
/**
* Generate a migration from schema differences
*
* @param string $name The name of the migration
* @param string $sourceConnection The name of the source connection (default: default)
* @param string $targetConnection The name of the target connection
* @param string|null $sourceSchema The name of the source schema (default: public for PostgreSQL, database name for MySQL)
* @param string|null $targetSchema The name of the target schema (default: public for PostgreSQL, database name for MySQL)
* @param string $domain The domain for the migration (default: Media)
* @return ExitCode
*/
#[ConsoleCommand('db:migrate:diff', 'Generate a migration from schema differences')]
public function __invoke(
string $name,
string $sourceConnection = 'default',
string $targetConnection = 'default',
?string $sourceSchema = null,
?string $targetSchema = null,
string $domain = 'Media'
): ExitCode {
if (empty($name)) {
echo "Error: Migration name is required\n";
echo "Usage: db:migrate:diff UpdateUserTable [sourceConnection] [targetConnection] [sourceSchema] [targetSchema] [domain]\n";
return ExitCode::INVALID_ARGUMENT;
}
try {
// Get the connections
$sourceConn = $this->databaseManager->getConnection($sourceConnection);
$targetConn = $this->databaseManager->getConnection($targetConnection);
// Compare the schemas
$comparator = new SchemaComparator($sourceConn, $targetConn);
$difference = $comparator->compare($sourceSchema, $targetSchema);
if (! $difference->hasDifferences()) {
echo "No schema differences found.\n";
return ExitCode::SUCCESS;
}
// Generate the migration
$className = $this->toClassName($name);
$version = MigrationVersion::fromDateTime(new \DateTimeImmutable());
$description = $name;
$migrationCode = $this->migrationGenerator->generateMigration(
$difference,
$className,
$description,
$version
);
// Save the migration to a file
$migrationPath = $this->pathProvider->resolvePath("src/Domain/{$domain}/Migrations");
if (! is_dir($migrationPath)) {
mkdir($migrationPath, 0755, true);
}
$fileName = "{$className}.php";
$filePath = $migrationPath . '/' . $fileName;
if (file_exists($filePath)) {
echo "Error: Migration file already exists: {$filePath}\n";
return ExitCode::SOFTWARE_ERROR;
}
file_put_contents($filePath, $migrationCode);
echo "Migration created: {$filePath}\n";
// Display a summary of the differences
echo "\nSchema Difference Summary:\n";
echo str_repeat('-', 80) . "\n";
$summary = $difference->getSummary();
echo "Missing tables: {$summary['missing_tables']}\n";
echo "Extra tables: {$summary['extra_tables']}\n";
echo "Modified tables: " . count($difference->tableDifferences) . "\n";
echo "\nFor detailed differences, use the db:schema:diff command.\n";
return ExitCode::SUCCESS;
} catch (\Throwable $e) {
echo "Error creating migration: {$e->getMessage()}\n";
if (isset($_ENV['APP_DEBUG']) && $_ENV['APP_DEBUG']) {
echo $e->getTraceAsString() . "\n";
}
return ExitCode::SOFTWARE_ERROR;
}
}
/**
* Convert a string to a class name
*/
private function toClassName(string $name): string
{
// Convert "Create Users Table" to "CreateUsersTable"
return str_replace(' ', '', ucwords(str_replace('_', ' ', $name)));
}
}