PDF rausgenommen
This commit is contained in:
381
msd2/tracking/piwik/plugins/CoreUpdater/Commands/Update.php
Normal file
381
msd2/tracking/piwik/plugins/CoreUpdater/Commands/Update.php
Normal file
@ -0,0 +1,381 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\CoreUpdater\Commands;
|
||||
|
||||
use Piwik\Filechecks;
|
||||
use Piwik\SettingsServer;
|
||||
use Piwik\Version;
|
||||
use Piwik\Config;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Filesystem;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugin\ConsoleCommand;
|
||||
use Piwik\Plugins\CoreUpdater\Commands\Update\CliUpdateObserver;
|
||||
use Piwik\Plugins\CoreUpdater\NoUpdatesFoundException;
|
||||
use Piwik\Plugins\UserCountry\LocationProvider;
|
||||
use Piwik\Updater;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
|
||||
/**
|
||||
* @package CoreUpdater
|
||||
*/
|
||||
class Update extends ConsoleCommand
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $migrationQueries;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('core:update');
|
||||
|
||||
$this->setDescription(Piwik::translate('CoreUpdater_ConsoleCommandDescription'));
|
||||
|
||||
$this->addOption('yes', null, InputOption::VALUE_NONE, Piwik::translate('CoreUpdater_ConsoleParameterDescription'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute command like: ./console core:update --yes
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->executeClearCaches();
|
||||
|
||||
$yes = $input->getOption('yes');
|
||||
|
||||
try {
|
||||
$this->makeUpdate($input, $output, true);
|
||||
|
||||
if (!$yes) {
|
||||
$yes = $this->askForUpdateConfirmation($input, $output);
|
||||
}
|
||||
|
||||
if ($yes) {
|
||||
$output->writeln("\n" . Piwik::translate('CoreUpdater_ConsoleStartingDbUpgrade'));
|
||||
|
||||
$this->makeUpdate($input, $output, false);
|
||||
|
||||
$this->writeSuccessMessage($output, array(Piwik::translate('CoreUpdater_PiwikHasBeenSuccessfullyUpgraded')));
|
||||
} else {
|
||||
$this->writeSuccessMessage($output, array(Piwik::translate('CoreUpdater_DbUpgradeNotExecuted')));
|
||||
}
|
||||
|
||||
$this->writeAlertMessageWhenCommandExecutedWithUnexpectedUser($output);
|
||||
|
||||
|
||||
} catch(NoUpdatesFoundException $e) {
|
||||
// Do not fail if no updates were found
|
||||
$this->writeSuccessMessage($output, array($e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private function askForUpdateConfirmation(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$helper = $this->getHelper('question');
|
||||
$question = new ConfirmationQuestion('<comment>'.Piwik::translate('CoreUpdater_ExecuteDbUpgrade').' (y/N) </comment>', false);
|
||||
|
||||
return $helper->ask($input, $output, $question);
|
||||
}
|
||||
|
||||
protected function executeClearCaches()
|
||||
{
|
||||
Filesystem::deleteAllCacheOnUpdate();
|
||||
}
|
||||
|
||||
protected function makeUpdate(InputInterface $input, OutputInterface $output, $doDryRun)
|
||||
{
|
||||
$this->checkAllRequiredOptionsAreNotEmpty($input);
|
||||
|
||||
$updater = $this->makeUpdaterInstance($output);
|
||||
|
||||
$componentsWithUpdateFile = $updater->getComponentUpdates();
|
||||
if (empty($componentsWithUpdateFile)) {
|
||||
throw new NoUpdatesFoundException(Piwik::translate('CoreUpdater_AlreadyUpToDate'));
|
||||
}
|
||||
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" *** " . Piwik::translate('CoreUpdater_UpdateTitle') . " ***"
|
||||
));
|
||||
|
||||
// handle case of existing database with no tables
|
||||
if (!DbHelper::isInstalled()) {
|
||||
$this->handleCoreError($output, Piwik::translate('CoreUpdater_EmptyDatabaseError', Config::getInstance()->database['dbname']));
|
||||
return;
|
||||
}
|
||||
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_DatabaseUpgradeRequired'),
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_YourDatabaseIsOutOfDate')
|
||||
));
|
||||
|
||||
if ($this->isUpdatingCore($componentsWithUpdateFile)) {
|
||||
$currentVersion = $this->getCurrentVersionForCore($updater);
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY', array($currentVersion, Version::VERSION))
|
||||
));
|
||||
}
|
||||
|
||||
$pluginsToUpdate = $this->getPluginsToUpdate($componentsWithUpdateFile);
|
||||
if (!empty($pluginsToUpdate)) {
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_TheFollowingPluginsWillBeUpgradedX', implode(', ', $pluginsToUpdate))
|
||||
));
|
||||
}
|
||||
|
||||
$dimensionsToUpdate = $this->getDimensionsToUpdate($componentsWithUpdateFile);
|
||||
if (!empty($dimensionsToUpdate)) {
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_TheFollowingDimensionsWillBeUpgradedX', implode(', ', $dimensionsToUpdate))
|
||||
));
|
||||
}
|
||||
|
||||
$output->writeln("");
|
||||
|
||||
if ($doDryRun) {
|
||||
$this->doDryRun($updater, $output);
|
||||
} else {
|
||||
$this->doRealUpdate($updater, $componentsWithUpdateFile, $output);
|
||||
}
|
||||
}
|
||||
|
||||
private function doDryRun(Updater $updater, OutputInterface $output)
|
||||
{
|
||||
$migrationQueries = $this->getMigrationQueriesToExecute($updater);
|
||||
|
||||
if(empty($migrationQueries)) {
|
||||
$output->writeln(array(" *** ".Piwik::translate('CoreUpdater_ConsoleUpdateNoSqlQueries')." ***", ""));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ($updater->hasMajorDbUpdate()) {
|
||||
$output->writeln(array(
|
||||
"",
|
||||
sprintf("<comment>%s \n</comment>", Piwik::translate('CoreUpdater_MajorUpdateWarning1'))
|
||||
));
|
||||
}
|
||||
|
||||
$output->writeln(array(" *** ".Piwik::translate('CoreUpdater_DryRun')." ***", ""));
|
||||
|
||||
foreach ($migrationQueries as $query) {
|
||||
$output->writeln(" " . $query->__toString());
|
||||
}
|
||||
|
||||
$output->writeln(array("", " *** " . Piwik::translate('CoreUpdater_DryRunEnd') . " ***", ""));
|
||||
}
|
||||
|
||||
private function doRealUpdate(Updater $updater, $componentsWithUpdateFile, OutputInterface $output)
|
||||
{
|
||||
$output->writeln(array(" " . Piwik::translate('CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'), ""));
|
||||
|
||||
$updaterResult = $updater->updateComponents($componentsWithUpdateFile);
|
||||
|
||||
if (@$updaterResult['coreError']) {
|
||||
$this->handleCoreError($output, $updaterResult['errors'], $includeDiyHelp = true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($updaterResult['warnings'])) {
|
||||
$this->outputUpdaterWarnings($output, $updaterResult['warnings']);
|
||||
}
|
||||
|
||||
if (!empty($updaterResult['errors'])) {
|
||||
$this->outputUpdaterErrors($output, $updaterResult['errors'], $updaterResult['deactivatedPlugins']);
|
||||
}
|
||||
|
||||
if (!empty($updaterResult['warnings'])
|
||||
|| !empty($updaterResult['errors'])
|
||||
) {
|
||||
$output->writeln(array(
|
||||
" " . Piwik::translate('CoreUpdater_HelpMessageIntroductionWhenWarning'),
|
||||
"",
|
||||
" * " . $this->getUpdateHelpMessage()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function handleCoreError(OutputInterface $output, $errors, $includeDiyHelp = false)
|
||||
{
|
||||
if (!is_array($errors)) {
|
||||
$errors = array($errors);
|
||||
}
|
||||
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" [X] " . Piwik::translate('CoreUpdater_CriticalErrorDuringTheUpgradeProcess'),
|
||||
"",
|
||||
));
|
||||
|
||||
foreach ($errors as $errorMessage) {
|
||||
$errorMessage = trim($errorMessage);
|
||||
$errorMessage = str_replace("\n", "\n ", $errorMessage);
|
||||
|
||||
$output->writeln(" * $errorMessage");
|
||||
}
|
||||
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_HelpMessageIntroductionWhenError'),
|
||||
"",
|
||||
" * " . $this->getUpdateHelpMessage()
|
||||
));
|
||||
|
||||
if ($includeDiyHelp) {
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" " . Piwik::translate('CoreUpdater_ErrorDIYHelp'),
|
||||
"",
|
||||
" * " . Piwik::translate('CoreUpdater_ErrorDIYHelp_1'),
|
||||
" * " . Piwik::translate('CoreUpdater_ErrorDIYHelp_2'),
|
||||
" * " . Piwik::translate('CoreUpdater_ErrorDIYHelp_3'),
|
||||
" * " . Piwik::translate('CoreUpdater_ErrorDIYHelp_4'),
|
||||
" * " . Piwik::translate('CoreUpdater_ErrorDIYHelp_5')
|
||||
));
|
||||
}
|
||||
|
||||
throw new \RuntimeException(Piwik::translate('CoreUpdater_ConsoleUpdateFailure'));
|
||||
}
|
||||
|
||||
private function outputUpdaterWarnings(OutputInterface $output, $warnings)
|
||||
{
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" [!] " . Piwik::translate('CoreUpdater_WarningMessages'),
|
||||
""
|
||||
));
|
||||
|
||||
foreach ($warnings as $message) {
|
||||
$output->writeln(" * $message");
|
||||
}
|
||||
}
|
||||
|
||||
private function outputUpdaterErrors(OutputInterface $output, $errors, $deactivatedPlugins)
|
||||
{
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" [X] " . Piwik::translate('CoreUpdater_ErrorDuringPluginsUpdates'),
|
||||
""
|
||||
));
|
||||
|
||||
foreach ($errors as $message) {
|
||||
$output->writeln(" * $message");
|
||||
}
|
||||
|
||||
if (!empty($deactivatedPlugins)) {
|
||||
$output->writeln(array(
|
||||
"",
|
||||
" [!] " . Piwik::translate('CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins', implode(', ', $deactivatedPlugins))
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
private function getUpdateHelpMessage()
|
||||
{
|
||||
return Piwik::translate('CoreUpdater_HelpMessageContent', array('[',']',"\n *"));
|
||||
}
|
||||
|
||||
private function isUpdatingCore($componentsWithUpdateFile)
|
||||
{
|
||||
foreach ($componentsWithUpdateFile as $componentName => $updates) {
|
||||
if ($componentName == 'core') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function getCurrentVersionForCore(Updater $updater)
|
||||
{
|
||||
$currentVersion = $updater->getCurrentComponentVersion('core');
|
||||
if ($currentVersion === false) {
|
||||
$currentVersion = "<= 0.2.9";
|
||||
}
|
||||
return $currentVersion;
|
||||
}
|
||||
|
||||
private function getPluginsToUpdate($componentsWithUpdateFile)
|
||||
{
|
||||
$plugins = array();
|
||||
foreach ($componentsWithUpdateFile as $componentName => $updates) {
|
||||
if ($componentName !== 'core'
|
||||
&& 0 !== strpos($componentName, 'log_')
|
||||
) {
|
||||
$plugins[] = $componentName;
|
||||
}
|
||||
}
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
private function getDimensionsToUpdate($componentsWithUpdateFile)
|
||||
{
|
||||
$dimensions = array();
|
||||
foreach ($componentsWithUpdateFile as $componentName => $updates) {
|
||||
if (0 === strpos($componentName, 'log_')) {
|
||||
$dimensions[] = $componentName;
|
||||
}
|
||||
}
|
||||
|
||||
sort($dimensions);
|
||||
return $dimensions;
|
||||
}
|
||||
|
||||
private function getMigrationQueriesToExecute(Updater $updater)
|
||||
{
|
||||
if (empty($this->migrationQueries)) {
|
||||
$this->migrationQueries = $updater->getSqlQueriesToExecute();
|
||||
}
|
||||
return $this->migrationQueries;
|
||||
}
|
||||
|
||||
private function makeUpdaterInstance(OutputInterface $output)
|
||||
{
|
||||
$updater = new Updater();
|
||||
|
||||
$migrationQueryCount = count($this->getMigrationQueriesToExecute($updater));
|
||||
$updater->addUpdateObserver(new CliUpdateObserver($output, $migrationQueryCount));
|
||||
|
||||
return $updater;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OutputInterface $output
|
||||
*/
|
||||
protected function writeAlertMessageWhenCommandExecutedWithUnexpectedUser(OutputInterface $output)
|
||||
{
|
||||
if (SettingsServer::isWindows()) {
|
||||
// does not work on windows
|
||||
return;
|
||||
}
|
||||
|
||||
$processUserAndGroup = Filechecks::getUserAndGroup();
|
||||
$fileOwnerUserAndGroup = Filechecks::getOwnerOfPiwikFiles();
|
||||
|
||||
if (!$fileOwnerUserAndGroup || $processUserAndGroup == $fileOwnerUserAndGroup) {
|
||||
// current process user/group appear to be same as the Matomo filesystem user/group -> OK
|
||||
return;
|
||||
}
|
||||
$output->writeln(
|
||||
sprintf("<comment>%s</comment>", Piwik::translate('CoreUpdater_ConsoleUpdateUnexpectedUserWarning', [
|
||||
$processUserAndGroup,
|
||||
$fileOwnerUserAndGroup,
|
||||
Filechecks::getCommandToChangeOwnerOfPiwikFiles()
|
||||
]))
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\CoreUpdater\Commands\Update;
|
||||
|
||||
use Piwik\Updater\Migration;
|
||||
use Piwik\Updater\UpdateObserver;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
* UpdateObserver used to output progress of an update initiated on the command line. Prints the currently
|
||||
* executing query and the total number of queries to run.
|
||||
*
|
||||
* @package CoreUpdater
|
||||
*/
|
||||
class CliUpdateObserver extends UpdateObserver
|
||||
{
|
||||
/**
|
||||
* @var OutputInterface
|
||||
*/
|
||||
private $output;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $totalMigrationQueryCount;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $currentMigrationQueryExecutionCount = 0;
|
||||
|
||||
public function __construct(OutputInterface $output, $totalMigrationQueryCount)
|
||||
{
|
||||
$this->output = $output;
|
||||
$this->totalMigrationQueryCount = $totalMigrationQueryCount;
|
||||
}
|
||||
|
||||
public function onStartExecutingMigration($updateFile, Migration $migration)
|
||||
{
|
||||
$string = $migration->__toString();
|
||||
$this->output->write(" Executing <comment>$string</comment>... ");
|
||||
|
||||
++$this->currentMigrationQueryExecutionCount;
|
||||
}
|
||||
|
||||
public function onFinishedExecutingMigration($updateFile, Migration $migration)
|
||||
{
|
||||
$this->output->writeln("Done. <info>[{$this->currentMigrationQueryExecutionCount} / {$this->totalMigrationQueryCount}]</info>");
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user