Files
ezmigrationbundle/Command/MigrateCommand.php

158 lines
5.7 KiB
PHP

<?php
namespace Kaliop\eZMigrationBundle\Command;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Helper\Table;
use Kaliop\eZMigrationBundle\API\Value\MigrationDefinition;
use Kaliop\eZMigrationBundle\API\Value\Migration;
/**
* Command to execute the available migration definitions.
*/
class MigrateCommand extends AbstractCommand
{
/**
* Set up the command.
*
* Define the name, options and help text.
*/
protected function configure()
{
parent::configure();
$this
->setName('kaliop:migration:migrate')
->setAliases(array('kaliop:migration:update'))
->setDescription('Execute available migration definitions.')
->addOption(
'path',
null,
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
"The directory or file to load the migration definitions from"
)
->addOption('ignore-failures', null, InputOption::VALUE_NONE, "Keep executing migration even if one fails")
->addOption('clear-cache', null, InputOption::VALUE_NONE, "Clear the cache after the command finishes")
->addOption('no-interaction', 'n', InputOption::VALUE_NONE, "Do not ask any interactive question")
->setHelp(<<<EOT
The <info>kaliop:migration:migrate</info> command loads and executes migrations:
<info>./ezpublish/console kaliop:migration:migrate</info>
You can optionally specify the path to migration definitions with <info>--path</info>:
<info>./ezpublish/console kaliop:migrations:migrate --path=/path/to/bundle/version_directory --path=/path/to/bundle/version_directory/single_migration_file</info>
EOT
);
}
/**
* Execute the command.
*
* @param InputInterface $input
* @param OutputInterface $output
* @return null|int null or 0 if everything went fine, or an error code
*
* @todo Add functionality to work with specified version files not just directories.
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$migrationsService = $this->getMigrationService();
$migrationDefinitions = $migrationsService->getMigrationsDefinitions($input->getOption('path')) ;
$migrations = $migrationsService->getMigrations();
if (!count($migrationDefinitions)) {
$output->writeln('<info>No migrations found</info>');
return;
}
// filter away all migrations except 'to do' ones
$toExecute = array();
foreach($migrationDefinitions as $name => $migrationDefinition) {
if (!isset($migrations[$name]) || (($migration = $migrations[$name]) && $migration->status == Migration::STATUS_TODO)) {
$toExecute[$name] = $migrationsService->parseMigrationDefinition($migrationDefinition);
}
}
// just in case...
ksort($toExecute);
if (!count($toExecute)) {
$output->writeln('<info>No migrations to execute</info>');
return;
}
$output->writeln("\n <info>==</info> Migrations to be executed\n");
$data = array();
$i = 1;
foreach($toExecute as $name => $migrationDefinition) {
$notes = '';
if ($migrationDefinition->status != MigrationDefinition::STATUS_PARSED) {
$notes = '<error>' . $migrationDefinition->parsingError . '</error>';
}
$data[] = array(
$i++,
$name,
$notes
);
}
$table = new Table($output);
$table
->setHeaders(array('#', 'Migration', 'Notes'))
->setRows($data);
$table->render();
$output->writeln('');
// ask user for confirmation to make changes
if ($input->isInteractive() && !$input->getOption('no-interaction')) {
$dialog = $this->getHelperSet()->get('dialog');
if (!$dialog->askConfirmation(
$output,
'<question>Careful, the database will be modified. Do you want to continue Y/N ?</question>',
false
)
) {
$output->writeln('<error>Migration execution cancelled!</error>');
return 0;
}
} else {
$output->writeln("=============================================\n");
}
foreach($toExecute as $name => $migrationDefinition) {
// let's skip migrations that we know are invalid - user was warned and he decide to proceed anyway
if ($migrationDefinition->status == MigrationDefinition::STATUS_INVALID) {
$output->writeln("<comment>Skipping $name</comment>\n");
continue;
}
$output->writeln("<info>Processing $name</info>");
try {
$migrationsService->executeMigration($migrationDefinition);
} catch(\Exception $e) {
if ($input->getOption('ignore-failures')) {
$output->writeln("\n<error>Migration failed!".$e->getMessage()."</error>\n");
continue;
}
$output->writeln("\n<error>Migration aborted!".$e->getMessage()."</error>");
return 1;
}
$output->writeln('');
}
if ($input->getOption('clear-cache')) {
$command = $this->getApplication()->find('cache:clear');
$inputArray = new ArrayInput(array('command' => 'cache:clear'));
$command->run($inputArray, $output);
}
}
}