checkNewVersionIsAvailableOrDie();
$view = Piwik_View::factory('update_new_version_available');
$view->piwik_version = Piwik_Version::VERSION;
$view->piwik_new_version = $newVersion;
echo $view->render();
}
public function oneClickUpdate()
{
Piwik::checkUserIsSuperUser();
$this->checkNewVersionIsAvailableOrDie();
Piwik::setMaxExecutionTime(0);
$steps = array(
array('oneClick_Download', Piwik_Translate('CoreUpdater_DownloadingUpdateFromX', self::LATEST_PIWIK_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;
}
}
$view = Piwik_View::factory('update_one_click_done');
$view->coreError = $errorMessage;
$view->feedbackMessages = $messages;
echo $view->render();
}
private function checkNewVersionIsAvailableOrDie()
{
$newVersion = Piwik_UpdateCheck::isNewestVersionAvailable();
if(!$newVersion)
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionAlreadyLatestVersion', Piwik_Version::VERSION));
}
return $newVersion;
}
private function oneClick_Download()
{
$this->pathPiwikZip = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION . '/latest.zip';
Piwik::checkDirectoriesWritableOrDie( array(self::PATH_TO_EXTRACT_LATEST_VERSION) );
// we catch exceptions in the caller (i.e., oneClickUpdate)
$fetched = Piwik_Http::fetchRemoteFile(self::LATEST_PIWIK_URL, $this->pathPiwikZip);
}
private function oneClick_Unpack()
{
require_once PIWIK_INCLUDE_PATH . '/libs/PclZip/pclzip.lib.php';
$archive = new PclZip($this->pathPiwikZip);
$pathExtracted = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION;
if ( false == ($archive_files = $archive->extract(
PCLZIP_OPT_PATH, $pathExtracted)) )
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveIncompatible', $archive->errorInfo(true)));
}
if ( 0 == count($archive_files) )
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveEmpty'));
}
unlink($this->pathPiwikZip);
$this->pathRootExtractedPiwik = $pathExtracted . '/piwik';
}
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;
Piwik::copy($configFileBefore, $configFileAfter);
}
private function oneClick_Copy()
{
/*
* Overwrite the downloaded robots.txt with our local copy
*/
Piwik::copy(PIWIK_DOCUMENT_ROOT . '/robots.txt', $this->pathRootExtractedPiwik . '/robots.txt');
/*
* Copy all files to PIWIK_INCLUDE_PATH.
* These files are accessed through the dispatcher.
*/
Piwik::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)
{
Piwik::copy($this->pathRootExtractedPiwik . $file, PIWIK_DOCUMENT_ROOT . $file);
}
/*
* Copy the non-PHP files (e.g., images, css, javascript)
*/
Piwik::copyRecursive($this->pathRootExtractedPiwik, PIWIK_DOCUMENT_ROOT, true);
}
/*
* Config files may be user (account) specific
*/
if(PIWIK_INCLUDE_PATH !== PIWIK_USER_PATH)
{
Piwik::copyRecursive($this->pathRootExtractedPiwik . '/config', PIWIK_USER_PATH . '/config');
}
Piwik::unlinkRecursive($this->pathRootExtractedPiwik, true);
}
private function oneClick_Finished()
{
}
public function index()
{
$language = Piwik_Common::getRequestVar('language', '');
if(!empty($language))
{
Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language);
}
$this->runUpdaterAndExit();
}
protected function runUpdaterAndExit()
{
$updater = new Piwik_Updater();
$componentsWithUpdateFile = Piwik_CoreUpdater::getComponentUpdates($updater);
if(empty($componentsWithUpdateFile))
{
Piwik::redirectToModule('CoreHome');
}
Piwik::setMaxExecutionTime(0);
if(Piwik_Common::isPhpCliMode())
{
$view = Piwik_View::factory('update_welcome');
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
if(!$this->coreError)
{
$view = Piwik_View::factory('update_database_done');
$this->doExecuteUpdates($view, $updater, $componentsWithUpdateFile);
}
}
else if(Piwik_Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1)
{
$this->warningMessages = array();
$view = Piwik_View::factory('update_database_done');
$this->doExecuteUpdates($view, $updater, $componentsWithUpdateFile);
}
else
{
$view = Piwik_View::factory('update_welcome');
$view->queries = $updater->getSqlQueriesToExecute();
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
}
exit;
}
private function doWelcomeUpdates($view, $componentsWithUpdateFile)
{
$view->new_piwik_version = Piwik_Version::VERSION;
$view->commandUpgradePiwik = "
php ".Piwik_Common::getPathToPiwikRoot()."/index.php -- \"module=CoreUpdater\"
";
$pluginNamesToUpdate = array();
$coreToUpdate = false;
// handle case of existing database with no tables
if(!Piwik::isInstalled())
{
$this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Zend_Registry::get('config')->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 = Piwik::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));
}
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->current_piwik_version = $currentVersion;
$view->pluginNamesToUpdate = $pluginNamesToUpdate;
$view->coreToUpdate = $coreToUpdate;
$view->clearCompiledTemplates();
echo $view->render();
}
private function doExecuteUpdates($view, $updater, $componentsWithUpdateFile)
{
$this->loadAndExecuteUpdateFiles($updater, $componentsWithUpdateFile);
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->deactivatedPlugins = $this->deactivatedPlugins;
$view->clearCompiledTemplates();
echo $view->render();
}
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 (Piwik_Updater_UpdateErrorException $e) {
$this->errorMessages[] = $e->getMessage();
if($name == 'core')
{
$this->coreError = true;
break;
}
else
{
Piwik_PluginsManager::getInstance()->deactivatePlugin($name);
$this->deactivatedPlugins[] = $name;
}
}
}
}
}