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(<<kaliop:migration:migrate command loads and executes migrations: ./ezpublish/console kaliop:migration:migrate You can optionally specify the path to migration definitions with --path: ./ezpublish/console kaliop:migrations:migrate --path=/path/to/bundle/version_directory --path=/path/to/bundle/version_directory/single_migration_file 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('No migrations found'); 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('No migrations to execute'); return; } $output->writeln("\n == Migrations to be executed\n"); $data = array(); $i = 1; foreach($toExecute as $name => $migrationDefinition) { $notes = ''; if ($migrationDefinition->status != MigrationDefinition::STATUS_PARSED) { $notes = '' . $migrationDefinition->parsingError . ''; } $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, 'Careful, the database will be modified. Do you want to continue Y/N ?', false ) ) { $output->writeln('Migration execution cancelled!'); 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("Skipping $name\n"); continue; } $output->writeln("Processing $name"); try { $migrationsService->executeMigration($migrationDefinition); } catch(\Exception $e) { if ($input->getOption('ignore-failures')) { $output->writeln("\nMigration failed!".$e->getMessage()."\n"); continue; } $output->writeln("\nMigration aborted!".$e->getMessage().""); 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); } } }