Completed
Pull Request — master (#7956)
by Morris
35:37 queued 15:27
created
lib/private/Updater.php 1 patch
Indentation   +579 added lines, -579 removed lines patch added patch discarded remove patch
@@ -54,585 +54,585 @@
 block discarded – undo
54 54
  */
55 55
 class Updater extends BasicEmitter {
56 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
-	/** @var bool */
70
-	private $skip3rdPartyAppsDisable;
71
-
72
-	private $logLevelNames = [
73
-		0 => 'Debug',
74
-		1 => 'Info',
75
-		2 => 'Warning',
76
-		3 => 'Error',
77
-		4 => 'Fatal',
78
-	];
79
-
80
-	/**
81
-	 * @param IConfig $config
82
-	 * @param Checker $checker
83
-	 * @param ILogger $log
84
-	 * @param Installer $installer
85
-	 */
86
-	public function __construct(IConfig $config,
87
-								Checker $checker,
88
-								ILogger $log = null,
89
-								Installer $installer) {
90
-		$this->log = $log;
91
-		$this->config = $config;
92
-		$this->checker = $checker;
93
-		$this->installer = $installer;
94
-
95
-		// If at least PHP 7.0.0 is used we don't need to disable apps as we catch
96
-		// fatal errors and exceptions and disable the app just instead.
97
-		if(version_compare(phpversion(), '7.0.0', '>=')) {
98
-			$this->skip3rdPartyAppsDisable = true;
99
-		}
100
-	}
101
-
102
-	/**
103
-	 * Sets whether the update disables 3rd party apps.
104
-	 * This can be set to true to skip the disable.
105
-	 *
106
-	 * @param bool $flag false to not disable, true otherwise
107
-	 */
108
-	public function setSkip3rdPartyAppsDisable($flag) {
109
-		$this->skip3rdPartyAppsDisable = $flag;
110
-	}
111
-
112
-	/**
113
-	 * runs the update actions in maintenance mode, does not upgrade the source files
114
-	 * except the main .htaccess file
115
-	 *
116
-	 * @return bool true if the operation succeeded, false otherwise
117
-	 */
118
-	public function upgrade() {
119
-		$this->emitRepairEvents();
120
-		$this->logAllEvents();
121
-
122
-		$logLevel = $this->config->getSystemValue('loglevel', Util::WARN);
123
-		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
124
-		$this->config->setSystemValue('loglevel', Util::DEBUG);
125
-
126
-		$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
127
-
128
-		if(!$wasMaintenanceModeEnabled) {
129
-			$this->config->setSystemValue('maintenance', true);
130
-			$this->emit('\OC\Updater', 'maintenanceEnabled');
131
-		}
132
-
133
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
134
-		$currentVersion = implode('.', \OCP\Util::getVersion());
135
-		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
136
-
137
-		$success = true;
138
-		try {
139
-			$this->doUpgrade($currentVersion, $installedVersion);
140
-		} catch (HintException $exception) {
141
-			$this->log->logException($exception, ['app' => 'core']);
142
-			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
143
-			$success = false;
144
-		} catch (\Exception $exception) {
145
-			$this->log->logException($exception, ['app' => 'core']);
146
-			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
147
-			$success = false;
148
-		}
149
-
150
-		$this->emit('\OC\Updater', 'updateEnd', array($success));
151
-
152
-		if(!$wasMaintenanceModeEnabled && $success) {
153
-			$this->config->setSystemValue('maintenance', false);
154
-			$this->emit('\OC\Updater', 'maintenanceDisabled');
155
-		} else {
156
-			$this->emit('\OC\Updater', 'maintenanceActive');
157
-		}
158
-
159
-		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
160
-		$this->config->setSystemValue('loglevel', $logLevel);
161
-		$this->config->setSystemValue('installed', true);
162
-
163
-		return $success;
164
-	}
165
-
166
-	/**
167
-	 * Return version from which this version is allowed to upgrade from
168
-	 *
169
-	 * @return array allowed previous versions per vendor
170
-	 */
171
-	private function getAllowedPreviousVersions() {
172
-		// this should really be a JSON file
173
-		require \OC::$SERVERROOT . '/version.php';
174
-		/** @var array $OC_VersionCanBeUpgradedFrom */
175
-		return $OC_VersionCanBeUpgradedFrom;
176
-	}
177
-
178
-	/**
179
-	 * Return vendor from which this version was published
180
-	 *
181
-	 * @return string Get the vendor
182
-	 */
183
-	private function getVendor() {
184
-		// this should really be a JSON file
185
-		require \OC::$SERVERROOT . '/version.php';
186
-		/** @var string $vendor */
187
-		return (string) $vendor;
188
-	}
189
-
190
-	/**
191
-	 * Whether an upgrade to a specified version is possible
192
-	 * @param string $oldVersion
193
-	 * @param string $newVersion
194
-	 * @param array $allowedPreviousVersions
195
-	 * @return bool
196
-	 */
197
-	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
198
-		$version = explode('.', $oldVersion);
199
-		$majorMinor = $version[0] . '.' . $version[1];
200
-
201
-		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
202
-
203
-		// Vendor was not set correctly on install, so we have to white-list known versions
204
-		if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
205
-			$currentVendor = 'owncloud';
206
-		}
207
-
208
-		if ($currentVendor === 'nextcloud') {
209
-			return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
210
-				&& (version_compare($oldVersion, $newVersion, '<=') ||
211
-					$this->config->getSystemValue('debug', false));
212
-		}
213
-
214
-		// Check if the instance can be migrated
215
-		return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
216
-			isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
217
-	}
218
-
219
-	/**
220
-	 * runs the update actions in maintenance mode, does not upgrade the source files
221
-	 * except the main .htaccess file
222
-	 *
223
-	 * @param string $currentVersion current version to upgrade to
224
-	 * @param string $installedVersion previous version from which to upgrade from
225
-	 *
226
-	 * @throws \Exception
227
-	 */
228
-	private function doUpgrade($currentVersion, $installedVersion) {
229
-		// Stop update if the update is over several major versions
230
-		$allowedPreviousVersions = $this->getAllowedPreviousVersions();
231
-		if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
232
-			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
233
-		}
234
-
235
-		// Update .htaccess files
236
-		try {
237
-			Setup::updateHtaccess();
238
-			Setup::protectDataDirectory();
239
-		} catch (\Exception $e) {
240
-			throw new \Exception($e->getMessage());
241
-		}
242
-
243
-		// create empty file in data dir, so we can later find
244
-		// out that this is indeed an ownCloud data directory
245
-		// (in case it didn't exist before)
246
-		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
247
-
248
-		// pre-upgrade repairs
249
-		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
250
-		$repair->run();
251
-
252
-		$this->doCoreUpgrade();
253
-
254
-		try {
255
-			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
256
-			Setup::installBackgroundJobs();
257
-		} catch (\Exception $e) {
258
-			throw new \Exception($e->getMessage());
259
-		}
260
-
261
-		// update all shipped apps
262
-		$this->checkAppsRequirements();
263
-		$this->doAppUpgrade();
264
-
265
-		// Update the appfetchers version so it downloads the correct list from the appstore
266
-		\OC::$server->getAppFetcher()->setVersion($currentVersion);
267
-
268
-		// upgrade appstore apps
269
-		$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
270
-
271
-		// install new shipped apps on upgrade
272
-		OC_App::loadApps('authentication');
273
-		$errors = Installer::installShippedApps(true);
274
-		foreach ($errors as $appId => $exception) {
275
-			/** @var \Exception $exception */
276
-			$this->log->logException($exception, ['app' => $appId]);
277
-			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
278
-		}
279
-
280
-		// post-upgrade repairs
281
-		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
282
-		$repair->run();
283
-
284
-		//Invalidate update feed
285
-		$this->config->setAppValue('core', 'lastupdatedat', 0);
286
-
287
-		// Check for code integrity if not disabled
288
-		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
289
-			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
290
-			$this->checker->runInstanceVerification();
291
-			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
292
-		}
293
-
294
-		// only set the final version if everything went well
295
-		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
296
-		$this->config->setAppValue('core', 'vendor', $this->getVendor());
297
-	}
298
-
299
-	protected function doCoreUpgrade() {
300
-		$this->emit('\OC\Updater', 'dbUpgradeBefore');
301
-
302
-		// execute core migrations
303
-		$ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
304
-		$ms->migrate();
305
-
306
-		$this->emit('\OC\Updater', 'dbUpgrade');
307
-	}
308
-
309
-	/**
310
-	 * @param string $version the oc version to check app compatibility with
311
-	 */
312
-	protected function checkAppUpgrade($version) {
313
-		$apps = \OC_App::getEnabledApps();
314
-		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
315
-
316
-		$appManager = \OC::$server->getAppManager();
317
-		foreach ($apps as $appId) {
318
-			$info = \OC_App::getAppInfo($appId);
319
-			$compatible = \OC_App::isAppCompatible($version, $info);
320
-			$isShipped = $appManager->isShipped($appId);
321
-
322
-			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
323
-				/**
324
-				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
325
-				 * are not possible anymore within it. - Consider this when touching the code.
326
-				 * @link https://github.com/owncloud/core/issues/10980
327
-				 * @see \OC_App::updateApp
328
-				 */
329
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
330
-					$this->includePreUpdate($appId);
331
-				}
332
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
333
-					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
334
-					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
335
-				}
336
-			}
337
-		}
338
-
339
-		$this->emit('\OC\Updater', 'appUpgradeCheck');
340
-	}
341
-
342
-	/**
343
-	 * Includes the pre-update file. Done here to prevent namespace mixups.
344
-	 * @param string $appId
345
-	 */
346
-	private function includePreUpdate($appId) {
347
-		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
348
-	}
349
-
350
-	/**
351
-	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
352
-	 * (types authentication, filesystem, logging, in that order) afterwards.
353
-	 *
354
-	 * @throws NeedsUpdateException
355
-	 */
356
-	protected function doAppUpgrade() {
357
-		$apps = \OC_App::getEnabledApps();
358
-		$priorityTypes = array('authentication', 'filesystem', 'logging');
359
-		$pseudoOtherType = 'other';
360
-		$stacks = array($pseudoOtherType => array());
361
-
362
-		foreach ($apps as $appId) {
363
-			$priorityType = false;
364
-			foreach ($priorityTypes as $type) {
365
-				if(!isset($stacks[$type])) {
366
-					$stacks[$type] = array();
367
-				}
368
-				if (\OC_App::isType($appId, $type)) {
369
-					$stacks[$type][] = $appId;
370
-					$priorityType = true;
371
-					break;
372
-				}
373
-			}
374
-			if (!$priorityType) {
375
-				$stacks[$pseudoOtherType][] = $appId;
376
-			}
377
-		}
378
-		foreach ($stacks as $type => $stack) {
379
-			foreach ($stack as $appId) {
380
-				if (\OC_App::shouldUpgrade($appId)) {
381
-					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
382
-					\OC_App::updateApp($appId);
383
-					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
384
-				}
385
-				if($type !== $pseudoOtherType) {
386
-					// load authentication, filesystem and logging apps after
387
-					// upgrading them. Other apps my need to rely on modifying
388
-					// user and/or filesystem aspects.
389
-					\OC_App::loadApp($appId);
390
-				}
391
-			}
392
-		}
393
-	}
394
-
395
-	/**
396
-	 * check if the current enabled apps are compatible with the current
397
-	 * ownCloud version. disable them if not.
398
-	 * This is important if you upgrade ownCloud and have non ported 3rd
399
-	 * party apps installed.
400
-	 *
401
-	 * @return array
402
-	 * @throws \Exception
403
-	 */
404
-	private function checkAppsRequirements() {
405
-		$isCoreUpgrade = $this->isCodeUpgrade();
406
-		$apps = OC_App::getEnabledApps();
407
-		$version = Util::getVersion();
408
-		$disabledApps = [];
409
-		$appManager = \OC::$server->getAppManager();
410
-		foreach ($apps as $app) {
411
-			// check if the app is compatible with this version of ownCloud
412
-			$info = OC_App::getAppInfo($app);
413
-			if(!OC_App::isAppCompatible($version, $info)) {
414
-				if ($appManager->isShipped($app)) {
415
-					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
416
-				}
417
-				OC_App::disable($app);
418
-				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
419
-			}
420
-			// no need to disable any app in case this is a non-core upgrade
421
-			if (!$isCoreUpgrade) {
422
-				continue;
423
-			}
424
-			// shipped apps will remain enabled
425
-			if ($appManager->isShipped($app)) {
426
-				continue;
427
-			}
428
-			// authentication and session apps will remain enabled as well
429
-			if (OC_App::isType($app, ['session', 'authentication'])) {
430
-				continue;
431
-			}
432
-
433
-			// disable any other 3rd party apps if not overriden
434
-			if(!$this->skip3rdPartyAppsDisable) {
435
-				\OC_App::disable($app);
436
-				$disabledApps[]= $app;
437
-				$this->emit('\OC\Updater', 'thirdPartyAppDisabled', array($app));
438
-			};
439
-		}
440
-		return $disabledApps;
441
-	}
442
-
443
-	/**
444
-	 * @return bool
445
-	 */
446
-	private function isCodeUpgrade() {
447
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
448
-		$currentVersion = implode('.', Util::getVersion());
449
-		if (version_compare($currentVersion, $installedVersion, '>')) {
450
-			return true;
451
-		}
452
-		return false;
453
-	}
454
-
455
-	/**
456
-	 * @param array $disabledApps
457
-	 * @throws \Exception
458
-	 */
459
-	private function upgradeAppStoreApps(array $disabledApps) {
460
-		foreach($disabledApps as $app) {
461
-			try {
462
-				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
463
-				if ($this->installer->isUpdateAvailable($app)) {
464
-					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
465
-					$this->installer->updateAppstoreApp($app);
466
-				}
467
-				$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
468
-			} catch (\Exception $ex) {
469
-				$this->log->logException($ex, ['app' => 'core']);
470
-			}
471
-		}
472
-	}
473
-
474
-	/**
475
-	 * Forward messages emitted by the repair routine
476
-	 */
477
-	private function emitRepairEvents() {
478
-		$dispatcher = \OC::$server->getEventDispatcher();
479
-		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
480
-			if ($event instanceof GenericEvent) {
481
-				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
482
-			}
483
-		});
484
-		$dispatcher->addListener('\OC\Repair::error', function ($event) {
485
-			if ($event instanceof GenericEvent) {
486
-				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
487
-			}
488
-		});
489
-		$dispatcher->addListener('\OC\Repair::info', function ($event) {
490
-			if ($event instanceof GenericEvent) {
491
-				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
492
-			}
493
-		});
494
-		$dispatcher->addListener('\OC\Repair::step', function ($event) {
495
-			if ($event instanceof GenericEvent) {
496
-				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
497
-			}
498
-		});
499
-	}
500
-
501
-	private function logAllEvents() {
502
-		$log = $this->log;
503
-
504
-		$dispatcher = \OC::$server->getEventDispatcher();
505
-		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
506
-			if (!$event instanceof GenericEvent) {
507
-				return;
508
-			}
509
-			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
510
-		});
511
-		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
512
-			if (!$event instanceof GenericEvent) {
513
-				return;
514
-			}
515
-			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
516
-		});
517
-
518
-		$repairListener = function($event) use ($log) {
519
-			if (!$event instanceof GenericEvent) {
520
-				return;
521
-			}
522
-			switch ($event->getSubject()) {
523
-				case '\OC\Repair::startProgress':
524
-					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
525
-					break;
526
-				case '\OC\Repair::advance':
527
-					$desc = $event->getArgument(1);
528
-					if (empty($desc)) {
529
-						$desc = '';
530
-					}
531
-					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
532
-
533
-					break;
534
-				case '\OC\Repair::finishProgress':
535
-					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
536
-					break;
537
-				case '\OC\Repair::step':
538
-					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
539
-					break;
540
-				case '\OC\Repair::info':
541
-					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
542
-					break;
543
-				case '\OC\Repair::warning':
544
-					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
545
-					break;
546
-				case '\OC\Repair::error':
547
-					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
548
-					break;
549
-			}
550
-		};
551
-
552
-		$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
553
-		$dispatcher->addListener('\OC\Repair::advance', $repairListener);
554
-		$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
555
-		$dispatcher->addListener('\OC\Repair::step', $repairListener);
556
-		$dispatcher->addListener('\OC\Repair::info', $repairListener);
557
-		$dispatcher->addListener('\OC\Repair::warning', $repairListener);
558
-		$dispatcher->addListener('\OC\Repair::error', $repairListener);
559
-
560
-
561
-		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
562
-			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
563
-		});
564
-		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
565
-			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
566
-		});
567
-		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
568
-			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
569
-		});
570
-		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
571
-			if ($success) {
572
-				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
573
-			} else {
574
-				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
575
-			}
576
-		});
577
-		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
578
-			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
579
-		});
580
-		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
581
-			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
582
-		});
583
-		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
584
-			$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']);
585
-		});
586
-		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
587
-			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
588
-		});
589
-		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
590
-			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
591
-		});
592
-		$this->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use ($log) {
593
-			$log->info('\OC\Updater::thirdPartyAppDisabled: Disabled 3rd-party app: ' . $app, ['app' => 'updater']);
594
-		});
595
-		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
596
-			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
597
-		});
598
-		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
599
-			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
600
-		});
601
-		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
602
-			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
603
-		});
604
-		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
605
-			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
606
-		});
607
-		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
608
-			$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']);
609
-		});
610
-		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
611
-			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
612
-		});
613
-		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
614
-			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
615
-		});
616
-		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
617
-			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
618
-		});
619
-		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
620
-			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
621
-		});
622
-		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
623
-			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
624
-		});
625
-		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
626
-			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
627
-		});
628
-		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
629
-			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
630
-		});
631
-		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
632
-			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
633
-		});
634
-
635
-	}
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
+    /** @var bool */
70
+    private $skip3rdPartyAppsDisable;
71
+
72
+    private $logLevelNames = [
73
+        0 => 'Debug',
74
+        1 => 'Info',
75
+        2 => 'Warning',
76
+        3 => 'Error',
77
+        4 => 'Fatal',
78
+    ];
79
+
80
+    /**
81
+     * @param IConfig $config
82
+     * @param Checker $checker
83
+     * @param ILogger $log
84
+     * @param Installer $installer
85
+     */
86
+    public function __construct(IConfig $config,
87
+                                Checker $checker,
88
+                                ILogger $log = null,
89
+                                Installer $installer) {
90
+        $this->log = $log;
91
+        $this->config = $config;
92
+        $this->checker = $checker;
93
+        $this->installer = $installer;
94
+
95
+        // If at least PHP 7.0.0 is used we don't need to disable apps as we catch
96
+        // fatal errors and exceptions and disable the app just instead.
97
+        if(version_compare(phpversion(), '7.0.0', '>=')) {
98
+            $this->skip3rdPartyAppsDisable = true;
99
+        }
100
+    }
101
+
102
+    /**
103
+     * Sets whether the update disables 3rd party apps.
104
+     * This can be set to true to skip the disable.
105
+     *
106
+     * @param bool $flag false to not disable, true otherwise
107
+     */
108
+    public function setSkip3rdPartyAppsDisable($flag) {
109
+        $this->skip3rdPartyAppsDisable = $flag;
110
+    }
111
+
112
+    /**
113
+     * runs the update actions in maintenance mode, does not upgrade the source files
114
+     * except the main .htaccess file
115
+     *
116
+     * @return bool true if the operation succeeded, false otherwise
117
+     */
118
+    public function upgrade() {
119
+        $this->emitRepairEvents();
120
+        $this->logAllEvents();
121
+
122
+        $logLevel = $this->config->getSystemValue('loglevel', Util::WARN);
123
+        $this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
124
+        $this->config->setSystemValue('loglevel', Util::DEBUG);
125
+
126
+        $wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
127
+
128
+        if(!$wasMaintenanceModeEnabled) {
129
+            $this->config->setSystemValue('maintenance', true);
130
+            $this->emit('\OC\Updater', 'maintenanceEnabled');
131
+        }
132
+
133
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
134
+        $currentVersion = implode('.', \OCP\Util::getVersion());
135
+        $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
136
+
137
+        $success = true;
138
+        try {
139
+            $this->doUpgrade($currentVersion, $installedVersion);
140
+        } catch (HintException $exception) {
141
+            $this->log->logException($exception, ['app' => 'core']);
142
+            $this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
143
+            $success = false;
144
+        } catch (\Exception $exception) {
145
+            $this->log->logException($exception, ['app' => 'core']);
146
+            $this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
147
+            $success = false;
148
+        }
149
+
150
+        $this->emit('\OC\Updater', 'updateEnd', array($success));
151
+
152
+        if(!$wasMaintenanceModeEnabled && $success) {
153
+            $this->config->setSystemValue('maintenance', false);
154
+            $this->emit('\OC\Updater', 'maintenanceDisabled');
155
+        } else {
156
+            $this->emit('\OC\Updater', 'maintenanceActive');
157
+        }
158
+
159
+        $this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
160
+        $this->config->setSystemValue('loglevel', $logLevel);
161
+        $this->config->setSystemValue('installed', true);
162
+
163
+        return $success;
164
+    }
165
+
166
+    /**
167
+     * Return version from which this version is allowed to upgrade from
168
+     *
169
+     * @return array allowed previous versions per vendor
170
+     */
171
+    private function getAllowedPreviousVersions() {
172
+        // this should really be a JSON file
173
+        require \OC::$SERVERROOT . '/version.php';
174
+        /** @var array $OC_VersionCanBeUpgradedFrom */
175
+        return $OC_VersionCanBeUpgradedFrom;
176
+    }
177
+
178
+    /**
179
+     * Return vendor from which this version was published
180
+     *
181
+     * @return string Get the vendor
182
+     */
183
+    private function getVendor() {
184
+        // this should really be a JSON file
185
+        require \OC::$SERVERROOT . '/version.php';
186
+        /** @var string $vendor */
187
+        return (string) $vendor;
188
+    }
189
+
190
+    /**
191
+     * Whether an upgrade to a specified version is possible
192
+     * @param string $oldVersion
193
+     * @param string $newVersion
194
+     * @param array $allowedPreviousVersions
195
+     * @return bool
196
+     */
197
+    public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
198
+        $version = explode('.', $oldVersion);
199
+        $majorMinor = $version[0] . '.' . $version[1];
200
+
201
+        $currentVendor = $this->config->getAppValue('core', 'vendor', '');
202
+
203
+        // Vendor was not set correctly on install, so we have to white-list known versions
204
+        if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
205
+            $currentVendor = 'owncloud';
206
+        }
207
+
208
+        if ($currentVendor === 'nextcloud') {
209
+            return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
210
+                && (version_compare($oldVersion, $newVersion, '<=') ||
211
+                    $this->config->getSystemValue('debug', false));
212
+        }
213
+
214
+        // Check if the instance can be migrated
215
+        return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
216
+            isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
217
+    }
218
+
219
+    /**
220
+     * runs the update actions in maintenance mode, does not upgrade the source files
221
+     * except the main .htaccess file
222
+     *
223
+     * @param string $currentVersion current version to upgrade to
224
+     * @param string $installedVersion previous version from which to upgrade from
225
+     *
226
+     * @throws \Exception
227
+     */
228
+    private function doUpgrade($currentVersion, $installedVersion) {
229
+        // Stop update if the update is over several major versions
230
+        $allowedPreviousVersions = $this->getAllowedPreviousVersions();
231
+        if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
232
+            throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
233
+        }
234
+
235
+        // Update .htaccess files
236
+        try {
237
+            Setup::updateHtaccess();
238
+            Setup::protectDataDirectory();
239
+        } catch (\Exception $e) {
240
+            throw new \Exception($e->getMessage());
241
+        }
242
+
243
+        // create empty file in data dir, so we can later find
244
+        // out that this is indeed an ownCloud data directory
245
+        // (in case it didn't exist before)
246
+        file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
247
+
248
+        // pre-upgrade repairs
249
+        $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
250
+        $repair->run();
251
+
252
+        $this->doCoreUpgrade();
253
+
254
+        try {
255
+            // TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
256
+            Setup::installBackgroundJobs();
257
+        } catch (\Exception $e) {
258
+            throw new \Exception($e->getMessage());
259
+        }
260
+
261
+        // update all shipped apps
262
+        $this->checkAppsRequirements();
263
+        $this->doAppUpgrade();
264
+
265
+        // Update the appfetchers version so it downloads the correct list from the appstore
266
+        \OC::$server->getAppFetcher()->setVersion($currentVersion);
267
+
268
+        // upgrade appstore apps
269
+        $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
270
+
271
+        // install new shipped apps on upgrade
272
+        OC_App::loadApps('authentication');
273
+        $errors = Installer::installShippedApps(true);
274
+        foreach ($errors as $appId => $exception) {
275
+            /** @var \Exception $exception */
276
+            $this->log->logException($exception, ['app' => $appId]);
277
+            $this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
278
+        }
279
+
280
+        // post-upgrade repairs
281
+        $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
282
+        $repair->run();
283
+
284
+        //Invalidate update feed
285
+        $this->config->setAppValue('core', 'lastupdatedat', 0);
286
+
287
+        // Check for code integrity if not disabled
288
+        if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
289
+            $this->emit('\OC\Updater', 'startCheckCodeIntegrity');
290
+            $this->checker->runInstanceVerification();
291
+            $this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
292
+        }
293
+
294
+        // only set the final version if everything went well
295
+        $this->config->setSystemValue('version', implode('.', Util::getVersion()));
296
+        $this->config->setAppValue('core', 'vendor', $this->getVendor());
297
+    }
298
+
299
+    protected function doCoreUpgrade() {
300
+        $this->emit('\OC\Updater', 'dbUpgradeBefore');
301
+
302
+        // execute core migrations
303
+        $ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
304
+        $ms->migrate();
305
+
306
+        $this->emit('\OC\Updater', 'dbUpgrade');
307
+    }
308
+
309
+    /**
310
+     * @param string $version the oc version to check app compatibility with
311
+     */
312
+    protected function checkAppUpgrade($version) {
313
+        $apps = \OC_App::getEnabledApps();
314
+        $this->emit('\OC\Updater', 'appUpgradeCheckBefore');
315
+
316
+        $appManager = \OC::$server->getAppManager();
317
+        foreach ($apps as $appId) {
318
+            $info = \OC_App::getAppInfo($appId);
319
+            $compatible = \OC_App::isAppCompatible($version, $info);
320
+            $isShipped = $appManager->isShipped($appId);
321
+
322
+            if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
323
+                /**
324
+                 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
325
+                 * are not possible anymore within it. - Consider this when touching the code.
326
+                 * @link https://github.com/owncloud/core/issues/10980
327
+                 * @see \OC_App::updateApp
328
+                 */
329
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
330
+                    $this->includePreUpdate($appId);
331
+                }
332
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
333
+                    $this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
334
+                    \OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
335
+                }
336
+            }
337
+        }
338
+
339
+        $this->emit('\OC\Updater', 'appUpgradeCheck');
340
+    }
341
+
342
+    /**
343
+     * Includes the pre-update file. Done here to prevent namespace mixups.
344
+     * @param string $appId
345
+     */
346
+    private function includePreUpdate($appId) {
347
+        include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
348
+    }
349
+
350
+    /**
351
+     * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
352
+     * (types authentication, filesystem, logging, in that order) afterwards.
353
+     *
354
+     * @throws NeedsUpdateException
355
+     */
356
+    protected function doAppUpgrade() {
357
+        $apps = \OC_App::getEnabledApps();
358
+        $priorityTypes = array('authentication', 'filesystem', 'logging');
359
+        $pseudoOtherType = 'other';
360
+        $stacks = array($pseudoOtherType => array());
361
+
362
+        foreach ($apps as $appId) {
363
+            $priorityType = false;
364
+            foreach ($priorityTypes as $type) {
365
+                if(!isset($stacks[$type])) {
366
+                    $stacks[$type] = array();
367
+                }
368
+                if (\OC_App::isType($appId, $type)) {
369
+                    $stacks[$type][] = $appId;
370
+                    $priorityType = true;
371
+                    break;
372
+                }
373
+            }
374
+            if (!$priorityType) {
375
+                $stacks[$pseudoOtherType][] = $appId;
376
+            }
377
+        }
378
+        foreach ($stacks as $type => $stack) {
379
+            foreach ($stack as $appId) {
380
+                if (\OC_App::shouldUpgrade($appId)) {
381
+                    $this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
382
+                    \OC_App::updateApp($appId);
383
+                    $this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
384
+                }
385
+                if($type !== $pseudoOtherType) {
386
+                    // load authentication, filesystem and logging apps after
387
+                    // upgrading them. Other apps my need to rely on modifying
388
+                    // user and/or filesystem aspects.
389
+                    \OC_App::loadApp($appId);
390
+                }
391
+            }
392
+        }
393
+    }
394
+
395
+    /**
396
+     * check if the current enabled apps are compatible with the current
397
+     * ownCloud version. disable them if not.
398
+     * This is important if you upgrade ownCloud and have non ported 3rd
399
+     * party apps installed.
400
+     *
401
+     * @return array
402
+     * @throws \Exception
403
+     */
404
+    private function checkAppsRequirements() {
405
+        $isCoreUpgrade = $this->isCodeUpgrade();
406
+        $apps = OC_App::getEnabledApps();
407
+        $version = Util::getVersion();
408
+        $disabledApps = [];
409
+        $appManager = \OC::$server->getAppManager();
410
+        foreach ($apps as $app) {
411
+            // check if the app is compatible with this version of ownCloud
412
+            $info = OC_App::getAppInfo($app);
413
+            if(!OC_App::isAppCompatible($version, $info)) {
414
+                if ($appManager->isShipped($app)) {
415
+                    throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
416
+                }
417
+                OC_App::disable($app);
418
+                $this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
419
+            }
420
+            // no need to disable any app in case this is a non-core upgrade
421
+            if (!$isCoreUpgrade) {
422
+                continue;
423
+            }
424
+            // shipped apps will remain enabled
425
+            if ($appManager->isShipped($app)) {
426
+                continue;
427
+            }
428
+            // authentication and session apps will remain enabled as well
429
+            if (OC_App::isType($app, ['session', 'authentication'])) {
430
+                continue;
431
+            }
432
+
433
+            // disable any other 3rd party apps if not overriden
434
+            if(!$this->skip3rdPartyAppsDisable) {
435
+                \OC_App::disable($app);
436
+                $disabledApps[]= $app;
437
+                $this->emit('\OC\Updater', 'thirdPartyAppDisabled', array($app));
438
+            };
439
+        }
440
+        return $disabledApps;
441
+    }
442
+
443
+    /**
444
+     * @return bool
445
+     */
446
+    private function isCodeUpgrade() {
447
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
448
+        $currentVersion = implode('.', Util::getVersion());
449
+        if (version_compare($currentVersion, $installedVersion, '>')) {
450
+            return true;
451
+        }
452
+        return false;
453
+    }
454
+
455
+    /**
456
+     * @param array $disabledApps
457
+     * @throws \Exception
458
+     */
459
+    private function upgradeAppStoreApps(array $disabledApps) {
460
+        foreach($disabledApps as $app) {
461
+            try {
462
+                $this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
463
+                if ($this->installer->isUpdateAvailable($app)) {
464
+                    $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
465
+                    $this->installer->updateAppstoreApp($app);
466
+                }
467
+                $this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
468
+            } catch (\Exception $ex) {
469
+                $this->log->logException($ex, ['app' => 'core']);
470
+            }
471
+        }
472
+    }
473
+
474
+    /**
475
+     * Forward messages emitted by the repair routine
476
+     */
477
+    private function emitRepairEvents() {
478
+        $dispatcher = \OC::$server->getEventDispatcher();
479
+        $dispatcher->addListener('\OC\Repair::warning', function ($event) {
480
+            if ($event instanceof GenericEvent) {
481
+                $this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
482
+            }
483
+        });
484
+        $dispatcher->addListener('\OC\Repair::error', function ($event) {
485
+            if ($event instanceof GenericEvent) {
486
+                $this->emit('\OC\Updater', 'repairError', $event->getArguments());
487
+            }
488
+        });
489
+        $dispatcher->addListener('\OC\Repair::info', function ($event) {
490
+            if ($event instanceof GenericEvent) {
491
+                $this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
492
+            }
493
+        });
494
+        $dispatcher->addListener('\OC\Repair::step', function ($event) {
495
+            if ($event instanceof GenericEvent) {
496
+                $this->emit('\OC\Updater', 'repairStep', $event->getArguments());
497
+            }
498
+        });
499
+    }
500
+
501
+    private function logAllEvents() {
502
+        $log = $this->log;
503
+
504
+        $dispatcher = \OC::$server->getEventDispatcher();
505
+        $dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
506
+            if (!$event instanceof GenericEvent) {
507
+                return;
508
+            }
509
+            $log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
510
+        });
511
+        $dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
512
+            if (!$event instanceof GenericEvent) {
513
+                return;
514
+            }
515
+            $log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
516
+        });
517
+
518
+        $repairListener = function($event) use ($log) {
519
+            if (!$event instanceof GenericEvent) {
520
+                return;
521
+            }
522
+            switch ($event->getSubject()) {
523
+                case '\OC\Repair::startProgress':
524
+                    $log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
525
+                    break;
526
+                case '\OC\Repair::advance':
527
+                    $desc = $event->getArgument(1);
528
+                    if (empty($desc)) {
529
+                        $desc = '';
530
+                    }
531
+                    $log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
532
+
533
+                    break;
534
+                case '\OC\Repair::finishProgress':
535
+                    $log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
536
+                    break;
537
+                case '\OC\Repair::step':
538
+                    $log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
539
+                    break;
540
+                case '\OC\Repair::info':
541
+                    $log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
542
+                    break;
543
+                case '\OC\Repair::warning':
544
+                    $log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
545
+                    break;
546
+                case '\OC\Repair::error':
547
+                    $log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
548
+                    break;
549
+            }
550
+        };
551
+
552
+        $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
553
+        $dispatcher->addListener('\OC\Repair::advance', $repairListener);
554
+        $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
555
+        $dispatcher->addListener('\OC\Repair::step', $repairListener);
556
+        $dispatcher->addListener('\OC\Repair::info', $repairListener);
557
+        $dispatcher->addListener('\OC\Repair::warning', $repairListener);
558
+        $dispatcher->addListener('\OC\Repair::error', $repairListener);
559
+
560
+
561
+        $this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
562
+            $log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
563
+        });
564
+        $this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
565
+            $log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
566
+        });
567
+        $this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
568
+            $log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
569
+        });
570
+        $this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
571
+            if ($success) {
572
+                $log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
573
+            } else {
574
+                $log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
575
+            }
576
+        });
577
+        $this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
578
+            $log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
579
+        });
580
+        $this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
581
+            $log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
582
+        });
583
+        $this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
584
+            $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']);
585
+        });
586
+        $this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
587
+            $log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
588
+        });
589
+        $this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
590
+            $log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
591
+        });
592
+        $this->listen('\OC\Updater', 'thirdPartyAppDisabled', function ($app) use ($log) {
593
+            $log->info('\OC\Updater::thirdPartyAppDisabled: Disabled 3rd-party app: ' . $app, ['app' => 'updater']);
594
+        });
595
+        $this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
596
+            $log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
597
+        });
598
+        $this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
599
+            $log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
600
+        });
601
+        $this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
602
+            $log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
603
+        });
604
+        $this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
605
+            $log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
606
+        });
607
+        $this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
608
+            $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']);
609
+        });
610
+        $this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
611
+            $log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
612
+        });
613
+        $this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
614
+            $log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
615
+        });
616
+        $this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
617
+            $log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
618
+        });
619
+        $this->listen('\OC\Updater', 'failure', function ($message) use($log) {
620
+            $log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
621
+        });
622
+        $this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
623
+            $log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
624
+        });
625
+        $this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
626
+            $log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
627
+        });
628
+        $this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
629
+            $log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
630
+        });
631
+        $this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
632
+            $log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
633
+        });
634
+
635
+    }
636 636
 
637 637
 }
638 638
 
Please login to merge, or discard this patch.