Passed
Push — master ( d96e2c...35e3d4 )
by Morris
24:18 queued 10:44
created

Updater::waitForCronToFinish()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 * @copyright Copyright (c) 2016, Lukas Reschke <[email protected]>
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Frank Karlitschek <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Lukas Reschke <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Steffen Lindner <[email protected]>
15
 * @author Thomas Müller <[email protected]>
16
 * @author Victor Dubiniuk <[email protected]>
17
 * @author Vincent Petry <[email protected]>
18
 *
19
 * @license AGPL-3.0
20
 *
21
 * This code is free software: you can redistribute it and/or modify
22
 * it under the terms of the GNU Affero General Public License, version 3,
23
 * as published by the Free Software Foundation.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
 * GNU Affero General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Affero General Public License, version 3,
31
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
32
 *
33
 */
34
35
namespace OC;
36
37
use OC\DB\MigrationService;
38
use OC\Hooks\BasicEmitter;
39
use OC\IntegrityCheck\Checker;
40
use OC_App;
41
use OCP\IConfig;
42
use OCP\ILogger;
43
use OCP\Util;
44
use Symfony\Component\EventDispatcher\GenericEvent;
45
46
/**
47
 * Class that handles autoupdating of ownCloud
48
 *
49
 * Hooks provided in scope \OC\Updater
50
 *  - maintenanceStart()
51
 *  - maintenanceEnd()
52
 *  - dbUpgrade()
53
 *  - failure(string $message)
54
 */
55
class Updater extends BasicEmitter {
56
57
	/** @var ILogger $log */
58
	private $log;
59
60
	/** @var IConfig */
61
	private $config;
62
63
	/** @var Checker */
64
	private $checker;
65
66
	/** @var Installer */
67
	private $installer;
68
69
	private $logLevelNames = [
70
		0 => 'Debug',
71
		1 => 'Info',
72
		2 => 'Warning',
73
		3 => 'Error',
74
		4 => 'Fatal',
75
	];
76
77
	/**
78
	 * @param IConfig $config
79
	 * @param Checker $checker
80
	 * @param ILogger $log
81
	 * @param Installer $installer
82
	 */
83
	public function __construct(IConfig $config,
84
								Checker $checker,
85
								ILogger $log = null,
86
								Installer $installer) {
87
		$this->log = $log;
88
		$this->config = $config;
89
		$this->checker = $checker;
90
		$this->installer = $installer;
91
	}
92
93
	/**
94
	 * runs the update actions in maintenance mode, does not upgrade the source files
95
	 * except the main .htaccess file
96
	 *
97
	 * @return bool true if the operation succeeded, false otherwise
98
	 */
99
	public function upgrade() {
100
		$this->emitRepairEvents();
101
		$this->logAllEvents();
102
103
		$logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
		$this->config->setSystemValue('loglevel', ILogger::DEBUG);
106
107
		$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
108
109
		if(!$wasMaintenanceModeEnabled) {
110
			$this->config->setSystemValue('maintenance', true);
111
			$this->emit('\OC\Updater', 'maintenanceEnabled');
112
		}
113
114
		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
115
		$currentVersion = implode('.', \OCP\Util::getVersion());
116
117
		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
118
119
		$success = true;
120
		try {
121
			$this->doUpgrade($currentVersion, $installedVersion);
122
		} catch (HintException $exception) {
123
			$this->log->logException($exception, ['app' => 'core']);
124
			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
125
			$success = false;
126
		} catch (\Exception $exception) {
127
			$this->log->logException($exception, ['app' => 'core']);
128
			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
129
			$success = false;
130
		}
131
132
		$this->emit('\OC\Updater', 'updateEnd', array($success));
133
134
		if(!$wasMaintenanceModeEnabled && $success) {
135
			$this->config->setSystemValue('maintenance', false);
136
			$this->emit('\OC\Updater', 'maintenanceDisabled');
137
		} else {
138
			$this->emit('\OC\Updater', 'maintenanceActive');
139
		}
140
141
		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
142
		$this->config->setSystemValue('loglevel', $logLevel);
143
		$this->config->setSystemValue('installed', true);
144
145
		return $success;
146
	}
147
148
	/**
149
	 * Return version from which this version is allowed to upgrade from
150
	 *
151
	 * @return array allowed previous versions per vendor
152
	 */
153
	private function getAllowedPreviousVersions() {
154
		// this should really be a JSON file
155
		require \OC::$SERVERROOT . '/version.php';
156
		/** @var array $OC_VersionCanBeUpgradedFrom */
157
		return $OC_VersionCanBeUpgradedFrom;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $OC_VersionCanBeUpgradedFrom seems to be never defined.
Loading history...
158
	}
159
160
	/**
161
	 * Return vendor from which this version was published
162
	 *
163
	 * @return string Get the vendor
164
	 */
165
	private function getVendor() {
166
		// this should really be a JSON file
167
		require \OC::$SERVERROOT . '/version.php';
168
		/** @var string $vendor */
169
		return (string) $vendor;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $vendor seems to be never defined.
Loading history...
170
	}
171
172
	/**
173
	 * Whether an upgrade to a specified version is possible
174
	 * @param string $oldVersion
175
	 * @param string $newVersion
176
	 * @param array $allowedPreviousVersions
177
	 * @return bool
178
	 */
179
	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
180
		$version = explode('.', $oldVersion);
181
		$majorMinor = $version[0] . '.' . $version[1];
182
183
		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
184
185
		// Vendor was not set correctly on install, so we have to white-list known versions
186
		if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
187
			$currentVendor = 'owncloud';
188
		}
189
190
		if ($currentVendor === 'nextcloud') {
191
			return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
192
				&& (version_compare($oldVersion, $newVersion, '<=') ||
193
					$this->config->getSystemValue('debug', false));
194
		}
195
196
		// Check if the instance can be migrated
197
		return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
198
			isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
199
	}
200
201
	/**
202
	 * runs the update actions in maintenance mode, does not upgrade the source files
203
	 * except the main .htaccess file
204
	 *
205
	 * @param string $currentVersion current version to upgrade to
206
	 * @param string $installedVersion previous version from which to upgrade from
207
	 *
208
	 * @throws \Exception
209
	 */
210
	private function doUpgrade($currentVersion, $installedVersion) {
211
		// Stop update if the update is over several major versions
212
		$allowedPreviousVersions = $this->getAllowedPreviousVersions();
213
		if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
214
			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
215
		}
216
217
		// Update .htaccess files
218
		try {
219
			Setup::updateHtaccess();
220
			Setup::protectDataDirectory();
221
		} catch (\Exception $e) {
222
			throw new \Exception($e->getMessage());
223
		}
224
225
		// create empty file in data dir, so we can later find
226
		// out that this is indeed an ownCloud data directory
227
		// (in case it didn't exist before)
228
		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
229
230
		// pre-upgrade repairs
231
		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
232
		$repair->run();
233
234
		$this->doCoreUpgrade();
235
236
		try {
237
			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
238
			Setup::installBackgroundJobs();
239
		} catch (\Exception $e) {
240
			throw new \Exception($e->getMessage());
241
		}
242
243
		// update all shipped apps
244
		$this->checkAppsRequirements();
245
		$this->doAppUpgrade();
246
247
		// Update the appfetchers version so it downloads the correct list from the appstore
248
		\OC::$server->getAppFetcher()->setVersion($currentVersion);
249
250
		// upgrade appstore apps
251
		$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
252
		$this->upgradeAppStoreApps(\OC_App::$autoDisabledApps, true);
253
254
		// install new shipped apps on upgrade
255
		OC_App::loadApps(['authentication']);
256
		$errors = Installer::installShippedApps(true);
257
		foreach ($errors as $appId => $exception) {
258
			/** @var \Exception $exception */
259
			$this->log->logException($exception, ['app' => $appId]);
260
			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
261
		}
262
263
		// post-upgrade repairs
264
		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
265
		$repair->run();
266
267
		//Invalidate update feed
268
		$this->config->setAppValue('core', 'lastupdatedat', 0);
269
270
		// Check for code integrity if not disabled
271
		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272
			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273
			$this->checker->runInstanceVerification();
274
			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
275
		}
276
277
		// only set the final version if everything went well
278
		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
279
		$this->config->setAppValue('core', 'vendor', $this->getVendor());
280
	}
281
282
	protected function doCoreUpgrade() {
283
		$this->emit('\OC\Updater', 'dbUpgradeBefore');
284
285
		// execute core migrations
286
		$ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
287
		$ms->migrate();
288
289
		$this->emit('\OC\Updater', 'dbUpgrade');
290
	}
291
292
	/**
293
	 * @param string $version the oc version to check app compatibility with
294
	 */
295
	protected function checkAppUpgrade($version) {
296
		$apps = \OC_App::getEnabledApps();
297
		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
298
299
		$appManager = \OC::$server->getAppManager();
300
		foreach ($apps as $appId) {
301
			$info = \OC_App::getAppInfo($appId);
0 ignored issues
show
Deprecated Code introduced by
The function OC_App::getAppInfo() has been deprecated: 14.0.0 use \OC::$server->getAppManager()->getAppInfo() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

301
			$info = /** @scrutinizer ignore-deprecated */ \OC_App::getAppInfo($appId);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
302
			$compatible = \OC_App::isAppCompatible($version, $info);
0 ignored issues
show
Bug introduced by
It seems like $info can also be of type null; however, parameter $appInfo of OC_App::isAppCompatible() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

302
			$compatible = \OC_App::isAppCompatible($version, /** @scrutinizer ignore-type */ $info);
Loading history...
303
			$isShipped = $appManager->isShipped($appId);
304
305
			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
306
				/**
307
				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
308
				 * are not possible anymore within it. - Consider this when touching the code.
309
				 * @link https://github.com/owncloud/core/issues/10980
310
				 * @see \OC_App::updateApp
311
				 */
312
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
0 ignored issues
show
Bug introduced by
Are you sure OC_App::getAppPath($appId) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

312
				if (file_exists(/** @scrutinizer ignore-type */ \OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
Loading history...
313
					$this->includePreUpdate($appId);
314
				}
315
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
316
					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
0 ignored issues
show
Bug introduced by
The method simulateUpdateDbFromStructure() does not exist on OC_DB. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

317
					\OC_DB::/** @scrutinizer ignore-call */ 
318
             simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
318
				}
319
			}
320
		}
321
322
		$this->emit('\OC\Updater', 'appUpgradeCheck');
323
	}
324
325
	/**
326
	 * Includes the pre-update file. Done here to prevent namespace mixups.
327
	 * @param string $appId
328
	 */
329
	private function includePreUpdate($appId) {
330
		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
0 ignored issues
show
Bug introduced by
Are you sure OC_App::getAppPath($appId) of type false|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

330
		include /** @scrutinizer ignore-type */ \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
Loading history...
331
	}
332
333
	/**
334
	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
335
	 * (types authentication, filesystem, logging, in that order) afterwards.
336
	 *
337
	 * @throws NeedsUpdateException
338
	 */
339
	protected function doAppUpgrade() {
340
		$apps = \OC_App::getEnabledApps();
341
		$priorityTypes = array('authentication', 'filesystem', 'logging');
342
		$pseudoOtherType = 'other';
343
		$stacks = array($pseudoOtherType => array());
344
345
		foreach ($apps as $appId) {
346
			$priorityType = false;
347
			foreach ($priorityTypes as $type) {
348
				if(!isset($stacks[$type])) {
349
					$stacks[$type] = array();
350
				}
351
				if (\OC_App::isType($appId, [$type])) {
352
					$stacks[$type][] = $appId;
353
					$priorityType = true;
354
					break;
355
				}
356
			}
357
			if (!$priorityType) {
358
				$stacks[$pseudoOtherType][] = $appId;
359
			}
360
		}
361
		foreach ($stacks as $type => $stack) {
362
			foreach ($stack as $appId) {
363
				if (\OC_App::shouldUpgrade($appId)) {
364
					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
0 ignored issues
show
Deprecated Code introduced by
The function OC_App::getAppVersion() has been deprecated: 14.0.0 use \OC::$server->getAppManager()->getAppVersion() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

364
					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, /** @scrutinizer ignore-deprecated */ \OC_App::getAppVersion($appId)]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
365
					\OC_App::updateApp($appId);
366
					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
0 ignored issues
show
Deprecated Code introduced by
The function OC_App::getAppVersion() has been deprecated: 14.0.0 use \OC::$server->getAppManager()->getAppVersion() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

366
					$this->emit('\OC\Updater', 'appUpgrade', [$appId, /** @scrutinizer ignore-deprecated */ \OC_App::getAppVersion($appId)]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
367
				}
368
				if($type !== $pseudoOtherType) {
369
					// load authentication, filesystem and logging apps after
370
					// upgrading them. Other apps my need to rely on modifying
371
					// user and/or filesystem aspects.
372
					\OC_App::loadApp($appId);
373
				}
374
			}
375
		}
376
	}
377
378
	/**
379
	 * check if the current enabled apps are compatible with the current
380
	 * ownCloud version. disable them if not.
381
	 * This is important if you upgrade ownCloud and have non ported 3rd
382
	 * party apps installed.
383
	 *
384
	 * @return array
385
	 * @throws \Exception
386
	 */
387
	private function checkAppsRequirements() {
388
		$isCoreUpgrade = $this->isCodeUpgrade();
389
		$apps = OC_App::getEnabledApps();
390
		$version = implode('.', Util::getVersion());
391
		$disabledApps = [];
392
		$appManager = \OC::$server->getAppManager();
393
		foreach ($apps as $app) {
394
			// check if the app is compatible with this version of ownCloud
395
			$info = OC_App::getAppInfo($app);
0 ignored issues
show
Deprecated Code introduced by
The function OC_App::getAppInfo() has been deprecated: 14.0.0 use \OC::$server->getAppManager()->getAppInfo() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

395
			$info = /** @scrutinizer ignore-deprecated */ OC_App::getAppInfo($app);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
396
			if($info === null || !OC_App::isAppCompatible($version, $info)) {
397
				if ($appManager->isShipped($app)) {
398
					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
399
				}
400
				\OC::$server->getAppManager()->disableApp($app);
401
				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
402
			}
403
			// no need to disable any app in case this is a non-core upgrade
404
			if (!$isCoreUpgrade) {
405
				continue;
406
			}
407
			// shipped apps will remain enabled
408
			if ($appManager->isShipped($app)) {
409
				continue;
410
			}
411
			// authentication and session apps will remain enabled as well
412
			if (OC_App::isType($app, ['session', 'authentication'])) {
413
				continue;
414
			}
415
		}
416
		return $disabledApps;
417
	}
418
419
	/**
420
	 * @return bool
421
	 */
422
	private function isCodeUpgrade() {
423
		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
424
		$currentVersion = implode('.', Util::getVersion());
425
		if (version_compare($currentVersion, $installedVersion, '>')) {
426
			return true;
427
		}
428
		return false;
429
	}
430
431
	/**
432
	 * @param array $disabledApps
433
	 * @param bool $reenable
434
	 * @throws \Exception
435
	 */
436
	private function upgradeAppStoreApps(array $disabledApps, $reenable = false) {
437
		foreach($disabledApps as $app) {
438
			try {
439
				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
440
				if ($this->installer->isUpdateAvailable($app)) {
441
					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
442
					$this->installer->updateAppstoreApp($app);
443
				}
444
				$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
445
446
				if ($reenable) {
447
					$ocApp = new \OC_App();
448
					$ocApp->enable($app);
449
				}
450
			} catch (\Exception $ex) {
451
				$this->log->logException($ex, ['app' => 'core']);
452
			}
453
		}
454
	}
455
456
	/**
457
	 * Forward messages emitted by the repair routine
458
	 */
459
	private function emitRepairEvents() {
460
		$dispatcher = \OC::$server->getEventDispatcher();
461
		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
462
			if ($event instanceof GenericEvent) {
463
				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
464
			}
465
		});
466
		$dispatcher->addListener('\OC\Repair::error', function ($event) {
467
			if ($event instanceof GenericEvent) {
468
				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
469
			}
470
		});
471
		$dispatcher->addListener('\OC\Repair::info', function ($event) {
472
			if ($event instanceof GenericEvent) {
473
				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
474
			}
475
		});
476
		$dispatcher->addListener('\OC\Repair::step', function ($event) {
477
			if ($event instanceof GenericEvent) {
478
				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
479
			}
480
		});
481
	}
482
483
	private function logAllEvents() {
484
		$log = $this->log;
485
486
		$dispatcher = \OC::$server->getEventDispatcher();
487
		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
488
			if (!$event instanceof GenericEvent) {
489
				return;
490
			}
491
			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
		});
493
		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
494
			if (!$event instanceof GenericEvent) {
495
				return;
496
			}
497
			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
498
		});
499
500
		$repairListener = function($event) use ($log) {
501
			if (!$event instanceof GenericEvent) {
502
				return;
503
			}
504
			switch ($event->getSubject()) {
505
				case '\OC\Repair::startProgress':
506
					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
507
					break;
508
				case '\OC\Repair::advance':
509
					$desc = $event->getArgument(1);
510
					if (empty($desc)) {
511
						$desc = '';
512
					}
513
					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
514
515
					break;
516
				case '\OC\Repair::finishProgress':
517
					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
518
					break;
519
				case '\OC\Repair::step':
520
					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
521
					break;
522
				case '\OC\Repair::info':
523
					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
524
					break;
525
				case '\OC\Repair::warning':
526
					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
527
					break;
528
				case '\OC\Repair::error':
529
					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
530
					break;
531
			}
532
		};
533
534
		$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
535
		$dispatcher->addListener('\OC\Repair::advance', $repairListener);
536
		$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
537
		$dispatcher->addListener('\OC\Repair::step', $repairListener);
538
		$dispatcher->addListener('\OC\Repair::info', $repairListener);
539
		$dispatcher->addListener('\OC\Repair::warning', $repairListener);
540
		$dispatcher->addListener('\OC\Repair::error', $repairListener);
541
542
543
		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
544
			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
545
		});
546
		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
547
			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
548
		});
549
		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
550
			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
551
		});
552
		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
553
			if ($success) {
554
				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
555
			} else {
556
				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
557
			}
558
		});
559
		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
560
			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
561
		});
562
		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
563
			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
564
		});
565
		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
566
			$log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
567
		});
568
		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
569
			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
570
		});
571
		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
572
			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
573
		});
574
		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
575
			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
		});
577
		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
578
			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
579
		});
580
		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
581
			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
582
		});
583
		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
584
			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
585
		});
586
		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
587
			$log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
588
		});
589
		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
590
			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
591
		});
592
		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
593
			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
594
		});
595
		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
596
			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
597
		});
598
		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
599
			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
600
		});
601
		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
602
			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
603
		});
604
		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
605
			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
606
		});
607
		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
608
			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
609
		});
610
		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
611
			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
612
		});
613
614
	}
615
616
}
617
618