From 58f473d734373047db585d3b2926d33aa326f5ab Mon Sep 17 00:00:00 2001
From: Robin Appelman <icewind@owncloud.com>
Date: Sat, 6 Jul 2013 17:00:00 +0200
Subject: [PATCH] split upgrade logic from ajax file

---
 core/ajax/update.php   | 135 ++++++++---------------------------
 lib/legacy/updater.php |  14 ++++
 lib/updater.php        | 157 +++++++++++++++++++++++++++++++----------
 3 files changed, 160 insertions(+), 146 deletions(-)
 create mode 100644 lib/legacy/updater.php

diff --git a/core/ajax/update.php b/core/ajax/update.php
index db00da0223..43ed75b07f 100644
--- a/core/ajax/update.php
+++ b/core/ajax/update.php
@@ -4,113 +4,34 @@ $RUNTIME_NOAPPS = true;
 require_once '../../lib/base.php';
 
 if (OC::checkUpgrade(false)) {
-	\OC_DB::enableCaching(false);
-	OC_Config::setValue('maintenance', true);
-	$installedVersion = OC_Config::getValue('version', '0.0.0');
-	$currentVersion = implode('.', OC_Util::getVersion());
-	OC_Log::write('core', 'starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, OC_Log::WARN);
-	$updateEventSource = new OC_EventSource();
-	$watcher = new UpdateWatcher($updateEventSource);
-	OC_Hook::connect('update', 'success', $watcher, 'success');
-	OC_Hook::connect('update', 'error', $watcher, 'error');
-	OC_Hook::connect('update', 'failure', $watcher, 'failure');
-	$watcher->success('Turned on maintenance mode');
-	try {
-		$result = OC_DB::updateDbFromStructure(OC::$SERVERROOT.'/db_structure.xml');
-		$watcher->success('Updated database');
-
-		// do a file cache upgrade for users with files
-		// this can take loooooooooooooooooooooooong
-		__doFileCacheUpgrade($watcher);
-	} catch (Exception $exception) {
-		$watcher->failure($exception->getMessage());
-	}
-	OC_Config::setValue('version', implode('.', OC_Util::getVersion()));
-	OC_App::checkAppsRequirements();
-	// load all apps to also upgrade enabled apps
-	OC_App::loadApps();
-	OC_Config::setValue('maintenance', false);
-	$watcher->success('Turned off maintenance mode');
-	$watcher->done();
-}
-
-/**
- * The FileCache Upgrade routine
- *
- * @param UpdateWatcher $watcher
- */
-function __doFileCacheUpgrade($watcher) {
-	try {
-		$query = \OC_DB::prepare('
-		SELECT DISTINCT `user`
-		FROM `*PREFIX*fscache`
-		');
-		$result = $query->execute();
-	} catch (\Exception $e) {
-		return;
-	}
-	$users = $result->fetchAll();
-	if(count($users) == 0) {
-		return;
-	}
-	$step = 100 / count($users);
-	$percentCompleted = 0;
-	$lastPercentCompletedOutput = 0;
-	$startInfoShown = false;
-	foreach($users as $userRow) {
-		$user = $userRow['user'];
-		\OC\Files\Filesystem::initMountPoints($user);
-		\OC\Files\Cache\Upgrade::doSilentUpgrade($user);
-		if(!$startInfoShown) {
-			//We show it only now, because otherwise Info about upgraded apps
-			//will appear between this and progress info
-			$watcher->success('Updating filecache, this may take really long...');
-			$startInfoShown = true;
-		}
-		$percentCompleted += $step;
-		$out = floor($percentCompleted);
-		if($out != $lastPercentCompletedOutput) {
-			$watcher->success('... '. $out.'% done ...');
-			$lastPercentCompletedOutput = $out;
-		}
-	}
-	$watcher->success('Updated filecache');
-}
-
-class UpdateWatcher {
-	/**
-	 * @var \OC_EventSource $eventSource;
-	 */
-	private $eventSource;
-
-	public function __construct($eventSource) {
-		$this->eventSource = $eventSource;
-	}
-
-	public function success($message) {
-		OC_Util::obEnd();
-		$this->eventSource->send('success', $message);
-		ob_start();
-	}
-
-	public function error($message) {
-		OC_Util::obEnd();
-		$this->eventSource->send('error', $message);
-		ob_start();
-	}
-
-	public function failure($message) {
-		OC_Util::obEnd();
-		$this->eventSource->send('failure', $message);
-		$this->eventSource->close();
+	$eventSource = new OC_EventSource();
+	$updater = new \OC\Updater(\OC_Log::$object);
+	$updater->listen('\OC\Updater', 'maintenanceStart', function () use ($eventSource) {
+		$eventSource->send('success', 'Turned on maintenance mode');
+	});
+	$updater->listen('\OC\Updater', 'maintenanceEnd', function () use ($eventSource) {
+		$eventSource->send('success', 'Turned off maintenance mode');
+	});
+	$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource) {
+		$eventSource->send('success', 'Updated database');
+	});
+	$updater->listen('\OC\Updater', 'filecacheStart', function () use ($eventSource) {
+		$eventSource->send('success', 'Updating filecache, this may take really long...');
+	});
+	$updater->listen('\OC\Updater', 'filecacheDone', function () use ($eventSource) {
+		$eventSource->send('success', 'Updated filecache');
+	});
+	$updater->listen('\OC\Updater', 'filecacheProgress', function ($out) use ($eventSource) {
+		$eventSource->send('success', '... ' . $out . '% done ...');
+	});
+	$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource) {
+		$eventSource->send('failure', $message);
+		$eventSource->close();
 		OC_Config::setValue('maintenance', false);
-		die();
-	}
+	});
 
-	public function done() {
-		OC_Util::obEnd();
-		$this->eventSource->send('done', '');
-		$this->eventSource->close();
-	}
+	$updater->upgrade();
 
-}
\ No newline at end of file
+	$eventSource->send('done', '');
+	$eventSource->close();
+}
diff --git a/lib/legacy/updater.php b/lib/legacy/updater.php
new file mode 100644
index 0000000000..8a769a2f14
--- /dev/null
+++ b/lib/legacy/updater.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
+ */
+
+class OC_Updater {
+	public static function check() {
+		$updater = new \OC\Updater();
+		return $updater->check();
+	}
+}
diff --git a/lib/updater.php b/lib/updater.php
index 9081bfc4be..6baf346a8e 100644
--- a/lib/updater.php
+++ b/lib/updater.php
@@ -1,56 +1,67 @@
 <?php
 /**
- * ownCloud
- *
- * @author Frank Karlitschek
- * @copyright 2012 Frank Karlitschek frank@owncloud.org
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
- *
+ * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com>
+ * This file is licensed under the Affero General Public License version 3 or
+ * later.
+ * See the COPYING-README file.
  */
 
+namespace OC;
+use OC\Hooks\BasicEmitter;
+
 /**
  * Class that handels autoupdating of ownCloud
+ *
+ * Hooks provided in scope \OC\Updater
+ *  - maintenanceStart()
+ *  - maintenanceEnd()
+ *  - dbUpgrade()
+ *  - filecacheStart()
+ *  - filecacheProgress(int $percentage)
+ *  - filecacheDone()
+ *  - failure(string $message)
  */
-class OC_Updater{
+class Updater extends BasicEmitter {
+
+	/**
+	 * @var \OC\Log $log
+	 */
+	private $log;
+
+	/**
+	 * @param \OC\Log $log
+	 */
+	public function __construct($log = null) {
+		$this->log = $log;
+	}
 
 	/**
 	 * Check if a new version is available
+	 * @return array | bool
 	 */
-	public static function check() {
+	public function check() {
 
 		// Look up the cache - it is invalidated all 30 minutes
-		if((OC_Appconfig::getValue('core', 'lastupdatedat') + 1800) > time()) {
-			return json_decode(OC_Appconfig::getValue('core', 'lastupdateResult'), true);
+		if ((\OC_Appconfig::getValue('core', 'lastupdatedat') + 1800) > time()) {
+			return json_decode(\OC_Appconfig::getValue('core', 'lastupdateResult'), true);
 		}
 
-		OC_Appconfig::setValue('core', 'lastupdatedat', time());
+		\OC_Appconfig::setValue('core', 'lastupdatedat', time());
 
-		if(OC_Appconfig::getValue('core', 'installedat', '')=='') {
-			OC_Appconfig::setValue('core', 'installedat', microtime(true));
+		if (\OC_Appconfig::getValue('core', 'installedat', '') == '') {
+			\OC_Appconfig::setValue('core', 'installedat', microtime(true));
 		}
 
-		$updaterurl='http://apps.owncloud.com/updater.php';
-		$version=OC_Util::getVersion();
-		$version['installed']=OC_Appconfig::getValue('core', 'installedat');
-		$version['updated']=OC_Appconfig::getValue('core', 'lastupdatedat');
-		$version['updatechannel']='stable';
-		$version['edition']=OC_Util::getEditionString();
-		$versionstring=implode('x', $version);
+		$updaterurl = 'http://apps.owncloud.com/updater.php';
+		$version = \OC_Util::getVersion();
+		$version['installed'] = \OC_Appconfig::getValue('core', 'installedat');
+		$version['updated'] = \OC_Appconfig::getValue('core', 'lastupdatedat');
+		$version['updatechannel'] = 'stable';
+		$version['edition'] = \OC_Util::getEditionString();
+		$versionstring = implode('x', $version);
 
 		//fetch xml data from updater
-		$url=$updaterurl.'?version='.$versionstring;
+		$url = $updaterurl . '?version=' . $versionstring;
 
 		// set a sensible timeout of 10 sec to stay responsive even if the update server is down.
 		$ctx = stream_context_create(
@@ -60,21 +71,89 @@ class OC_Updater{
 				)
 			)
 		);
-		$xml=@file_get_contents($url, 0, $ctx);
-		if($xml==false) {
+		$xml = @file_get_contents($url, 0, $ctx);
+		if ($xml == false) {
 			return array();
 		}
-		$data=@simplexml_load_string($xml);
+		$data = @simplexml_load_string($xml);
 
-		$tmp=array();
+		$tmp = array();
 		$tmp['version'] = $data->version;
 		$tmp['versionstring'] = $data->versionstring;
 		$tmp['url'] = $data->url;
 		$tmp['web'] = $data->web;
 
 		// Cache the result
-		OC_Appconfig::setValue('core', 'lastupdateResult', json_encode($data));
+		\OC_Appconfig::setValue('core', 'lastupdateResult', json_encode($data));
 
 		return $tmp;
 	}
-}
\ No newline at end of file
+
+	/**
+	 * runs the update actions in maintenance mode, does not upgrade the source files
+	 */
+	public function upgrade() {
+		\OC_DB::enableCaching(false);
+		\OC_Config::setValue('maintenance', true);
+		$installedVersion = \OC_Config::getValue('version', '0.0.0');
+		$currentVersion = implode('.', \OC_Util::getVersion());
+		if ($this->log) {
+			$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
+		}
+		$this->emit('\OC\Updater', 'maintenanceStart');
+		try {
+			\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml');
+			$this->emit('\OC\Updater', 'dbUpgrade');
+
+			// do a file cache upgrade for users with files
+			// this can take loooooooooooooooooooooooong
+			$this->upgradeFileCache();
+		} catch (\Exception $exception) {
+			$this->emit('\OC\Updater', 'failure', array($exception->getMessage()));
+		}
+		\OC_Config::setValue('version', implode('.', \OC_Util::getVersion()));
+		\OC_App::checkAppsRequirements();
+		// load all apps to also upgrade enabled apps
+		\OC_App::loadApps();
+		\OC_Config::setValue('maintenance', false);
+		$this->emit('\OC\Updater', 'maintenanceEnd');
+	}
+
+	private function upgradeFileCache() {
+		try {
+			$query = \OC_DB::prepare('
+				SELECT DISTINCT `user`
+				FROM `*PREFIX*fscache`
+			');
+			$result = $query->execute();
+		} catch (\Exception $e) {
+			return;
+		}
+		$users = $result->fetchAll();
+		if (count($users) == 0) {
+			return;
+		}
+		$step = 100 / count($users);
+		$percentCompleted = 0;
+		$lastPercentCompletedOutput = 0;
+		$startInfoShown = false;
+		foreach ($users as $userRow) {
+			$user = $userRow['user'];
+			\OC\Files\Filesystem::initMountPoints($user);
+			\OC\Files\Cache\Upgrade::doSilentUpgrade($user);
+			if (!$startInfoShown) {
+				//We show it only now, because otherwise Info about upgraded apps
+				//will appear between this and progress info
+				$this->emit('\OC\Updater', 'filecacheStart');
+				$startInfoShown = true;
+			}
+			$percentCompleted += $step;
+			$out = floor($percentCompleted);
+			if ($out != $lastPercentCompletedOutput) {
+				$this->emit('\OC\Updater', 'filecacheProgress', array($out));
+				$lastPercentCompletedOutput = $out;
+			}
+		}
+		$this->emit('\OC\Updater', 'filecacheDone');
+	}
+}
-- 
GitLab