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