- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
131 lines
4.7 KiB
PHP
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)));
|
|
}
|
|
}
|