Merge pull request #3904 from Zoddo/ticket/14162

[ticket/14162] Add CLI commands to manage migrations
This commit is contained in:
Marc Alexander 2015-10-07 14:03:02 +02:00
commit 64641f9b1f
8 changed files with 272 additions and 35 deletions

View file

@ -75,6 +75,17 @@ services:
tags: tags:
- { name: console.command } - { name: console.command }
console.command.db.list:
class: phpbb\console\command\db\list_command
arguments:
- @user
- @migrator
- @ext.manager
- @config
- @cache
tags:
- { name: console.command }
console.command.db.migrate: console.command.db.migrate:
class: phpbb\console\command\db\migrate class: phpbb\console\command\db\migrate
arguments: arguments:
@ -89,6 +100,19 @@ services:
tags: tags:
- { name: console.command } - { name: console.command }
console.command.db.revert:
class: phpbb\console\command\db\revert
arguments:
- @user
- @migrator
- @ext.manager
- @config
- @cache
- @filesystem
- %core.root_path%
tags:
- { name: console.command }
console.command.dev.migration_tips: console.command.dev.migration_tips:
class: phpbb\console\command\dev\migration_tips class: phpbb\console\command\dev\migration_tips
arguments: arguments:

View file

@ -50,7 +50,9 @@ $lang = array_merge($lang, array(
'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.', 'CLI_DESCRIPTION_CRON_LIST' => 'Prints a list of ready and unready cron jobs.',
'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.', 'CLI_DESCRIPTION_CRON_RUN' => 'Runs all ready cron tasks.',
'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run', 'CLI_DESCRIPTION_CRON_RUN_ARGUMENT_1' => 'Name of the task to be run',
'CLI_DESCRIPTION_DB_LIST' => 'List all installed and available migrations.',
'CLI_DESCRIPTION_DB_MIGRATE' => 'Updates the database by applying migrations.', 'CLI_DESCRIPTION_DB_MIGRATE' => 'Updates the database by applying migrations.',
'CLI_DESCRIPTION_DB_REVERT' => 'Revert a migration.',
'CLI_DESCRIPTION_DELETE_CONFIG' => 'Deletes a configuration option', 'CLI_DESCRIPTION_DELETE_CONFIG' => 'Deletes a configuration option',
'CLI_DESCRIPTION_DISABLE_EXTENSION' => 'Disables the specified extension.', 'CLI_DESCRIPTION_DISABLE_EXTENSION' => 'Disables the specified extension.',
'CLI_DESCRIPTION_ENABLE_EXTENSION' => 'Enables the specified extension.', 'CLI_DESCRIPTION_ENABLE_EXTENSION' => 'Enables the specified extension.',
@ -94,6 +96,12 @@ $lang = array_merge($lang, array(
'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.', 'CLI_FIXUP_RECALCULATE_EMAIL_HASH_SUCCESS' => 'Successfully recalculated all email hashes.',
'CLI_MIGRATION_NAME' => 'Migration name, including the namespace (use forward slashes instead of backslashes to avoid problems).',
'CLI_MIGRATIONS_AVAILABLE' => 'Available migrations',
'CLI_MIGRATIONS_INSTALLED' => 'Installed migrations',
'CLI_MIGRATIONS_ONLY_AVAILABLE' => 'Show only available migrations',
'CLI_MIGRATIONS_EMPTY' => 'No migrations.',
'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)', 'CLI_REPARSER_REPARSE_REPARSING' => 'Reparsing %1$s (range %2$d..%3$d)',
'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...', 'CLI_REPARSER_REPARSE_REPARSING_START' => 'Reparsing %s...',
'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success', 'CLI_REPARSER_REPARSE_SUCCESS' => 'Reparsing ended with success',

View file

@ -48,10 +48,17 @@ $lang = array_merge($lang, array(
'MIGRATION_EFFECTIVELY_INSTALLED' => 'Migration already effectively installed (skipped): %s', 'MIGRATION_EFFECTIVELY_INSTALLED' => 'Migration already effectively installed (skipped): %s',
'MIGRATION_EXCEPTION_ERROR' => 'Something went wrong during the request and an exception was thrown. The changes made before the error occurred were reversed to the best of our abilities, but you should check the board for errors.', 'MIGRATION_EXCEPTION_ERROR' => 'Something went wrong during the request and an exception was thrown. The changes made before the error occurred were reversed to the best of our abilities, but you should check the board for errors.',
'MIGRATION_NOT_FULFILLABLE' => 'The migration "%1$s" is not fulfillable, missing migration "%2$s".', 'MIGRATION_NOT_FULFILLABLE' => 'The migration "%1$s" is not fulfillable, missing migration "%2$s".',
'MIGRATION_NOT_INSTALLED' => 'The migration "%s" is not installed.',
'MIGRATION_NOT_VALID' => '%s is not a valid migration.', 'MIGRATION_NOT_VALID' => '%s is not a valid migration.',
'MIGRATION_SCHEMA_DONE' => 'Installed Schema: %1$s; Time: %2$.2f seconds', 'MIGRATION_SCHEMA_DONE' => 'Installed Schema: %1$s; Time: %2$.2f seconds',
'MIGRATION_SCHEMA_RUNNING' => 'Installing Schema: %s.', 'MIGRATION_SCHEMA_RUNNING' => 'Installing Schema: %s.',
'MIGRATION_REVERT_DATA_DONE' => 'Reverted Data: %1$s; Time: %2$.2f seconds',
'MIGRATION_REVERT_DATA_IN_PROGRESS' => 'Reverting Data: %1$s; Time: %2$.2f seconds',
'MIGRATION_REVERT_DATA_RUNNING' => 'Reverting Data: %s.',
'MIGRATION_REVERT_SCHEMA_DONE' => 'Reverted Schema: %1$s; Time: %2$.2f seconds',
'MIGRATION_REVERT_SCHEMA_RUNNING' => 'Reverting Schema: %s.',
'MIGRATION_INVALID_DATA_MISSING_CONDITION' => 'A migration is invalid. An if statement helper is missing a condition.', 'MIGRATION_INVALID_DATA_MISSING_CONDITION' => 'A migration is invalid. An if statement helper is missing a condition.',
'MIGRATION_INVALID_DATA_MISSING_STEP' => 'A migration is invalid. An if statement helper is missing a valid call to a migration step.', 'MIGRATION_INVALID_DATA_MISSING_STEP' => 'A migration is invalid. An if statement helper is missing a valid call to a migration step.',
'MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE' => 'A migration is invalid. A custom callable function could not be called.', 'MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE' => 'A migration is invalid. A custom callable function could not be called.',

View file

@ -0,0 +1,73 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\console\command\db;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class list_command extends \phpbb\console\command\db\migration_command
{
protected function configure()
{
$this
->setName('db:list')
->setDescription($this->user->lang('CLI_DESCRIPTION_DB_LIST'))
->addOption(
'available',
'u',
InputOption::VALUE_NONE,
$this->user->lang('CLI_MIGRATIONS_ONLY_AVAILABLE')
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$show_installed = !$input->getOption('available');
$installed = $available = array();
foreach ($this->load_migrations() as $name)
{
if ($this->migrator->migration_state($name) !== false)
{
$installed[] = $name;
}
else
{
$available[] = $name;
}
}
if ($show_installed)
{
$output->writeln('<info>' . $this->user->lang('CLI_MIGRATIONS_INSTALLED') . $this->user->lang('COLON') . '</info>');
$output->writeln($installed);
if (empty($installed))
{
$output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY'));
}
$output->writeln('');
}
$output->writeln('<info>' . $this->user->lang('CLI_MIGRATIONS_AVAILABLE') . $this->user->lang('COLON') . '</info>');
$output->writeln($available);
if (empty($available))
{
$output->writeln($this->user->lang('CLI_MIGRATIONS_EMPTY'));
}
}
}

View file

@ -15,20 +15,8 @@ namespace phpbb\console\command\db;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
class migrate extends \phpbb\console\command\command class migrate extends \phpbb\console\command\db\migration_command
{ {
/** @var \phpbb\db\migrator */
protected $migrator;
/** @var \phpbb\extension\manager */
protected $extension_manager;
/** @var \phpbb\config\config */
protected $config;
/** @var \phpbb\cache\service */
protected $cache;
/** @var \phpbb\log\log */ /** @var \phpbb\log\log */
protected $log; protected $log;
@ -40,14 +28,10 @@ class migrate extends \phpbb\console\command\command
function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path) function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\log\log $log, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
{ {
$this->migrator = $migrator;
$this->extension_manager = $extension_manager;
$this->config = $config;
$this->cache = $cache;
$this->log = $log; $this->log = $log;
$this->filesystem = $filesystem; $this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
parent::__construct($user); parent::__construct($user, $migrator, $extension_manager, $config, $cache);
$this->user->add_lang(array('common', 'install', 'migrator')); $this->user->add_lang(array('common', 'install', 'migrator'));
} }
@ -91,21 +75,4 @@ class migrate extends \phpbb\console\command\command
$this->finalise_update(); $this->finalise_update();
$output->writeln($this->user->lang['DATABASE_UPDATE_COMPLETE']); $output->writeln($this->user->lang['DATABASE_UPDATE_COMPLETE']);
} }
protected function load_migrations()
{
$migrations = $this->extension_manager
->get_finder()
->core_path('phpbb/db/migration/data/')
->extension_directory('/migrations')
->get_classes();
$this->migrator->set_migrations($migrations);
}
protected function finalise_update()
{
$this->cache->purge();
$this->config->increment('assets_version', 1);
}
} }

View file

@ -0,0 +1,56 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\console\command\db;
abstract class migration_command extends \phpbb\console\command\command
{
/** @var \phpbb\db\migrator */
protected $migrator;
/** @var \phpbb\extension\manager */
protected $extension_manager;
/** @var \phpbb\config\config */
protected $config;
/** @var \phpbb\cache\service */
protected $cache;
function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache)
{
$this->migrator = $migrator;
$this->extension_manager = $extension_manager;
$this->config = $config;
$this->cache = $cache;
parent::__construct($user);
}
protected function load_migrations()
{
$migrations = $this->extension_manager
->get_finder()
->core_path('phpbb/db/migration/data/')
->extension_directory('/migrations')
->get_classes();
$this->migrator->set_migrations($migrations);
return $migrations;
}
protected function finalise_update()
{
$this->cache->purge();
$this->config->increment('assets_version', 1);
}
}

View file

@ -0,0 +1,83 @@
<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
namespace phpbb\console\command\db;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class revert extends \phpbb\console\command\db\migration_command
{
/** @var string phpBB root path */
protected $phpbb_root_path;
/** @var \phpbb\filesystem\filesystem_interface */
protected $filesystem;
function __construct(\phpbb\user $user, \phpbb\db\migrator $migrator, \phpbb\extension\manager $extension_manager, \phpbb\config\config $config, \phpbb\cache\service $cache, \phpbb\filesystem\filesystem_interface $filesystem, $phpbb_root_path)
{
$this->filesystem = $filesystem;
$this->phpbb_root_path = $phpbb_root_path;
parent::__construct($user, $migrator, $extension_manager, $config, $cache);
$this->user->add_lang(array('common', 'migrator'));
}
protected function configure()
{
$this
->setName('db:revert')
->setDescription($this->user->lang('CLI_DESCRIPTION_DB_REVERT'))
->addArgument(
'name',
InputArgument::REQUIRED,
$this->user->lang('CLI_MIGRATION_NAME')
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$name = str_replace('/', '\\', $input->getArgument('name'));
$this->migrator->set_output_handler(new \phpbb\db\log_wrapper_migrator_output_handler($this->user, new console_migrator_output_handler($this->user, $output), $this->phpbb_root_path . 'store/migrations_' . time() . '.log', $this->filesystem));
$this->cache->purge();
if (!in_array($name, $this->load_migrations()))
{
$output->writeln('<error>' . $this->user->lang('MIGRATION_NOT_VALID', $name) . '</error>');
return 1;
}
else if ($this->migrator->migration_state($name) === false)
{
$output->writeln('<error>' . $this->user->lang('MIGRATION_NOT_INSTALLED', $name) . '</error>');
return 1;
}
try
{
while ($this->migrator->migration_state($name) !== false)
{
$this->migrator->revert($name);
}
}
catch (\phpbb\db\migration\exception $e)
{
$output->writeln('<error>' . $e->getLocalisedMessage($this->user) . '</error>');
$this->finalise_update();
return 1;
}
$this->finalise_update();
}
}

View file

@ -416,6 +416,9 @@ class migrator
if ($state['migration_data_done']) if ($state['migration_data_done'])
{ {
$this->output_handler->write(array('MIGRATION_REVERT_DATA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
$elapsed_time = microtime(true);
if ($state['migration_data_state'] !== 'revert_data') if ($state['migration_data_state'] !== 'revert_data')
{ {
$result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true); $result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true);
@ -431,9 +434,22 @@ class migrator
} }
$this->set_migration_state($name, $state); $this->set_migration_state($name, $state);
$elapsed_time = microtime(true) - $elapsed_time;
if ($state['migration_data_done'])
{
$this->output_handler->write(array('MIGRATION_REVERT_DATA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
}
else
{
$this->output_handler->write(array('MIGRATION_REVERT_DATA_IN_PROGRESS', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_VERY_VERBOSE);
}
} }
else if ($state['migration_schema_done']) else if ($state['migration_schema_done'])
{ {
$this->output_handler->write(array('MIGRATION_REVERT_SCHEMA_RUNNING', $name), migrator_output_handler_interface::VERBOSITY_VERBOSE);
$elapsed_time = microtime(true);
$steps = $this->helper->get_schema_steps($migration->revert_schema()); $steps = $this->helper->get_schema_steps($migration->revert_schema());
$result = $this->process_data_step($steps, $state['migration_data_state']); $result = $this->process_data_step($steps, $state['migration_data_state']);
@ -448,6 +464,9 @@ class migrator
unset($this->migration_state[$name]); unset($this->migration_state[$name]);
} }
$elapsed_time = microtime(true) - $elapsed_time;
$this->output_handler->write(array('MIGRATION_REVERT_SCHEMA_DONE', $name, $elapsed_time), migrator_output_handler_interface::VERBOSITY_NORMAL);
} }
return true; return true;