Debug['allow_upgrades_to_beta']) {
return 'http://builds.piwik.org/piwik-' . $newVersion . '.zip';
}
return Config::getInstance()->General['latest_version_url'];
}
public function newVersionAvailable()
{
Piwik::checkUserIsSuperUser();
$newVersion = $this->checkNewVersionIsAvailableOrDie();
$view = new View('@CoreUpdater/newVersionAvailable');
$view->piwik_version = Version::VERSION;
$view->piwik_new_version = $newVersion;
$view->piwik_latest_version_url = self::getLatestZipUrl($newVersion);
$view->can_auto_update = Filechecks::canAutoUpdate();
$view->makeWritableCommands = Filechecks::getAutoUpdateMakeWritableMessage();
echo $view->render();
}
public function oneClickUpdate()
{
Piwik::checkUserIsSuperUser();
$this->newVersion = $this->checkNewVersionIsAvailableOrDie();
SettingsServer::setMaxExecutionTime(0);
$url = self::getLatestZipUrl($this->newVersion);
$steps = array(
array('oneClick_Download', Piwik_Translate('CoreUpdater_DownloadingUpdateFromX', $url)),
array('oneClick_Unpack', Piwik_Translate('CoreUpdater_UnpackingTheUpdate')),
array('oneClick_Verify', Piwik_Translate('CoreUpdater_VerifyingUnpackedFiles')),
array('oneClick_CreateConfigFileBackup', Piwik_Translate('CoreUpdater_CreatingBackupOfConfigurationFile', self::CONFIG_FILE_BACKUP)),
array('oneClick_Copy', Piwik_Translate('CoreUpdater_InstallingTheLatestVersion')),
array('oneClick_Finished', Piwik_Translate('CoreUpdater_PiwikUpdatedSuccessfully')),
);
$errorMessage = false;
$messages = array();
foreach ($steps as $step) {
try {
$method = $step[0];
$message = $step[1];
$this->$method();
$messages[] = $message;
} catch (Exception $e) {
$errorMessage = $e->getMessage();
break;
}
}
// this is a magic template to trigger the Piwik_View_Update
$view = new OneClickDone(Piwik::getCurrentUserTokenAuth());
$view->coreError = $errorMessage;
$view->feedbackMessages = $messages;
echo $view->render();
}
public function oneClickResults()
{
Request::reloadAuthUsingTokenAuth($_POST);
Piwik::checkUserIsSuperUser();
$view = new View('@CoreUpdater/oneClickResults');
$view->coreError = Common::getRequestVar('error', '', 'string', $_POST);
$view->feedbackMessages = safe_unserialize(Common::unsanitizeInputValue(Common::getRequestVar('messages', '', 'string', $_POST)));
echo $view->render();
}
private function checkNewVersionIsAvailableOrDie()
{
$newVersion = UpdateCheck::isNewestVersionAvailable();
if (!$newVersion) {
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionAlreadyLatestVersion', Version::VERSION));
}
return $newVersion;
}
private function oneClick_Download()
{
$pathPiwikZip = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION . 'latest.zip';
$this->pathPiwikZip = SettingsPiwik::rewriteTmpPathWithHostname($pathPiwikZip);
Filechecks::dieIfDirectoriesNotWritable(array(self::PATH_TO_EXTRACT_LATEST_VERSION));
// we catch exceptions in the caller (i.e., oneClickUpdate)
$url = self::getLatestZipUrl($this->newVersion) . '?cb=' . $this->newVersion;
Http::fetchRemoteFile($url, $this->pathPiwikZip);
}
private function oneClick_Unpack()
{
$pathExtracted = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION;
$pathExtracted = SettingsPiwik::rewriteTmpPathWithHostname($pathExtracted);
$this->pathRootExtractedPiwik = $pathExtracted . 'piwik';
if (file_exists($this->pathRootExtractedPiwik)) {
Filesystem::unlinkRecursive($this->pathRootExtractedPiwik, true);
}
$archive = Unzip::factory('PclZip', $this->pathPiwikZip);
if (0 == ($archive_files = $archive->extract($pathExtracted))) {
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveIncompatible', $archive->errorInfo()));
}
if (0 == count($archive_files)) {
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveEmpty'));
}
unlink($this->pathPiwikZip);
}
private function oneClick_Verify()
{
$someExpectedFiles = array(
'/config/global.ini.php',
'/index.php',
'/core/Piwik.php',
'/piwik.php',
'/plugins/API/API.php'
);
foreach ($someExpectedFiles as $file) {
if (!is_file($this->pathRootExtractedPiwik . $file)) {
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveIncomplete', $file));
}
}
}
private function oneClick_CreateConfigFileBackup()
{
$configFileBefore = PIWIK_USER_PATH . '/config/global.ini.php';
$configFileAfter = PIWIK_USER_PATH . self::CONFIG_FILE_BACKUP;
Filesystem::copy($configFileBefore, $configFileAfter);
}
private function oneClick_Copy()
{
/*
* Make sure the execute bit is set for this shell script
*/
if (!Rules::isBrowserTriggerEnabled()) {
@chmod($this->pathRootExtractedPiwik . '/misc/cron/archive.sh', 0755);
}
/*
* Copy all files to PIWIK_INCLUDE_PATH.
* These files are accessed through the dispatcher.
*/
Filesystem::copyRecursive($this->pathRootExtractedPiwik, PIWIK_INCLUDE_PATH);
/*
* These files are visible in the web root and are generally
* served directly by the web server. May be shared.
*/
if (PIWIK_INCLUDE_PATH !== PIWIK_DOCUMENT_ROOT) {
/*
* Copy PHP files that expect to be in the document root
*/
$specialCases = array(
'/index.php',
'/piwik.php',
'/js/index.php',
);
foreach ($specialCases as $file) {
Filesystem::copy($this->pathRootExtractedPiwik . $file, PIWIK_DOCUMENT_ROOT . $file);
}
/*
* Copy the non-PHP files (e.g., images, css, javascript)
*/
Filesystem::copyRecursive($this->pathRootExtractedPiwik, PIWIK_DOCUMENT_ROOT, true);
}
/*
* Config files may be user (account) specific
*/
if (PIWIK_INCLUDE_PATH !== PIWIK_USER_PATH) {
Filesystem::copyRecursive($this->pathRootExtractedPiwik . '/config', PIWIK_USER_PATH . '/config');
}
Filesystem::unlinkRecursive($this->pathRootExtractedPiwik, true);
if (function_exists('apc_clear_cache')) {
apc_clear_cache(); // clear the system (aka 'opcode') cache
}
}
private function oneClick_Finished()
{
}
public function index()
{
$language = Common::getRequestVar('language', '');
if (!empty($language)) {
LanguagesManager::setLanguageForSession($language);
}
$this->runUpdaterAndExit();
}
protected function runUpdaterAndExit()
{
$updater = new Updater();
$componentsWithUpdateFile = CoreUpdater::getComponentUpdates($updater);
if (empty($componentsWithUpdateFile)) {
Piwik::redirectToModule('CoreHome');
}
SettingsServer::setMaxExecutionTime(0);
$cli = Common::isPhpCliMode() ? '_cli' : '';
$welcomeTemplate = '@CoreUpdater/runUpdaterAndExit_welcome' . $cli;
$doneTemplate = '@CoreUpdater/runUpdaterAndExit_done' . $cli;
$viewWelcome = new View($welcomeTemplate);
$viewDone = new View($doneTemplate);
$sqlQueries = $updater->getSqlQueriesToExecute();
if (Common::isPhpCliMode()) {
$this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile);
echo $viewWelcome->render();
if (!$this->coreError && Piwik::getModule() == 'CoreUpdater') {
$this->doExecuteUpdates($viewDone, $updater, $componentsWithUpdateFile);
echo $viewDone->render();
}
} else {
if (Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1) {
$this->warningMessages = array();
$this->doExecuteUpdates($viewDone, $updater, $componentsWithUpdateFile);
if (count($sqlQueries) == 1 && !$this->coreError) {
Piwik::redirectToModule('CoreHome');
}
echo $viewDone->render();
} else {
$viewWelcome->queries = $sqlQueries;
$viewWelcome->isMajor = $updater->hasMajorDbUpdate();
$this->doWelcomeUpdates($viewWelcome, $componentsWithUpdateFile);
echo $viewWelcome->render();
}
}
exit;
}
private function doWelcomeUpdates($view, $componentsWithUpdateFile)
{
$view->new_piwik_version = Version::VERSION;
$view->commandUpgradePiwik = "
php " . Filesystem::getPathToPiwikRoot() . "/index.php -- \"module=CoreUpdater\"
";
$pluginNamesToUpdate = array();
$coreToUpdate = false;
// handle case of existing database with no tables
if (!DbHelper::isInstalled()) {
$this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Config::getInstance()->database['dbname']);
$this->coreError = true;
$currentVersion = 'N/A';
} else {
$this->errorMessages = array();
try {
$currentVersion = Piwik_GetOption('version_core');
} catch (Exception $e) {
$currentVersion = '<= 0.2.9';
}
foreach ($componentsWithUpdateFile as $name => $filenames) {
if ($name == 'core') {
$coreToUpdate = true;
} else {
$pluginNamesToUpdate[] = $name;
}
}
}
// check file integrity
$integrityInfo = Filechecks::getFileIntegrityInformation();
if (isset($integrityInfo[1])) {
if ($integrityInfo[0] == false) {
$this->warningMessages[] = Piwik_Translate('General_FileIntegrityWarningExplanation');
}
$this->warningMessages = array_merge($this->warningMessages, array_slice($integrityInfo, 1));
}
Filesystem::deleteAllCacheOnUpdate();
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->current_piwik_version = $currentVersion;
$view->pluginNamesToUpdate = $pluginNamesToUpdate;
$view->coreToUpdate = $coreToUpdate;
}
private function doExecuteUpdates($view, $updater, $componentsWithUpdateFile)
{
$this->loadAndExecuteUpdateFiles($updater, $componentsWithUpdateFile);
Filesystem::deleteAllCacheOnUpdate();
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->deactivatedPlugins = $this->deactivatedPlugins;
}
private function loadAndExecuteUpdateFiles($updater, $componentsWithUpdateFile)
{
// if error in any core update, show message + help message + EXIT
// if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE
// if warning in any core update or in any plugins update, show message + CONTINUE
// if no error or warning, success message + CONTINUE
foreach ($componentsWithUpdateFile as $name => $filenames) {
try {
$this->warningMessages = array_merge($this->warningMessages, $updater->update($name));
} catch (Updater_UpdateErrorException $e) {
$this->errorMessages[] = $e->getMessage();
if ($name == 'core') {
$this->coreError = true;
break;
} else {
\Piwik\PluginsManager::getInstance()->deactivatePlugin($name);
$this->deactivatedPlugins[] = $name;
}
}
}
}
}