File: /var/www/payments-gateway/vendor/doctrine/migrations/src/Tools/Console/Command/ExecuteCommand.php
<?php
declare(strict_types=1);
namespace Doctrine\Migrations\Tools\Console\Command;
use Doctrine\Migrations\Version\Direction;
use Doctrine\Migrations\Version\Version;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function array_map;
use function dirname;
use function getcwd;
use function implode;
use function is_dir;
use function is_string;
use function is_writable;
use function sprintf;
use function strtoupper;
/**
* The ExecuteCommand class is responsible for executing migration versions up or down manually.
*/
#[AsCommand(name: 'migrations:execute', description: 'Execute one or more migration versions up or down manually.')]
final class ExecuteCommand extends DoctrineCommand
{
/** @var string|null */
protected static $defaultName = 'migrations:execute';
protected function configure(): void
{
$this
->setAliases(['execute'])
->setDescription(
'Execute one or more migration versions up or down manually.',
)
->addArgument(
'versions',
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
'The versions to execute.',
null,
)
->addOption(
'write-sql',
null,
InputOption::VALUE_OPTIONAL,
'The path to output the migration SQL file. Defaults to current working directory.',
false,
)
->addOption(
'dry-run',
null,
InputOption::VALUE_NONE,
'Execute the migration as a dry run.',
)
->addOption(
'up',
null,
InputOption::VALUE_NONE,
'Execute the migration up.',
)
->addOption(
'down',
null,
InputOption::VALUE_NONE,
'Execute the migration down.',
)
->addOption(
'query-time',
null,
InputOption::VALUE_NONE,
'Time all the queries individually.',
)
->setHelp(<<<'EOT'
The <info>%command.name%</info> command executes migration versions up or down manually:
<info>%command.full_name% FQCN</info>
You can show more information about the process by increasing the verbosity level. To see the
executed queries, set the level to debug with <comment>-vv</comment>:
<info>%command.full_name% FQCN -vv</info>
If no <comment>--up</comment> or <comment>--down</comment> option is specified it defaults to up:
<info>%command.full_name% FQCN --down</info>
You can also execute the migration as a <comment>--dry-run</comment>:
<info>%command.full_name% FQCN --dry-run</info>
You can output the prepared SQL statements to a file with <comment>--write-sql</comment>:
<info>%command.full_name% FQCN --write-sql</info>
Or you can also execute the migration without a warning message which you need to interact with:
<info>%command.full_name% FQCN --no-interaction</info>
All the previous commands accept multiple migration versions, allowing you run execute more than
one migration at once:
<info>%command.full_name% FQCN-1 FQCN-2 ...FQCN-n </info>
EOT);
parent::configure();
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$migratorConfigurationFactory = $this->getDependencyFactory()->getConsoleInputMigratorConfigurationFactory();
$migratorConfiguration = $migratorConfigurationFactory->getMigratorConfiguration($input);
$databaseName = (string) $this->getDependencyFactory()->getConnection()->getDatabase();
$question = sprintf(
'WARNING! You are about to execute a migration in database "%s" that could result in schema changes and data loss. Are you sure you wish to continue?',
$databaseName === '' ? '<unnamed>' : $databaseName,
);
if (! $migratorConfiguration->isDryRun() && ! $this->canExecute($question, $input)) {
$this->io->error('Migration cancelled!');
return 1;
}
$this->getDependencyFactory()->getMetadataStorage()->ensureInitialized();
$versions = $input->getArgument('versions');
$direction = $input->getOption('down') !== false
? Direction::DOWN
: Direction::UP;
$path = $input->getOption('write-sql') ?? getcwd();
if (is_string($path) && ! $this->isPathWritable($path)) {
$this->io->error(sprintf('The path "%s" not writeable!', $path));
return 1;
}
$planCalculator = $this->getDependencyFactory()->getMigrationPlanCalculator();
$plan = $planCalculator->getPlanForVersions(array_map(static fn (string $version): Version => new Version($version), $versions), $direction);
$this->getDependencyFactory()->getLogger()->notice(
'Executing' . ($migratorConfiguration->isDryRun() ? ' (dry-run)' : '') . ' {versions} {direction}',
[
'direction' => $plan->getDirection(),
'versions' => implode(', ', $versions),
],
);
$migrator = $this->getDependencyFactory()->getMigrator();
$sql = $migrator->migrate($plan, $migratorConfiguration);
if (is_string($path)) {
$writer = $this->getDependencyFactory()->getQueryWriter();
$writer->write($path, $direction, $sql);
}
$this->io->success(sprintf(
'Successfully migrated version(s): %s: [%s]',
implode(', ', $versions),
strtoupper($plan->getDirection()),
));
$this->io->newLine();
return 0;
}
private function isPathWritable(string $path): bool
{
return is_writable($path) || is_dir($path) || is_writable(dirname($path));
}
}