.
* ---------------------------------------------------------------------
*/
namespace Glpi\Console\Database;
if (!defined('GLPI_ROOT')) {
die("Sorry. You can't access this file directly");
}
use Glpi\Console\AbstractCommand;
use Glpi\Console\Command\ForceNoPluginsOptionCommandInterface;
use Migration;
use Session;
use Update;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\ConfirmationQuestion;
class UpdateCommand extends AbstractCommand implements ForceNoPluginsOptionCommandInterface {
/**
* Error code returned when trying to update from an unstable version.
*
* @var integer
*/
const ERROR_NO_UNSTABLE_UPDATE = 1;
/**
* Error code returned when security key file is missing.
*
* @var integer
*/
const ERROR_MISSING_SECURITY_KEY_FILE = 2;
protected function configure() {
parent::configure();
$this->setName('glpi:database:update');
$this->setAliases(['db:update']);
$this->setDescription(__('Update database schema to new version'));
$this->addOption(
'allow-unstable',
'u',
InputOption::VALUE_NONE,
__('Allow update to an unstable version')
);
$this->addOption(
'force',
'f',
InputOption::VALUE_NONE,
__('Force execution of update from v-1 version of GLPI even if schema did not changed')
);
}
protected function initialize(InputInterface $input, OutputInterface $output) {
parent::initialize($input, $output);
$this->outputWarningOnMissingOptionnalRequirements();
$this->db->disableTableCaching();
}
protected function execute(InputInterface $input, OutputInterface $output) {
$allow_unstable = $input->getOption('allow-unstable');
$force = $input->getOption('force');
$no_interaction = $input->getOption('no-interaction'); // Base symfony/console option
$update = new Update($this->db);
// Initialize entities
$_SESSION['glpidefault_entity'] = 0;
Session::initEntityProfiles(2);
Session::changeProfile(4);
// Display current/future state informations
$currents = $update->getCurrents();
$current_version = $currents['version'];
$current_db_version = $currents['dbversion'];
global $migration; // Migration scripts are using global migrations
$migration = new Migration(GLPI_SCHEMA_VERSION);
$migration->setOutputHandler($output);
$update->setMigration($migration);
$informations = new Table($output);
$informations->setHeaders(['', __('Current'), _n('Target', 'Targets', 1)]);
$informations->addRow([__('Database host'), $this->db->dbhost, '']);
$informations->addRow([__('Database name'), $this->db->dbdefault, '']);
$informations->addRow([__('Database user'), $this->db->dbuser, '']);
$informations->addRow([__('GLPI version'), $current_version, GLPI_VERSION]);
$informations->addRow([__('GLPI database version'), $current_db_version, GLPI_SCHEMA_VERSION]);
$informations->render();
if (defined('GLPI_PREVER')) {
// Prevent unstable update unless explicitly asked
if (!$allow_unstable && version_compare($current_db_version, GLPI_SCHEMA_VERSION, 'ne')) {
$output->writeln(
sprintf(
'' . __('%s is not a stable release. Please upgrade manually or add --allow-unstable option.') . '',
GLPI_SCHEMA_VERSION
),
OutputInterface::VERBOSITY_QUIET
);
return self::ERROR_NO_UNSTABLE_UPDATE;
}
}
if (version_compare($current_db_version, GLPI_SCHEMA_VERSION, 'eq') && !$force) {
$output->writeln('' . __('No migration needed.') . '');
return 0;
}
if ($update->isExpectedSecurityKeyFileMissing()) {
$output->writeln(
sprintf(
'' . __('The key file "%s" used to encrypt/decrypt sensitive data is missing. You should retrieve it from your previous installation or encrypted data will be unreadable.') . '',
$update->getExpectedSecurityKeyFilePath()
),
OutputInterface::VERBOSITY_QUIET
);
if ($no_interaction) {
return self::ERROR_MISSING_SECURITY_KEY_FILE;
}
}
if (!$no_interaction) {
// Ask for confirmation (unless --no-interaction)
/** @var \Symfony\Component\Console\Helper\QuestionHelper $question_helper */
$question_helper = $this->getHelper('question');
$run = $question_helper->ask(
$input,
$output,
new ConfirmationQuestion(__('Do you want to continue ?') . ' [Yes/no]', true)
);
if (!$run) {
$output->writeln(
'' . __('Update aborted.') . '',
OutputInterface::VERBOSITY_VERBOSE
);
return 0;
}
}
$update->doUpdates($current_version);
if (version_compare($current_db_version, GLPI_SCHEMA_VERSION, 'ne')) {
// Migration is considered as done as Update class has the responsibility
// to run updates if schema has changed (even for "pre-versions".
$output->writeln('' . __('Migration done.') . '');
} else if ($force) {
// Replay last update script even if there is no schema change.
// It can be used in dev environment when update script has been updated/fixed.
include_once(GLPI_ROOT . '/install/update_951_952.php');
update951to952();
$output->writeln('' . __('Last migration replayed.') . '');
}
return 0; // Success
}
public function getNoPluginsOptionValue() {
return true;
}
}