Completed
Pull Request — master (#9900)
by Morris
285:08 queued 261:24
created
lib/private/Updater.php 1 patch
Indentation   +557 added lines, -557 removed lines patch added patch discarded remove patch
@@ -55,563 +55,563 @@
 block discarded – undo
55 55
  */
56 56
 class Updater extends BasicEmitter {
57 57
 
58
-	/** @var ILogger $log */
59
-	private $log;
60
-
61
-	/** @var IConfig */
62
-	private $config;
63
-
64
-	/** @var Checker */
65
-	private $checker;
66
-
67
-	/** @var Installer */
68
-	private $installer;
69
-
70
-	/** @var IJobList */
71
-	private $jobList;
72
-
73
-	private $logLevelNames = [
74
-		0 => 'Debug',
75
-		1 => 'Info',
76
-		2 => 'Warning',
77
-		3 => 'Error',
78
-		4 => 'Fatal',
79
-	];
80
-
81
-	public function __construct(IConfig $config,
82
-								Checker $checker,
83
-								ILogger $log,
84
-								Installer $installer,
85
-								IJobList $jobList) {
86
-		$this->log = $log;
87
-		$this->config = $config;
88
-		$this->checker = $checker;
89
-		$this->installer = $installer;
90
-		$this->jobList = $jobList;
91
-	}
92
-
93
-	/**
94
-	 * runs the update actions in maintenance mode, does not upgrade the source files
95
-	 * except the main .htaccess file
96
-	 *
97
-	 * @return bool true if the operation succeeded, false otherwise
98
-	 */
99
-	public function upgrade() {
100
-		$this->emitRepairEvents();
101
-		$this->logAllEvents();
102
-
103
-		$logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
-		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
-		$this->config->setSystemValue('loglevel', ILogger::DEBUG);
106
-
107
-		$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
108
-
109
-		if(!$wasMaintenanceModeEnabled) {
110
-			$this->config->setSystemValue('maintenance', true);
111
-			$this->emit('\OC\Updater', 'maintenanceEnabled');
112
-		}
113
-
114
-		$this->waitForCronToFinish();
115
-
116
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
117
-		$currentVersion = implode('.', \OCP\Util::getVersion());
118
-		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
119
-
120
-		$success = true;
121
-		try {
122
-			$this->doUpgrade($currentVersion, $installedVersion);
123
-		} catch (HintException $exception) {
124
-			$this->log->logException($exception, ['app' => 'core']);
125
-			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
126
-			$success = false;
127
-		} catch (\Exception $exception) {
128
-			$this->log->logException($exception, ['app' => 'core']);
129
-			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
130
-			$success = false;
131
-		}
132
-
133
-		$this->emit('\OC\Updater', 'updateEnd', array($success));
134
-
135
-		if(!$wasMaintenanceModeEnabled && $success) {
136
-			$this->config->setSystemValue('maintenance', false);
137
-			$this->emit('\OC\Updater', 'maintenanceDisabled');
138
-		} else {
139
-			$this->emit('\OC\Updater', 'maintenanceActive');
140
-		}
141
-
142
-		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
143
-		$this->config->setSystemValue('loglevel', $logLevel);
144
-		$this->config->setSystemValue('installed', true);
145
-
146
-		return $success;
147
-	}
148
-
149
-	/**
150
-	 * Return version from which this version is allowed to upgrade from
151
-	 *
152
-	 * @return array allowed previous versions per vendor
153
-	 */
154
-	private function getAllowedPreviousVersions() {
155
-		// this should really be a JSON file
156
-		require \OC::$SERVERROOT . '/version.php';
157
-		/** @var array $OC_VersionCanBeUpgradedFrom */
158
-		return $OC_VersionCanBeUpgradedFrom;
159
-	}
160
-
161
-	/**
162
-	 * Return vendor from which this version was published
163
-	 *
164
-	 * @return string Get the vendor
165
-	 */
166
-	private function getVendor() {
167
-		// this should really be a JSON file
168
-		require \OC::$SERVERROOT . '/version.php';
169
-		/** @var string $vendor */
170
-		return (string) $vendor;
171
-	}
172
-
173
-	/**
174
-	 * Whether an upgrade to a specified version is possible
175
-	 * @param string $oldVersion
176
-	 * @param string $newVersion
177
-	 * @param array $allowedPreviousVersions
178
-	 * @return bool
179
-	 */
180
-	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
181
-		$version = explode('.', $oldVersion);
182
-		$majorMinor = $version[0] . '.' . $version[1];
183
-
184
-		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
185
-
186
-		// Vendor was not set correctly on install, so we have to white-list known versions
187
-		if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
188
-			$currentVendor = 'owncloud';
189
-		}
190
-
191
-		if ($currentVendor === 'nextcloud') {
192
-			return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
193
-				&& (version_compare($oldVersion, $newVersion, '<=') ||
194
-					$this->config->getSystemValue('debug', false));
195
-		}
196
-
197
-		// Check if the instance can be migrated
198
-		return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
199
-			isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
200
-	}
201
-
202
-	/**
203
-	 * runs the update actions in maintenance mode, does not upgrade the source files
204
-	 * except the main .htaccess file
205
-	 *
206
-	 * @param string $currentVersion current version to upgrade to
207
-	 * @param string $installedVersion previous version from which to upgrade from
208
-	 *
209
-	 * @throws \Exception
210
-	 */
211
-	private function doUpgrade($currentVersion, $installedVersion) {
212
-		// Stop update if the update is over several major versions
213
-		$allowedPreviousVersions = $this->getAllowedPreviousVersions();
214
-		if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
215
-			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
216
-		}
217
-
218
-		// Update .htaccess files
219
-		try {
220
-			Setup::updateHtaccess();
221
-			Setup::protectDataDirectory();
222
-		} catch (\Exception $e) {
223
-			throw new \Exception($e->getMessage());
224
-		}
225
-
226
-		// create empty file in data dir, so we can later find
227
-		// out that this is indeed an ownCloud data directory
228
-		// (in case it didn't exist before)
229
-		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
230
-
231
-		// pre-upgrade repairs
232
-		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
233
-		$repair->run();
234
-
235
-		$this->doCoreUpgrade();
236
-
237
-		try {
238
-			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
239
-			Setup::installBackgroundJobs();
240
-		} catch (\Exception $e) {
241
-			throw new \Exception($e->getMessage());
242
-		}
243
-
244
-		// update all shipped apps
245
-		$this->checkAppsRequirements();
246
-		$this->doAppUpgrade();
247
-
248
-		// Update the appfetchers version so it downloads the correct list from the appstore
249
-		\OC::$server->getAppFetcher()->setVersion($currentVersion);
250
-
251
-		// upgrade appstore apps
252
-		$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
253
-
254
-		// install new shipped apps on upgrade
255
-		OC_App::loadApps(['authentication']);
256
-		$errors = Installer::installShippedApps(true);
257
-		foreach ($errors as $appId => $exception) {
258
-			/** @var \Exception $exception */
259
-			$this->log->logException($exception, ['app' => $appId]);
260
-			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
261
-		}
262
-
263
-		// post-upgrade repairs
264
-		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
265
-		$repair->run();
266
-
267
-		//Invalidate update feed
268
-		$this->config->setAppValue('core', 'lastupdatedat', 0);
269
-
270
-		// Check for code integrity if not disabled
271
-		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272
-			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273
-			$this->checker->runInstanceVerification();
274
-			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
275
-		}
276
-
277
-		// only set the final version if everything went well
278
-		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
279
-		$this->config->setAppValue('core', 'vendor', $this->getVendor());
280
-	}
281
-
282
-	protected function doCoreUpgrade() {
283
-		$this->emit('\OC\Updater', 'dbUpgradeBefore');
284
-
285
-		// execute core migrations
286
-		$ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
287
-		$ms->migrate();
288
-
289
-		$this->emit('\OC\Updater', 'dbUpgrade');
290
-	}
291
-
292
-	/**
293
-	 * @param string $version the oc version to check app compatibility with
294
-	 */
295
-	protected function checkAppUpgrade($version) {
296
-		$apps = \OC_App::getEnabledApps();
297
-		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
298
-
299
-		$appManager = \OC::$server->getAppManager();
300
-		foreach ($apps as $appId) {
301
-			$info = \OC_App::getAppInfo($appId);
302
-			$compatible = \OC_App::isAppCompatible($version, $info);
303
-			$isShipped = $appManager->isShipped($appId);
304
-
305
-			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
306
-				/**
307
-				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
308
-				 * are not possible anymore within it. - Consider this when touching the code.
309
-				 * @link https://github.com/owncloud/core/issues/10980
310
-				 * @see \OC_App::updateApp
311
-				 */
312
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
313
-					$this->includePreUpdate($appId);
314
-				}
315
-				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
316
-					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
-					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
318
-				}
319
-			}
320
-		}
321
-
322
-		$this->emit('\OC\Updater', 'appUpgradeCheck');
323
-	}
324
-
325
-	/**
326
-	 * Includes the pre-update file. Done here to prevent namespace mixups.
327
-	 * @param string $appId
328
-	 */
329
-	private function includePreUpdate($appId) {
330
-		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
331
-	}
332
-
333
-	/**
334
-	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
335
-	 * (types authentication, filesystem, logging, in that order) afterwards.
336
-	 *
337
-	 * @throws NeedsUpdateException
338
-	 */
339
-	protected function doAppUpgrade() {
340
-		$apps = \OC_App::getEnabledApps();
341
-		$priorityTypes = array('authentication', 'filesystem', 'logging');
342
-		$pseudoOtherType = 'other';
343
-		$stacks = array($pseudoOtherType => array());
344
-
345
-		foreach ($apps as $appId) {
346
-			$priorityType = false;
347
-			foreach ($priorityTypes as $type) {
348
-				if(!isset($stacks[$type])) {
349
-					$stacks[$type] = array();
350
-				}
351
-				if (\OC_App::isType($appId, [$type])) {
352
-					$stacks[$type][] = $appId;
353
-					$priorityType = true;
354
-					break;
355
-				}
356
-			}
357
-			if (!$priorityType) {
358
-				$stacks[$pseudoOtherType][] = $appId;
359
-			}
360
-		}
361
-		foreach ($stacks as $type => $stack) {
362
-			foreach ($stack as $appId) {
363
-				if (\OC_App::shouldUpgrade($appId)) {
364
-					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
365
-					\OC_App::updateApp($appId);
366
-					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
367
-				}
368
-				if($type !== $pseudoOtherType) {
369
-					// load authentication, filesystem and logging apps after
370
-					// upgrading them. Other apps my need to rely on modifying
371
-					// user and/or filesystem aspects.
372
-					\OC_App::loadApp($appId);
373
-				}
374
-			}
375
-		}
376
-	}
377
-
378
-	/**
379
-	 * check if the current enabled apps are compatible with the current
380
-	 * ownCloud version. disable them if not.
381
-	 * This is important if you upgrade ownCloud and have non ported 3rd
382
-	 * party apps installed.
383
-	 *
384
-	 * @return array
385
-	 * @throws \Exception
386
-	 */
387
-	private function checkAppsRequirements() {
388
-		$isCoreUpgrade = $this->isCodeUpgrade();
389
-		$apps = OC_App::getEnabledApps();
390
-		$version = implode('.', Util::getVersion());
391
-		$disabledApps = [];
392
-		$appManager = \OC::$server->getAppManager();
393
-		foreach ($apps as $app) {
394
-			// check if the app is compatible with this version of ownCloud
395
-			$info = OC_App::getAppInfo($app);
396
-			if($info === null || !OC_App::isAppCompatible($version, $info)) {
397
-				if ($appManager->isShipped($app)) {
398
-					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
399
-				}
400
-				\OC::$server->getAppManager()->disableApp($app);
401
-				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
402
-			}
403
-			// no need to disable any app in case this is a non-core upgrade
404
-			if (!$isCoreUpgrade) {
405
-				continue;
406
-			}
407
-			// shipped apps will remain enabled
408
-			if ($appManager->isShipped($app)) {
409
-				continue;
410
-			}
411
-			// authentication and session apps will remain enabled as well
412
-			if (OC_App::isType($app, ['session', 'authentication'])) {
413
-				continue;
414
-			}
415
-		}
416
-		return $disabledApps;
417
-	}
418
-
419
-	/**
420
-	 * @return bool
421
-	 */
422
-	private function isCodeUpgrade() {
423
-		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
424
-		$currentVersion = implode('.', Util::getVersion());
425
-		if (version_compare($currentVersion, $installedVersion, '>')) {
426
-			return true;
427
-		}
428
-		return false;
429
-	}
430
-
431
-	/**
432
-	 * @param array $disabledApps
433
-	 * @throws \Exception
434
-	 */
435
-	private function upgradeAppStoreApps(array $disabledApps) {
436
-		foreach($disabledApps as $app) {
437
-			try {
438
-				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
439
-				if ($this->installer->isUpdateAvailable($app)) {
440
-					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
441
-					$this->installer->updateAppstoreApp($app);
442
-				}
443
-				$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
444
-			} catch (\Exception $ex) {
445
-				$this->log->logException($ex, ['app' => 'core']);
446
-			}
447
-		}
448
-	}
449
-
450
-	/**
451
-	 * Forward messages emitted by the repair routine
452
-	 */
453
-	private function emitRepairEvents() {
454
-		$dispatcher = \OC::$server->getEventDispatcher();
455
-		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
456
-			if ($event instanceof GenericEvent) {
457
-				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
458
-			}
459
-		});
460
-		$dispatcher->addListener('\OC\Repair::error', function ($event) {
461
-			if ($event instanceof GenericEvent) {
462
-				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
463
-			}
464
-		});
465
-		$dispatcher->addListener('\OC\Repair::info', function ($event) {
466
-			if ($event instanceof GenericEvent) {
467
-				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
468
-			}
469
-		});
470
-		$dispatcher->addListener('\OC\Repair::step', function ($event) {
471
-			if ($event instanceof GenericEvent) {
472
-				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
473
-			}
474
-		});
475
-	}
476
-
477
-	private function logAllEvents() {
478
-		$log = $this->log;
479
-
480
-		$dispatcher = \OC::$server->getEventDispatcher();
481
-		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
482
-			if (!$event instanceof GenericEvent) {
483
-				return;
484
-			}
485
-			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
486
-		});
487
-		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
488
-			if (!$event instanceof GenericEvent) {
489
-				return;
490
-			}
491
-			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
-		});
493
-
494
-		$repairListener = function($event) use ($log) {
495
-			if (!$event instanceof GenericEvent) {
496
-				return;
497
-			}
498
-			switch ($event->getSubject()) {
499
-				case '\OC\Repair::startProgress':
500
-					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
501
-					break;
502
-				case '\OC\Repair::advance':
503
-					$desc = $event->getArgument(1);
504
-					if (empty($desc)) {
505
-						$desc = '';
506
-					}
507
-					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
508
-
509
-					break;
510
-				case '\OC\Repair::finishProgress':
511
-					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
512
-					break;
513
-				case '\OC\Repair::step':
514
-					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
515
-					break;
516
-				case '\OC\Repair::info':
517
-					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
518
-					break;
519
-				case '\OC\Repair::warning':
520
-					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
521
-					break;
522
-				case '\OC\Repair::error':
523
-					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
524
-					break;
525
-			}
526
-		};
527
-
528
-		$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
529
-		$dispatcher->addListener('\OC\Repair::advance', $repairListener);
530
-		$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
531
-		$dispatcher->addListener('\OC\Repair::step', $repairListener);
532
-		$dispatcher->addListener('\OC\Repair::info', $repairListener);
533
-		$dispatcher->addListener('\OC\Repair::warning', $repairListener);
534
-		$dispatcher->addListener('\OC\Repair::error', $repairListener);
535
-
536
-
537
-		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
538
-			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
539
-		});
540
-		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
541
-			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
542
-		});
543
-		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
544
-			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
545
-		});
546
-		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
547
-			if ($success) {
548
-				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
549
-			} else {
550
-				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
551
-			}
552
-		});
553
-		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
554
-			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
555
-		});
556
-		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
557
-			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
558
-		});
559
-		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
560
-			$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']);
561
-		});
562
-		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
563
-			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
564
-		});
565
-		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
566
-			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
567
-		});
568
-		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
569
-			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
570
-		});
571
-		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
572
-			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
573
-		});
574
-		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
575
-			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
-		});
577
-		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
578
-			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
579
-		});
580
-		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
581
-			$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']);
582
-		});
583
-		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
584
-			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
585
-		});
586
-		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
587
-			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
588
-		});
589
-		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
590
-			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
591
-		});
592
-		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
593
-			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
594
-		});
595
-		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
596
-			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
597
-		});
598
-		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
599
-			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
600
-		});
601
-		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
602
-			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
603
-		});
604
-		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
605
-			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
606
-		});
607
-
608
-	}
609
-	private function waitForCronToFinish() {
610
-		while ($this->jobList->isAnyJobRunning()) {
611
-			$this->emit('\OC\Updater', 'waitForCronToFinish');
612
-			sleep(5);
613
-		}
614
-	}
58
+    /** @var ILogger $log */
59
+    private $log;
60
+
61
+    /** @var IConfig */
62
+    private $config;
63
+
64
+    /** @var Checker */
65
+    private $checker;
66
+
67
+    /** @var Installer */
68
+    private $installer;
69
+
70
+    /** @var IJobList */
71
+    private $jobList;
72
+
73
+    private $logLevelNames = [
74
+        0 => 'Debug',
75
+        1 => 'Info',
76
+        2 => 'Warning',
77
+        3 => 'Error',
78
+        4 => 'Fatal',
79
+    ];
80
+
81
+    public function __construct(IConfig $config,
82
+                                Checker $checker,
83
+                                ILogger $log,
84
+                                Installer $installer,
85
+                                IJobList $jobList) {
86
+        $this->log = $log;
87
+        $this->config = $config;
88
+        $this->checker = $checker;
89
+        $this->installer = $installer;
90
+        $this->jobList = $jobList;
91
+    }
92
+
93
+    /**
94
+     * runs the update actions in maintenance mode, does not upgrade the source files
95
+     * except the main .htaccess file
96
+     *
97
+     * @return bool true if the operation succeeded, false otherwise
98
+     */
99
+    public function upgrade() {
100
+        $this->emitRepairEvents();
101
+        $this->logAllEvents();
102
+
103
+        $logLevel = $this->config->getSystemValue('loglevel', ILogger::WARN);
104
+        $this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
+        $this->config->setSystemValue('loglevel', ILogger::DEBUG);
106
+
107
+        $wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
108
+
109
+        if(!$wasMaintenanceModeEnabled) {
110
+            $this->config->setSystemValue('maintenance', true);
111
+            $this->emit('\OC\Updater', 'maintenanceEnabled');
112
+        }
113
+
114
+        $this->waitForCronToFinish();
115
+
116
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
117
+        $currentVersion = implode('.', \OCP\Util::getVersion());
118
+        $this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
119
+
120
+        $success = true;
121
+        try {
122
+            $this->doUpgrade($currentVersion, $installedVersion);
123
+        } catch (HintException $exception) {
124
+            $this->log->logException($exception, ['app' => 'core']);
125
+            $this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
126
+            $success = false;
127
+        } catch (\Exception $exception) {
128
+            $this->log->logException($exception, ['app' => 'core']);
129
+            $this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
130
+            $success = false;
131
+        }
132
+
133
+        $this->emit('\OC\Updater', 'updateEnd', array($success));
134
+
135
+        if(!$wasMaintenanceModeEnabled && $success) {
136
+            $this->config->setSystemValue('maintenance', false);
137
+            $this->emit('\OC\Updater', 'maintenanceDisabled');
138
+        } else {
139
+            $this->emit('\OC\Updater', 'maintenanceActive');
140
+        }
141
+
142
+        $this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
143
+        $this->config->setSystemValue('loglevel', $logLevel);
144
+        $this->config->setSystemValue('installed', true);
145
+
146
+        return $success;
147
+    }
148
+
149
+    /**
150
+     * Return version from which this version is allowed to upgrade from
151
+     *
152
+     * @return array allowed previous versions per vendor
153
+     */
154
+    private function getAllowedPreviousVersions() {
155
+        // this should really be a JSON file
156
+        require \OC::$SERVERROOT . '/version.php';
157
+        /** @var array $OC_VersionCanBeUpgradedFrom */
158
+        return $OC_VersionCanBeUpgradedFrom;
159
+    }
160
+
161
+    /**
162
+     * Return vendor from which this version was published
163
+     *
164
+     * @return string Get the vendor
165
+     */
166
+    private function getVendor() {
167
+        // this should really be a JSON file
168
+        require \OC::$SERVERROOT . '/version.php';
169
+        /** @var string $vendor */
170
+        return (string) $vendor;
171
+    }
172
+
173
+    /**
174
+     * Whether an upgrade to a specified version is possible
175
+     * @param string $oldVersion
176
+     * @param string $newVersion
177
+     * @param array $allowedPreviousVersions
178
+     * @return bool
179
+     */
180
+    public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
181
+        $version = explode('.', $oldVersion);
182
+        $majorMinor = $version[0] . '.' . $version[1];
183
+
184
+        $currentVendor = $this->config->getAppValue('core', 'vendor', '');
185
+
186
+        // Vendor was not set correctly on install, so we have to white-list known versions
187
+        if ($currentVendor === '' && isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
188
+            $currentVendor = 'owncloud';
189
+        }
190
+
191
+        if ($currentVendor === 'nextcloud') {
192
+            return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
193
+                && (version_compare($oldVersion, $newVersion, '<=') ||
194
+                    $this->config->getSystemValue('debug', false));
195
+        }
196
+
197
+        // Check if the instance can be migrated
198
+        return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
199
+            isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
200
+    }
201
+
202
+    /**
203
+     * runs the update actions in maintenance mode, does not upgrade the source files
204
+     * except the main .htaccess file
205
+     *
206
+     * @param string $currentVersion current version to upgrade to
207
+     * @param string $installedVersion previous version from which to upgrade from
208
+     *
209
+     * @throws \Exception
210
+     */
211
+    private function doUpgrade($currentVersion, $installedVersion) {
212
+        // Stop update if the update is over several major versions
213
+        $allowedPreviousVersions = $this->getAllowedPreviousVersions();
214
+        if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
215
+            throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
216
+        }
217
+
218
+        // Update .htaccess files
219
+        try {
220
+            Setup::updateHtaccess();
221
+            Setup::protectDataDirectory();
222
+        } catch (\Exception $e) {
223
+            throw new \Exception($e->getMessage());
224
+        }
225
+
226
+        // create empty file in data dir, so we can later find
227
+        // out that this is indeed an ownCloud data directory
228
+        // (in case it didn't exist before)
229
+        file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
230
+
231
+        // pre-upgrade repairs
232
+        $repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
233
+        $repair->run();
234
+
235
+        $this->doCoreUpgrade();
236
+
237
+        try {
238
+            // TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
239
+            Setup::installBackgroundJobs();
240
+        } catch (\Exception $e) {
241
+            throw new \Exception($e->getMessage());
242
+        }
243
+
244
+        // update all shipped apps
245
+        $this->checkAppsRequirements();
246
+        $this->doAppUpgrade();
247
+
248
+        // Update the appfetchers version so it downloads the correct list from the appstore
249
+        \OC::$server->getAppFetcher()->setVersion($currentVersion);
250
+
251
+        // upgrade appstore apps
252
+        $this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
253
+
254
+        // install new shipped apps on upgrade
255
+        OC_App::loadApps(['authentication']);
256
+        $errors = Installer::installShippedApps(true);
257
+        foreach ($errors as $appId => $exception) {
258
+            /** @var \Exception $exception */
259
+            $this->log->logException($exception, ['app' => $appId]);
260
+            $this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
261
+        }
262
+
263
+        // post-upgrade repairs
264
+        $repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
265
+        $repair->run();
266
+
267
+        //Invalidate update feed
268
+        $this->config->setAppValue('core', 'lastupdatedat', 0);
269
+
270
+        // Check for code integrity if not disabled
271
+        if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
272
+            $this->emit('\OC\Updater', 'startCheckCodeIntegrity');
273
+            $this->checker->runInstanceVerification();
274
+            $this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
275
+        }
276
+
277
+        // only set the final version if everything went well
278
+        $this->config->setSystemValue('version', implode('.', Util::getVersion()));
279
+        $this->config->setAppValue('core', 'vendor', $this->getVendor());
280
+    }
281
+
282
+    protected function doCoreUpgrade() {
283
+        $this->emit('\OC\Updater', 'dbUpgradeBefore');
284
+
285
+        // execute core migrations
286
+        $ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
287
+        $ms->migrate();
288
+
289
+        $this->emit('\OC\Updater', 'dbUpgrade');
290
+    }
291
+
292
+    /**
293
+     * @param string $version the oc version to check app compatibility with
294
+     */
295
+    protected function checkAppUpgrade($version) {
296
+        $apps = \OC_App::getEnabledApps();
297
+        $this->emit('\OC\Updater', 'appUpgradeCheckBefore');
298
+
299
+        $appManager = \OC::$server->getAppManager();
300
+        foreach ($apps as $appId) {
301
+            $info = \OC_App::getAppInfo($appId);
302
+            $compatible = \OC_App::isAppCompatible($version, $info);
303
+            $isShipped = $appManager->isShipped($appId);
304
+
305
+            if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
306
+                /**
307
+                 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
308
+                 * are not possible anymore within it. - Consider this when touching the code.
309
+                 * @link https://github.com/owncloud/core/issues/10980
310
+                 * @see \OC_App::updateApp
311
+                 */
312
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
313
+                    $this->includePreUpdate($appId);
314
+                }
315
+                if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
316
+                    $this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
317
+                    \OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
318
+                }
319
+            }
320
+        }
321
+
322
+        $this->emit('\OC\Updater', 'appUpgradeCheck');
323
+    }
324
+
325
+    /**
326
+     * Includes the pre-update file. Done here to prevent namespace mixups.
327
+     * @param string $appId
328
+     */
329
+    private function includePreUpdate($appId) {
330
+        include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
331
+    }
332
+
333
+    /**
334
+     * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
335
+     * (types authentication, filesystem, logging, in that order) afterwards.
336
+     *
337
+     * @throws NeedsUpdateException
338
+     */
339
+    protected function doAppUpgrade() {
340
+        $apps = \OC_App::getEnabledApps();
341
+        $priorityTypes = array('authentication', 'filesystem', 'logging');
342
+        $pseudoOtherType = 'other';
343
+        $stacks = array($pseudoOtherType => array());
344
+
345
+        foreach ($apps as $appId) {
346
+            $priorityType = false;
347
+            foreach ($priorityTypes as $type) {
348
+                if(!isset($stacks[$type])) {
349
+                    $stacks[$type] = array();
350
+                }
351
+                if (\OC_App::isType($appId, [$type])) {
352
+                    $stacks[$type][] = $appId;
353
+                    $priorityType = true;
354
+                    break;
355
+                }
356
+            }
357
+            if (!$priorityType) {
358
+                $stacks[$pseudoOtherType][] = $appId;
359
+            }
360
+        }
361
+        foreach ($stacks as $type => $stack) {
362
+            foreach ($stack as $appId) {
363
+                if (\OC_App::shouldUpgrade($appId)) {
364
+                    $this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
365
+                    \OC_App::updateApp($appId);
366
+                    $this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
367
+                }
368
+                if($type !== $pseudoOtherType) {
369
+                    // load authentication, filesystem and logging apps after
370
+                    // upgrading them. Other apps my need to rely on modifying
371
+                    // user and/or filesystem aspects.
372
+                    \OC_App::loadApp($appId);
373
+                }
374
+            }
375
+        }
376
+    }
377
+
378
+    /**
379
+     * check if the current enabled apps are compatible with the current
380
+     * ownCloud version. disable them if not.
381
+     * This is important if you upgrade ownCloud and have non ported 3rd
382
+     * party apps installed.
383
+     *
384
+     * @return array
385
+     * @throws \Exception
386
+     */
387
+    private function checkAppsRequirements() {
388
+        $isCoreUpgrade = $this->isCodeUpgrade();
389
+        $apps = OC_App::getEnabledApps();
390
+        $version = implode('.', Util::getVersion());
391
+        $disabledApps = [];
392
+        $appManager = \OC::$server->getAppManager();
393
+        foreach ($apps as $app) {
394
+            // check if the app is compatible with this version of ownCloud
395
+            $info = OC_App::getAppInfo($app);
396
+            if($info === null || !OC_App::isAppCompatible($version, $info)) {
397
+                if ($appManager->isShipped($app)) {
398
+                    throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
399
+                }
400
+                \OC::$server->getAppManager()->disableApp($app);
401
+                $this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
402
+            }
403
+            // no need to disable any app in case this is a non-core upgrade
404
+            if (!$isCoreUpgrade) {
405
+                continue;
406
+            }
407
+            // shipped apps will remain enabled
408
+            if ($appManager->isShipped($app)) {
409
+                continue;
410
+            }
411
+            // authentication and session apps will remain enabled as well
412
+            if (OC_App::isType($app, ['session', 'authentication'])) {
413
+                continue;
414
+            }
415
+        }
416
+        return $disabledApps;
417
+    }
418
+
419
+    /**
420
+     * @return bool
421
+     */
422
+    private function isCodeUpgrade() {
423
+        $installedVersion = $this->config->getSystemValue('version', '0.0.0');
424
+        $currentVersion = implode('.', Util::getVersion());
425
+        if (version_compare($currentVersion, $installedVersion, '>')) {
426
+            return true;
427
+        }
428
+        return false;
429
+    }
430
+
431
+    /**
432
+     * @param array $disabledApps
433
+     * @throws \Exception
434
+     */
435
+    private function upgradeAppStoreApps(array $disabledApps) {
436
+        foreach($disabledApps as $app) {
437
+            try {
438
+                $this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
439
+                if ($this->installer->isUpdateAvailable($app)) {
440
+                    $this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
441
+                    $this->installer->updateAppstoreApp($app);
442
+                }
443
+                $this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
444
+            } catch (\Exception $ex) {
445
+                $this->log->logException($ex, ['app' => 'core']);
446
+            }
447
+        }
448
+    }
449
+
450
+    /**
451
+     * Forward messages emitted by the repair routine
452
+     */
453
+    private function emitRepairEvents() {
454
+        $dispatcher = \OC::$server->getEventDispatcher();
455
+        $dispatcher->addListener('\OC\Repair::warning', function ($event) {
456
+            if ($event instanceof GenericEvent) {
457
+                $this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
458
+            }
459
+        });
460
+        $dispatcher->addListener('\OC\Repair::error', function ($event) {
461
+            if ($event instanceof GenericEvent) {
462
+                $this->emit('\OC\Updater', 'repairError', $event->getArguments());
463
+            }
464
+        });
465
+        $dispatcher->addListener('\OC\Repair::info', function ($event) {
466
+            if ($event instanceof GenericEvent) {
467
+                $this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
468
+            }
469
+        });
470
+        $dispatcher->addListener('\OC\Repair::step', function ($event) {
471
+            if ($event instanceof GenericEvent) {
472
+                $this->emit('\OC\Updater', 'repairStep', $event->getArguments());
473
+            }
474
+        });
475
+    }
476
+
477
+    private function logAllEvents() {
478
+        $log = $this->log;
479
+
480
+        $dispatcher = \OC::$server->getEventDispatcher();
481
+        $dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
482
+            if (!$event instanceof GenericEvent) {
483
+                return;
484
+            }
485
+            $log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
486
+        });
487
+        $dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
488
+            if (!$event instanceof GenericEvent) {
489
+                return;
490
+            }
491
+            $log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
+        });
493
+
494
+        $repairListener = function($event) use ($log) {
495
+            if (!$event instanceof GenericEvent) {
496
+                return;
497
+            }
498
+            switch ($event->getSubject()) {
499
+                case '\OC\Repair::startProgress':
500
+                    $log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
501
+                    break;
502
+                case '\OC\Repair::advance':
503
+                    $desc = $event->getArgument(1);
504
+                    if (empty($desc)) {
505
+                        $desc = '';
506
+                    }
507
+                    $log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
508
+
509
+                    break;
510
+                case '\OC\Repair::finishProgress':
511
+                    $log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
512
+                    break;
513
+                case '\OC\Repair::step':
514
+                    $log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
515
+                    break;
516
+                case '\OC\Repair::info':
517
+                    $log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
518
+                    break;
519
+                case '\OC\Repair::warning':
520
+                    $log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
521
+                    break;
522
+                case '\OC\Repair::error':
523
+                    $log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
524
+                    break;
525
+            }
526
+        };
527
+
528
+        $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
529
+        $dispatcher->addListener('\OC\Repair::advance', $repairListener);
530
+        $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
531
+        $dispatcher->addListener('\OC\Repair::step', $repairListener);
532
+        $dispatcher->addListener('\OC\Repair::info', $repairListener);
533
+        $dispatcher->addListener('\OC\Repair::warning', $repairListener);
534
+        $dispatcher->addListener('\OC\Repair::error', $repairListener);
535
+
536
+
537
+        $this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
538
+            $log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
539
+        });
540
+        $this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
541
+            $log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
542
+        });
543
+        $this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
544
+            $log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
545
+        });
546
+        $this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
547
+            if ($success) {
548
+                $log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
549
+            } else {
550
+                $log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
551
+            }
552
+        });
553
+        $this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
554
+            $log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
555
+        });
556
+        $this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
557
+            $log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
558
+        });
559
+        $this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
560
+            $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']);
561
+        });
562
+        $this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
563
+            $log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
564
+        });
565
+        $this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
566
+            $log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
567
+        });
568
+        $this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
569
+            $log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
570
+        });
571
+        $this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
572
+            $log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
573
+        });
574
+        $this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
575
+            $log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
+        });
577
+        $this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
578
+            $log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
579
+        });
580
+        $this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
581
+            $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']);
582
+        });
583
+        $this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
584
+            $log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
585
+        });
586
+        $this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
587
+            $log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
588
+        });
589
+        $this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
590
+            $log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
591
+        });
592
+        $this->listen('\OC\Updater', 'failure', function ($message) use($log) {
593
+            $log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
594
+        });
595
+        $this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
596
+            $log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
597
+        });
598
+        $this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
599
+            $log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
600
+        });
601
+        $this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
602
+            $log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
603
+        });
604
+        $this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
605
+            $log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
606
+        });
607
+
608
+    }
609
+    private function waitForCronToFinish() {
610
+        while ($this->jobList->isAnyJobRunning()) {
611
+            $this->emit('\OC\Updater', 'waitForCronToFinish');
612
+            sleep(5);
613
+        }
614
+    }
615 615
 
616 616
 }
617 617
 
Please login to merge, or discard this patch.
core/Command/Upgrade.php 2 patches
Indentation   +234 added lines, -234 removed lines patch added patch discarded remove patch
@@ -48,255 +48,255 @@
 block discarded – undo
48 48
 
49 49
 class Upgrade extends Command {
50 50
 
51
-	const ERROR_SUCCESS = 0;
52
-	const ERROR_NOT_INSTALLED = 1;
53
-	const ERROR_MAINTENANCE_MODE = 2;
54
-	const ERROR_UP_TO_DATE = 0;
55
-	const ERROR_INVALID_ARGUMENTS = 4;
56
-	const ERROR_FAILURE = 5;
51
+    const ERROR_SUCCESS = 0;
52
+    const ERROR_NOT_INSTALLED = 1;
53
+    const ERROR_MAINTENANCE_MODE = 2;
54
+    const ERROR_UP_TO_DATE = 0;
55
+    const ERROR_INVALID_ARGUMENTS = 4;
56
+    const ERROR_FAILURE = 5;
57 57
 
58
-	/** @var IConfig */
59
-	private $config;
58
+    /** @var IConfig */
59
+    private $config;
60 60
 
61
-	/** @var ILogger */
62
-	private $logger;
61
+    /** @var ILogger */
62
+    private $logger;
63 63
 
64
-	/**
65
-	 * @param IConfig $config
66
-	 * @param ILogger $logger
67
-	 * @param Installer $installer
68
-	 */
69
-	public function __construct(IConfig $config, ILogger $logger, Installer $installer) {
70
-		parent::__construct();
71
-		$this->config = $config;
72
-		$this->logger = $logger;
73
-		$this->installer = $installer;
74
-	}
64
+    /**
65
+     * @param IConfig $config
66
+     * @param ILogger $logger
67
+     * @param Installer $installer
68
+     */
69
+    public function __construct(IConfig $config, ILogger $logger, Installer $installer) {
70
+        parent::__construct();
71
+        $this->config = $config;
72
+        $this->logger = $logger;
73
+        $this->installer = $installer;
74
+    }
75 75
 
76
-	protected function configure() {
77
-		$this
78
-			->setName('upgrade')
79
-			->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.');
80
-	}
76
+    protected function configure() {
77
+        $this
78
+            ->setName('upgrade')
79
+            ->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.');
80
+    }
81 81
 
82
-	/**
83
-	 * Execute the upgrade command
84
-	 *
85
-	 * @param InputInterface $input input interface
86
-	 * @param OutputInterface $output output interface
87
-	 */
88
-	protected function execute(InputInterface $input, OutputInterface $output) {
82
+    /**
83
+     * Execute the upgrade command
84
+     *
85
+     * @param InputInterface $input input interface
86
+     * @param OutputInterface $output output interface
87
+     */
88
+    protected function execute(InputInterface $input, OutputInterface $output) {
89 89
 
90
-		if(Util::needUpgrade()) {
91
-			if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
92
-				// Prepend each line with a little timestamp
93
-				$timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter());
94
-				$output->setFormatter($timestampFormatter);
95
-			}
90
+        if(Util::needUpgrade()) {
91
+            if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
92
+                // Prepend each line with a little timestamp
93
+                $timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter());
94
+                $output->setFormatter($timestampFormatter);
95
+            }
96 96
 
97
-			$self = $this;
98
-			$updater = new Updater(
99
-					$this->config,
100
-					\OC::$server->getIntegrityCodeChecker(),
101
-					$this->logger,
102
-					$this->installer,
103
-					\OC::$server->getJobList()
104
-			);
97
+            $self = $this;
98
+            $updater = new Updater(
99
+                    $this->config,
100
+                    \OC::$server->getIntegrityCodeChecker(),
101
+                    $this->logger,
102
+                    $this->installer,
103
+                    \OC::$server->getJobList()
104
+            );
105 105
 
106
-			$dispatcher = \OC::$server->getEventDispatcher();
107
-			$progress = new ProgressBar($output);
108
-			$progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%");
109
-			$listener = function($event) use ($progress, $output) {
110
-				if ($event instanceof GenericEvent) {
111
-					$message = $event->getSubject();
112
-					if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
113
-						$output->writeln(' Checking table ' . $message);
114
-					} else {
115
-						if (strlen($message) > 60) {
116
-							$message = substr($message, 0, 57) . '...';
117
-						}
118
-						$progress->setMessage($message);
119
-						if ($event[0] === 1) {
120
-							$output->writeln('');
121
-							$progress->start($event[1]);
122
-						}
123
-						$progress->setProgress($event[0]);
124
-						if ($event[0] === $event[1]) {
125
-							$progress->setMessage('Done');
126
-							$progress->finish();
127
-							$output->writeln('');
128
-						}
129
-					}
130
-				}
131
-			};
132
-			$repairListener = function($event) use ($progress, $output) {
133
-				if (!$event instanceof GenericEvent) {
134
-					return;
135
-				}
136
-				switch ($event->getSubject()) {
137
-					case '\OC\Repair::startProgress':
138
-						$progress->setMessage('Starting ...');
139
-						$output->writeln($event->getArgument(1));
140
-						$output->writeln('');
141
-						$progress->start($event->getArgument(0));
142
-						break;
143
-					case '\OC\Repair::advance':
144
-						$desc = $event->getArgument(1);
145
-						if (!empty($desc)) {
146
-							$progress->setMessage($desc);
147
-						}
148
-						$progress->advance($event->getArgument(0));
106
+            $dispatcher = \OC::$server->getEventDispatcher();
107
+            $progress = new ProgressBar($output);
108
+            $progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%");
109
+            $listener = function($event) use ($progress, $output) {
110
+                if ($event instanceof GenericEvent) {
111
+                    $message = $event->getSubject();
112
+                    if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
113
+                        $output->writeln(' Checking table ' . $message);
114
+                    } else {
115
+                        if (strlen($message) > 60) {
116
+                            $message = substr($message, 0, 57) . '...';
117
+                        }
118
+                        $progress->setMessage($message);
119
+                        if ($event[0] === 1) {
120
+                            $output->writeln('');
121
+                            $progress->start($event[1]);
122
+                        }
123
+                        $progress->setProgress($event[0]);
124
+                        if ($event[0] === $event[1]) {
125
+                            $progress->setMessage('Done');
126
+                            $progress->finish();
127
+                            $output->writeln('');
128
+                        }
129
+                    }
130
+                }
131
+            };
132
+            $repairListener = function($event) use ($progress, $output) {
133
+                if (!$event instanceof GenericEvent) {
134
+                    return;
135
+                }
136
+                switch ($event->getSubject()) {
137
+                    case '\OC\Repair::startProgress':
138
+                        $progress->setMessage('Starting ...');
139
+                        $output->writeln($event->getArgument(1));
140
+                        $output->writeln('');
141
+                        $progress->start($event->getArgument(0));
142
+                        break;
143
+                    case '\OC\Repair::advance':
144
+                        $desc = $event->getArgument(1);
145
+                        if (!empty($desc)) {
146
+                            $progress->setMessage($desc);
147
+                        }
148
+                        $progress->advance($event->getArgument(0));
149 149
 
150
-						break;
151
-					case '\OC\Repair::finishProgress':
152
-						$progress->setMessage('Done');
153
-						$progress->finish();
154
-						$output->writeln('');
155
-						break;
156
-					case '\OC\Repair::step':
157
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
158
-							$output->writeln('<info>Repair step: ' . $event->getArgument(0) . '</info>');
159
-						}
160
-						break;
161
-					case '\OC\Repair::info':
162
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
163
-							$output->writeln('<info>Repair info: ' . $event->getArgument(0) . '</info>');
164
-						}
165
-						break;
166
-					case '\OC\Repair::warning':
167
-						$output->writeln('<error>Repair warning: ' . $event->getArgument(0) . '</error>');
168
-						break;
169
-					case '\OC\Repair::error':
170
-						$output->writeln('<error>Repair error: ' . $event->getArgument(0) . '</error>');
171
-						break;
172
-				}
173
-			};
150
+                        break;
151
+                    case '\OC\Repair::finishProgress':
152
+                        $progress->setMessage('Done');
153
+                        $progress->finish();
154
+                        $output->writeln('');
155
+                        break;
156
+                    case '\OC\Repair::step':
157
+                        if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
158
+                            $output->writeln('<info>Repair step: ' . $event->getArgument(0) . '</info>');
159
+                        }
160
+                        break;
161
+                    case '\OC\Repair::info':
162
+                        if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
163
+                            $output->writeln('<info>Repair info: ' . $event->getArgument(0) . '</info>');
164
+                        }
165
+                        break;
166
+                    case '\OC\Repair::warning':
167
+                        $output->writeln('<error>Repair warning: ' . $event->getArgument(0) . '</error>');
168
+                        break;
169
+                    case '\OC\Repair::error':
170
+                        $output->writeln('<error>Repair error: ' . $event->getArgument(0) . '</error>');
171
+                        break;
172
+                }
173
+            };
174 174
 
175
-			$dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener);
176
-			$dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener);
177
-			$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
178
-			$dispatcher->addListener('\OC\Repair::advance', $repairListener);
179
-			$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
180
-			$dispatcher->addListener('\OC\Repair::step', $repairListener);
181
-			$dispatcher->addListener('\OC\Repair::info', $repairListener);
182
-			$dispatcher->addListener('\OC\Repair::warning', $repairListener);
183
-			$dispatcher->addListener('\OC\Repair::error', $repairListener);
175
+            $dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener);
176
+            $dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener);
177
+            $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
178
+            $dispatcher->addListener('\OC\Repair::advance', $repairListener);
179
+            $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
180
+            $dispatcher->addListener('\OC\Repair::step', $repairListener);
181
+            $dispatcher->addListener('\OC\Repair::info', $repairListener);
182
+            $dispatcher->addListener('\OC\Repair::warning', $repairListener);
183
+            $dispatcher->addListener('\OC\Repair::error', $repairListener);
184 184
 			
185 185
 
186
-			$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use($output) {
187
-				$output->writeln('<info>Turned on maintenance mode</info>');
188
-			});
189
-			$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use($output) {
190
-				$output->writeln('<info>Turned off maintenance mode</info>');
191
-			});
192
-			$updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) {
193
-				$output->writeln('<info>Maintenance mode is kept active</info>');
194
-			});
195
-			$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use($output) {
196
-				$output->writeln('<info>Waiting for cron to finish (checks again in 5 seconds)...</info>');
197
-			});
198
-			$updater->listen('\OC\Updater', 'updateEnd',
199
-				function ($success) use($output, $self) {
200
-					if ($success) {
201
-						$message = "<info>Update successful</info>";
202
-					} else {
203
-						$message = "<error>Update failed</error>";
204
-					}
205
-					$output->writeln($message);
206
-				});
207
-			$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($output) {
208
-				$output->writeln('<info>Updating database schema</info>');
209
-			});
210
-			$updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) {
211
-				$output->writeln('<info>Updated database</info>');
212
-			});
213
-			$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($output) {
214
-				$output->writeln('<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>');
215
-			});
216
-			$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
217
-				$output->writeln('<info>Checked database schema update</info>');
218
-			});
219
-			$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) {
220
-				$output->writeln('<comment>Disabled incompatible app: ' . $app . '</comment>');
221
-			});
222
-			$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($output) {
223
-				$output->writeln('<info>Checking for update of app ' . $app . ' in appstore</info>');
224
-			});
225
-			$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($output) {
226
-				$output->writeln('<info>Update app ' . $app . ' from appstore</info>');
227
-			});
228
-			$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($output) {
229
-				$output->writeln('<info>Checked for update of app "' . $app . '" in appstore </info>');
230
-			});
231
-			$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) {
232
-				$output->writeln('<info>Checking updates of apps</info>');
233
-			});
234
-			$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) {
235
-				$output->writeln("<info>Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)</info>");
236
-			});
237
-			$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
238
-				$output->writeln('<info>Checked database schema update for apps</info>');
239
-			});
240
-			$updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) {
241
-				$output->writeln("<info>Updating <$app> ...</info>");
242
-			});
243
-			$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
244
-				$output->writeln("<info>Updated <$app> to $version</info>");
245
-			});
246
-			$updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) {
247
-				$output->writeln("<error>$message</error>");
248
-			});
249
-			$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($output) {
250
-				$output->writeln("<info>Set log level to debug</info>");
251
-			});
252
-			$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($output) {
253
-				$output->writeln("<info>Reset log level</info>");
254
-			});
255
-			$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($output) {
256
-				$output->writeln("<info>Starting code integrity check...</info>");
257
-			});
258
-			$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($output) {
259
-				$output->writeln("<info>Finished code integrity check</info>");
260
-			});
186
+            $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use($output) {
187
+                $output->writeln('<info>Turned on maintenance mode</info>');
188
+            });
189
+            $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use($output) {
190
+                $output->writeln('<info>Turned off maintenance mode</info>');
191
+            });
192
+            $updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) {
193
+                $output->writeln('<info>Maintenance mode is kept active</info>');
194
+            });
195
+            $updater->listen('\OC\Updater', 'waitForCronToFinish', function () use($output) {
196
+                $output->writeln('<info>Waiting for cron to finish (checks again in 5 seconds)...</info>');
197
+            });
198
+            $updater->listen('\OC\Updater', 'updateEnd',
199
+                function ($success) use($output, $self) {
200
+                    if ($success) {
201
+                        $message = "<info>Update successful</info>";
202
+                    } else {
203
+                        $message = "<error>Update failed</error>";
204
+                    }
205
+                    $output->writeln($message);
206
+                });
207
+            $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($output) {
208
+                $output->writeln('<info>Updating database schema</info>');
209
+            });
210
+            $updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) {
211
+                $output->writeln('<info>Updated database</info>');
212
+            });
213
+            $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($output) {
214
+                $output->writeln('<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>');
215
+            });
216
+            $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
217
+                $output->writeln('<info>Checked database schema update</info>');
218
+            });
219
+            $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) {
220
+                $output->writeln('<comment>Disabled incompatible app: ' . $app . '</comment>');
221
+            });
222
+            $updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($output) {
223
+                $output->writeln('<info>Checking for update of app ' . $app . ' in appstore</info>');
224
+            });
225
+            $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($output) {
226
+                $output->writeln('<info>Update app ' . $app . ' from appstore</info>');
227
+            });
228
+            $updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($output) {
229
+                $output->writeln('<info>Checked for update of app "' . $app . '" in appstore </info>');
230
+            });
231
+            $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) {
232
+                $output->writeln('<info>Checking updates of apps</info>');
233
+            });
234
+            $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) {
235
+                $output->writeln("<info>Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)</info>");
236
+            });
237
+            $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
238
+                $output->writeln('<info>Checked database schema update for apps</info>');
239
+            });
240
+            $updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) {
241
+                $output->writeln("<info>Updating <$app> ...</info>");
242
+            });
243
+            $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
244
+                $output->writeln("<info>Updated <$app> to $version</info>");
245
+            });
246
+            $updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) {
247
+                $output->writeln("<error>$message</error>");
248
+            });
249
+            $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($output) {
250
+                $output->writeln("<info>Set log level to debug</info>");
251
+            });
252
+            $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($output) {
253
+                $output->writeln("<info>Reset log level</info>");
254
+            });
255
+            $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($output) {
256
+                $output->writeln("<info>Starting code integrity check...</info>");
257
+            });
258
+            $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($output) {
259
+                $output->writeln("<info>Finished code integrity check</info>");
260
+            });
261 261
 
262
-			$success = $updater->upgrade();
262
+            $success = $updater->upgrade();
263 263
 
264
-			$this->postUpgradeCheck($input, $output);
264
+            $this->postUpgradeCheck($input, $output);
265 265
 
266
-			if(!$success) {
267
-				return self::ERROR_FAILURE;
268
-			}
266
+            if(!$success) {
267
+                return self::ERROR_FAILURE;
268
+            }
269 269
 
270
-			return self::ERROR_SUCCESS;
271
-		} else if($this->config->getSystemValue('maintenance', false)) {
272
-			//Possible scenario: Nextcloud core is updated but an app failed
273
-			$output->writeln('<warning>Nextcloud is in maintenance mode</warning>');
274
-			$output->write('<comment>Maybe an upgrade is already in process. Please check the '
275
-				. 'logfile (data/nextcloud.log). If you want to re-run the '
276
-				. 'upgrade procedure, remove the "maintenance mode" from '
277
-				. 'config.php and call this script again.</comment>'
278
-				, true);
279
-			return self::ERROR_MAINTENANCE_MODE;
280
-		} else {
281
-			$output->writeln('<info>Nextcloud is already latest version</info>');
282
-			return self::ERROR_UP_TO_DATE;
283
-		}
284
-	}
270
+            return self::ERROR_SUCCESS;
271
+        } else if($this->config->getSystemValue('maintenance', false)) {
272
+            //Possible scenario: Nextcloud core is updated but an app failed
273
+            $output->writeln('<warning>Nextcloud is in maintenance mode</warning>');
274
+            $output->write('<comment>Maybe an upgrade is already in process. Please check the '
275
+                . 'logfile (data/nextcloud.log). If you want to re-run the '
276
+                . 'upgrade procedure, remove the "maintenance mode" from '
277
+                . 'config.php and call this script again.</comment>'
278
+                , true);
279
+            return self::ERROR_MAINTENANCE_MODE;
280
+        } else {
281
+            $output->writeln('<info>Nextcloud is already latest version</info>');
282
+            return self::ERROR_UP_TO_DATE;
283
+        }
284
+    }
285 285
 
286
-	/**
287
-	 * Perform a post upgrade check (specific to the command line tool)
288
-	 *
289
-	 * @param InputInterface $input input interface
290
-	 * @param OutputInterface $output output interface
291
-	 */
292
-	protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) {
293
-		$trustedDomains = $this->config->getSystemValue('trusted_domains', array());
294
-		if (empty($trustedDomains)) {
295
-			$output->write(
296
-				'<warning>The setting "trusted_domains" could not be ' .
297
-				'set automatically by the upgrade script, ' .
298
-				'please set it manually</warning>'
299
-			);
300
-		}
301
-	}
286
+    /**
287
+     * Perform a post upgrade check (specific to the command line tool)
288
+     *
289
+     * @param InputInterface $input input interface
290
+     * @param OutputInterface $output output interface
291
+     */
292
+    protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) {
293
+        $trustedDomains = $this->config->getSystemValue('trusted_domains', array());
294
+        if (empty($trustedDomains)) {
295
+            $output->write(
296
+                '<warning>The setting "trusted_domains" could not be ' .
297
+                'set automatically by the upgrade script, ' .
298
+                'please set it manually</warning>'
299
+            );
300
+        }
301
+    }
302 302
 }
Please login to merge, or discard this patch.
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -87,7 +87,7 @@  discard block
 block discarded – undo
87 87
 	 */
88 88
 	protected function execute(InputInterface $input, OutputInterface $output) {
89 89
 
90
-		if(Util::needUpgrade()) {
90
+		if (Util::needUpgrade()) {
91 91
 			if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
92 92
 				// Prepend each line with a little timestamp
93 93
 				$timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter());
@@ -110,10 +110,10 @@  discard block
 block discarded – undo
110 110
 				if ($event instanceof GenericEvent) {
111 111
 					$message = $event->getSubject();
112 112
 					if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
113
-						$output->writeln(' Checking table ' . $message);
113
+						$output->writeln(' Checking table '.$message);
114 114
 					} else {
115 115
 						if (strlen($message) > 60) {
116
-							$message = substr($message, 0, 57) . '...';
116
+							$message = substr($message, 0, 57).'...';
117 117
 						}
118 118
 						$progress->setMessage($message);
119 119
 						if ($event[0] === 1) {
@@ -154,20 +154,20 @@  discard block
 block discarded – undo
154 154
 						$output->writeln('');
155 155
 						break;
156 156
 					case '\OC\Repair::step':
157
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
158
-							$output->writeln('<info>Repair step: ' . $event->getArgument(0) . '</info>');
157
+						if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
158
+							$output->writeln('<info>Repair step: '.$event->getArgument(0).'</info>');
159 159
 						}
160 160
 						break;
161 161
 					case '\OC\Repair::info':
162
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
163
-							$output->writeln('<info>Repair info: ' . $event->getArgument(0) . '</info>');
162
+						if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
163
+							$output->writeln('<info>Repair info: '.$event->getArgument(0).'</info>');
164 164
 						}
165 165
 						break;
166 166
 					case '\OC\Repair::warning':
167
-						$output->writeln('<error>Repair warning: ' . $event->getArgument(0) . '</error>');
167
+						$output->writeln('<error>Repair warning: '.$event->getArgument(0).'</error>');
168 168
 						break;
169 169
 					case '\OC\Repair::error':
170
-						$output->writeln('<error>Repair error: ' . $event->getArgument(0) . '</error>');
170
+						$output->writeln('<error>Repair error: '.$event->getArgument(0).'</error>');
171 171
 						break;
172 172
 				}
173 173
 			};
@@ -183,20 +183,20 @@  discard block
 block discarded – undo
183 183
 			$dispatcher->addListener('\OC\Repair::error', $repairListener);
184 184
 			
185 185
 
186
-			$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use($output) {
186
+			$updater->listen('\OC\Updater', 'maintenanceEnabled', function() use($output) {
187 187
 				$output->writeln('<info>Turned on maintenance mode</info>');
188 188
 			});
189
-			$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use($output) {
189
+			$updater->listen('\OC\Updater', 'maintenanceDisabled', function() use($output) {
190 190
 				$output->writeln('<info>Turned off maintenance mode</info>');
191 191
 			});
192
-			$updater->listen('\OC\Updater', 'maintenanceActive', function () use($output) {
192
+			$updater->listen('\OC\Updater', 'maintenanceActive', function() use($output) {
193 193
 				$output->writeln('<info>Maintenance mode is kept active</info>');
194 194
 			});
195
-			$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use($output) {
195
+			$updater->listen('\OC\Updater', 'waitForCronToFinish', function() use($output) {
196 196
 				$output->writeln('<info>Waiting for cron to finish (checks again in 5 seconds)...</info>');
197 197
 			});
198 198
 			$updater->listen('\OC\Updater', 'updateEnd',
199
-				function ($success) use($output, $self) {
199
+				function($success) use($output, $self) {
200 200
 					if ($success) {
201 201
 						$message = "<info>Update successful</info>";
202 202
 					} else {
@@ -204,58 +204,58 @@  discard block
 block discarded – undo
204 204
 					}
205 205
 					$output->writeln($message);
206 206
 				});
207
-			$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($output) {
207
+			$updater->listen('\OC\Updater', 'dbUpgradeBefore', function() use($output) {
208 208
 				$output->writeln('<info>Updating database schema</info>');
209 209
 			});
210
-			$updater->listen('\OC\Updater', 'dbUpgrade', function () use($output) {
210
+			$updater->listen('\OC\Updater', 'dbUpgrade', function() use($output) {
211 211
 				$output->writeln('<info>Updated database</info>');
212 212
 			});
213
-			$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($output) {
213
+			$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function() use($output) {
214 214
 				$output->writeln('<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>');
215 215
 			});
216
-			$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($output) {
216
+			$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function() use($output) {
217 217
 				$output->writeln('<info>Checked database schema update</info>');
218 218
 			});
219
-			$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($output) {
220
-				$output->writeln('<comment>Disabled incompatible app: ' . $app . '</comment>');
219
+			$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function($app) use($output) {
220
+				$output->writeln('<comment>Disabled incompatible app: '.$app.'</comment>');
221 221
 			});
222
-			$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($output) {
223
-				$output->writeln('<info>Checking for update of app ' . $app . ' in appstore</info>');
222
+			$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function($app) use($output) {
223
+				$output->writeln('<info>Checking for update of app '.$app.' in appstore</info>');
224 224
 			});
225
-			$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($output) {
226
-				$output->writeln('<info>Update app ' . $app . ' from appstore</info>');
225
+			$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function($app) use($output) {
226
+				$output->writeln('<info>Update app '.$app.' from appstore</info>');
227 227
 			});
228
-			$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($output) {
229
-				$output->writeln('<info>Checked for update of app "' . $app . '" in appstore </info>');
228
+			$updater->listen('\OC\Updater', 'checkAppStoreApp', function($app) use($output) {
229
+				$output->writeln('<info>Checked for update of app "'.$app.'" in appstore </info>');
230 230
 			});
231
-			$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) {
231
+			$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function() use ($output) {
232 232
 				$output->writeln('<info>Checking updates of apps</info>');
233 233
 			});
234
-			$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) {
234
+			$updater->listen('\OC\Updater', 'appSimulateUpdate', function($app) use ($output) {
235 235
 				$output->writeln("<info>Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)</info>");
236 236
 			});
237
-			$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
237
+			$updater->listen('\OC\Updater', 'appUpgradeCheck', function() use ($output) {
238 238
 				$output->writeln('<info>Checked database schema update for apps</info>');
239 239
 			});
240
-			$updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) {
240
+			$updater->listen('\OC\Updater', 'appUpgradeStarted', function($app, $version) use ($output) {
241 241
 				$output->writeln("<info>Updating <$app> ...</info>");
242 242
 			});
243
-			$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
243
+			$updater->listen('\OC\Updater', 'appUpgrade', function($app, $version) use ($output) {
244 244
 				$output->writeln("<info>Updated <$app> to $version</info>");
245 245
 			});
246
-			$updater->listen('\OC\Updater', 'failure', function ($message) use($output, $self) {
246
+			$updater->listen('\OC\Updater', 'failure', function($message) use($output, $self) {
247 247
 				$output->writeln("<error>$message</error>");
248 248
 			});
249
-			$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($output) {
249
+			$updater->listen('\OC\Updater', 'setDebugLogLevel', function($logLevel, $logLevelName) use($output) {
250 250
 				$output->writeln("<info>Set log level to debug</info>");
251 251
 			});
252
-			$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($output) {
252
+			$updater->listen('\OC\Updater', 'resetLogLevel', function($logLevel, $logLevelName) use($output) {
253 253
 				$output->writeln("<info>Reset log level</info>");
254 254
 			});
255
-			$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($output) {
255
+			$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function() use($output) {
256 256
 				$output->writeln("<info>Starting code integrity check...</info>");
257 257
 			});
258
-			$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($output) {
258
+			$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function() use($output) {
259 259
 				$output->writeln("<info>Finished code integrity check</info>");
260 260
 			});
261 261
 
@@ -263,12 +263,12 @@  discard block
 block discarded – undo
263 263
 
264 264
 			$this->postUpgradeCheck($input, $output);
265 265
 
266
-			if(!$success) {
266
+			if (!$success) {
267 267
 				return self::ERROR_FAILURE;
268 268
 			}
269 269
 
270 270
 			return self::ERROR_SUCCESS;
271
-		} else if($this->config->getSystemValue('maintenance', false)) {
271
+		} else if ($this->config->getSystemValue('maintenance', false)) {
272 272
 			//Possible scenario: Nextcloud core is updated but an app failed
273 273
 			$output->writeln('<warning>Nextcloud is in maintenance mode</warning>');
274 274
 			$output->write('<comment>Maybe an upgrade is already in process. Please check the '
@@ -293,8 +293,8 @@  discard block
 block discarded – undo
293 293
 		$trustedDomains = $this->config->getSystemValue('trusted_domains', array());
294 294
 		if (empty($trustedDomains)) {
295 295
 			$output->write(
296
-				'<warning>The setting "trusted_domains" could not be ' .
297
-				'set automatically by the upgrade script, ' .
296
+				'<warning>The setting "trusted_domains" could not be '.
297
+				'set automatically by the upgrade script, '.
298 298
 				'please set it manually</warning>'
299 299
 			);
300 300
 		}
Please login to merge, or discard this patch.
core/ajax/update.php 2 patches
Indentation   +182 added lines, -182 removed lines patch added patch discarded remove patch
@@ -33,7 +33,7 @@  discard block
 block discarded – undo
33 33
 use Symfony\Component\EventDispatcher\GenericEvent;
34 34
 
35 35
 if (strpos(@ini_get('disable_functions'), 'set_time_limit') === false) {
36
-	@set_time_limit(0);
36
+    @set_time_limit(0);
37 37
 }
38 38
 
39 39
 require_once '../../lib/base.php';
@@ -47,192 +47,192 @@  discard block
 block discarded – undo
47 47
 $eventSource->send('success', (string)$l->t('Preparing update'));
48 48
 
49 49
 class FeedBackHandler {
50
-	/** @var integer */
51
-	private $progressStateMax = 100;
52
-	/** @var integer */
53
-	private $progressStateStep = 0;
54
-	/** @var string */
55
-	private $currentStep;
56
-	/** @var \OCP\IEventSource */
57
-	private $eventSource;
58
-	/** @var \OCP\IL10N */
59
-	private $l10n;
60
-
61
-	public function __construct(\OCP\IEventSource $eventSource, \OCP\IL10N $l10n) {
62
-		$this->eventSource = $eventSource;
63
-		$this->l10n = $l10n;
64
-	}
65
-
66
-	public function handleRepairFeedback($event) {
67
-		if (!$event instanceof GenericEvent) {
68
-			return;
69
-		}
70
-
71
-		switch ($event->getSubject()) {
72
-			case '\OC\Repair::startProgress':
73
-				$this->progressStateMax = $event->getArgument(0);
74
-				$this->progressStateStep = 0;
75
-				$this->currentStep = $event->getArgument(1);
76
-				break;
77
-			case '\OC\Repair::advance':
78
-				$this->progressStateStep += $event->getArgument(0);
79
-				$desc = $event->getArgument(1);
80
-				if (empty($desc)) {
81
-					$desc = $this->currentStep;
82
-				}
83
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84
-				break;
85
-			case '\OC\Repair::finishProgress':
86
-				$this->progressStateMax = $this->progressStateStep;
87
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88
-				break;
89
-			case '\OC\Repair::step':
90
-				break;
91
-			case '\OC\Repair::info':
92
-				break;
93
-			case '\OC\Repair::warning':
94
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
95
-				break;
96
-			case '\OC\Repair::error':
97
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
98
-				break;
99
-		}
100
-	}
50
+    /** @var integer */
51
+    private $progressStateMax = 100;
52
+    /** @var integer */
53
+    private $progressStateStep = 0;
54
+    /** @var string */
55
+    private $currentStep;
56
+    /** @var \OCP\IEventSource */
57
+    private $eventSource;
58
+    /** @var \OCP\IL10N */
59
+    private $l10n;
60
+
61
+    public function __construct(\OCP\IEventSource $eventSource, \OCP\IL10N $l10n) {
62
+        $this->eventSource = $eventSource;
63
+        $this->l10n = $l10n;
64
+    }
65
+
66
+    public function handleRepairFeedback($event) {
67
+        if (!$event instanceof GenericEvent) {
68
+            return;
69
+        }
70
+
71
+        switch ($event->getSubject()) {
72
+            case '\OC\Repair::startProgress':
73
+                $this->progressStateMax = $event->getArgument(0);
74
+                $this->progressStateStep = 0;
75
+                $this->currentStep = $event->getArgument(1);
76
+                break;
77
+            case '\OC\Repair::advance':
78
+                $this->progressStateStep += $event->getArgument(0);
79
+                $desc = $event->getArgument(1);
80
+                if (empty($desc)) {
81
+                    $desc = $this->currentStep;
82
+                }
83
+                $this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84
+                break;
85
+            case '\OC\Repair::finishProgress':
86
+                $this->progressStateMax = $this->progressStateStep;
87
+                $this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88
+                break;
89
+            case '\OC\Repair::step':
90
+                break;
91
+            case '\OC\Repair::info':
92
+                break;
93
+            case '\OC\Repair::warning':
94
+                $this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
95
+                break;
96
+            case '\OC\Repair::error':
97
+                $this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
98
+                break;
99
+        }
100
+    }
101 101
 }
102 102
 
103 103
 if (\OCP\Util::needUpgrade()) {
104 104
 
105
-	$config = \OC::$server->getSystemConfig();
106
-	if ($config->getValue('upgrade.disable-web', false)) {
107
-		$eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108
-		$eventSource->close();
109
-		exit();
110
-	}
111
-
112
-	// if a user is currently logged in, their session must be ignored to
113
-	// avoid side effects
114
-	\OC_User::setIncognitoMode(true);
115
-
116
-	$logger = \OC::$server->getLogger();
117
-	$config = \OC::$server->getConfig();
118
-	$updater = new \OC\Updater(
119
-			$config,
120
-			\OC::$server->getIntegrityCodeChecker(),
121
-			$logger,
122
-			\OC::$server->query(\OC\Installer::class),
123
-			\OC::$server->getJobList()
124
-	);
125
-	$incompatibleApps = [];
126
-
127
-	$dispatcher = \OC::$server->getEventDispatcher();
128
-	$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129
-		if ($event instanceof GenericEvent) {
130
-			$eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131
-		}
132
-	});
133
-	$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134
-		if ($event instanceof GenericEvent) {
135
-			$eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136
-		}
137
-	});
138
-	$feedBack = new FeedBackHandler($eventSource, $l);
139
-	$dispatcher->addListener('\OC\Repair::startProgress', [$feedBack, 'handleRepairFeedback']);
140
-	$dispatcher->addListener('\OC\Repair::advance', [$feedBack, 'handleRepairFeedback']);
141
-	$dispatcher->addListener('\OC\Repair::finishProgress', [$feedBack, 'handleRepairFeedback']);
142
-	$dispatcher->addListener('\OC\Repair::step', [$feedBack, 'handleRepairFeedback']);
143
-	$dispatcher->addListener('\OC\Repair::info', [$feedBack, 'handleRepairFeedback']);
144
-	$dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145
-	$dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146
-
147
-	$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
-		$eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
149
-	});
150
-	$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
-		$eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
152
-	});
153
-	$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
-		$eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
155
-	});
156
-	$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
-		$eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds)...'));
158
-	});
159
-	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
-		$eventSource->send('success', (string)$l->t('Updating database schema'));
161
-	});
162
-	$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
-		$eventSource->send('success', (string)$l->t('Updated database'));
164
-	});
165
-	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167
-	});
168
-	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
-		$eventSource->send('success', (string)$l->t('Checked database schema update'));
170
-	});
171
-	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
-		$eventSource->send('success', (string)$l->t('Checking updates of apps'));
173
-	});
174
-	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
-		$eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
176
-	});
177
-	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
-		$eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
179
-	});
180
-	$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
-		$eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
182
-	});
183
-	$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185
-	});
186
-	$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
-		$eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
188
-	});
189
-	$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
-		$eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version)));
191
-	});
192
-	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
-		$incompatibleApps[]= $app;
194
-	});
195
-	$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
196
-		$eventSource->send('failure', $message);
197
-		$eventSource->close();
198
-		$config->setSystemValue('maintenance', false);
199
-	});
200
-	$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
-		$eventSource->send('success', (string)$l->t('Set log level to debug'));
202
-	});
203
-	$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
-		$eventSource->send('success', (string)$l->t('Reset log level'));
205
-	});
206
-	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
-		$eventSource->send('success', (string)$l->t('Starting code integrity check'));
208
-	});
209
-	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
-		$eventSource->send('success', (string)$l->t('Finished code integrity check'));
211
-	});
212
-
213
-	try {
214
-		$updater->upgrade();
215
-	} catch (\Exception $e) {
216
-		\OC::$server->getLogger()->logException($e, [
217
-			'level' => ILogger::ERROR,
218
-			'app' => 'update',
219
-		]);
220
-		$eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
221
-		$eventSource->close();
222
-		exit();
223
-	}
224
-
225
-	$disabledApps = [];
226
-	foreach ($incompatibleApps as $app) {
227
-		$disabledApps[$app] = (string) $l->t('%s (incompatible)', [$app]);
228
-	}
229
-
230
-	if (!empty($disabledApps)) {
231
-		$eventSource->send('notice',
232
-			(string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233
-	}
105
+    $config = \OC::$server->getSystemConfig();
106
+    if ($config->getValue('upgrade.disable-web', false)) {
107
+        $eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108
+        $eventSource->close();
109
+        exit();
110
+    }
111
+
112
+    // if a user is currently logged in, their session must be ignored to
113
+    // avoid side effects
114
+    \OC_User::setIncognitoMode(true);
115
+
116
+    $logger = \OC::$server->getLogger();
117
+    $config = \OC::$server->getConfig();
118
+    $updater = new \OC\Updater(
119
+            $config,
120
+            \OC::$server->getIntegrityCodeChecker(),
121
+            $logger,
122
+            \OC::$server->query(\OC\Installer::class),
123
+            \OC::$server->getJobList()
124
+    );
125
+    $incompatibleApps = [];
126
+
127
+    $dispatcher = \OC::$server->getEventDispatcher();
128
+    $dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129
+        if ($event instanceof GenericEvent) {
130
+            $eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131
+        }
132
+    });
133
+    $dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134
+        if ($event instanceof GenericEvent) {
135
+            $eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136
+        }
137
+    });
138
+    $feedBack = new FeedBackHandler($eventSource, $l);
139
+    $dispatcher->addListener('\OC\Repair::startProgress', [$feedBack, 'handleRepairFeedback']);
140
+    $dispatcher->addListener('\OC\Repair::advance', [$feedBack, 'handleRepairFeedback']);
141
+    $dispatcher->addListener('\OC\Repair::finishProgress', [$feedBack, 'handleRepairFeedback']);
142
+    $dispatcher->addListener('\OC\Repair::step', [$feedBack, 'handleRepairFeedback']);
143
+    $dispatcher->addListener('\OC\Repair::info', [$feedBack, 'handleRepairFeedback']);
144
+    $dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145
+    $dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146
+
147
+    $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
+        $eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
149
+    });
150
+    $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
+        $eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
152
+    });
153
+    $updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
+        $eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
155
+    });
156
+    $updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
+        $eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds)...'));
158
+    });
159
+    $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
+        $eventSource->send('success', (string)$l->t('Updating database schema'));
161
+    });
162
+    $updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
+        $eventSource->send('success', (string)$l->t('Updated database'));
164
+    });
165
+    $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
+        $eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167
+    });
168
+    $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
+        $eventSource->send('success', (string)$l->t('Checked database schema update'));
170
+    });
171
+    $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
+        $eventSource->send('success', (string)$l->t('Checking updates of apps'));
173
+    });
174
+    $updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
+        $eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
176
+    });
177
+    $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
+        $eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
179
+    });
180
+    $updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
+        $eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
182
+    });
183
+    $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
+        $eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185
+    });
186
+    $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
+        $eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
188
+    });
189
+    $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
+        $eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version)));
191
+    });
192
+    $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
+        $incompatibleApps[]= $app;
194
+    });
195
+    $updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
196
+        $eventSource->send('failure', $message);
197
+        $eventSource->close();
198
+        $config->setSystemValue('maintenance', false);
199
+    });
200
+    $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
+        $eventSource->send('success', (string)$l->t('Set log level to debug'));
202
+    });
203
+    $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
+        $eventSource->send('success', (string)$l->t('Reset log level'));
205
+    });
206
+    $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
+        $eventSource->send('success', (string)$l->t('Starting code integrity check'));
208
+    });
209
+    $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
+        $eventSource->send('success', (string)$l->t('Finished code integrity check'));
211
+    });
212
+
213
+    try {
214
+        $updater->upgrade();
215
+    } catch (\Exception $e) {
216
+        \OC::$server->getLogger()->logException($e, [
217
+            'level' => ILogger::ERROR,
218
+            'app' => 'update',
219
+        ]);
220
+        $eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
221
+        $eventSource->close();
222
+        exit();
223
+    }
224
+
225
+    $disabledApps = [];
226
+    foreach ($incompatibleApps as $app) {
227
+        $disabledApps[$app] = (string) $l->t('%s (incompatible)', [$app]);
228
+    }
229
+
230
+    if (!empty($disabledApps)) {
231
+        $eventSource->send('notice',
232
+            (string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233
+    }
234 234
 } else {
235
-	$eventSource->send('notice', (string)$l->t('Already up to date'));
235
+    $eventSource->send('notice', (string)$l->t('Already up to date'));
236 236
 }
237 237
 
238 238
 $eventSource->send('done', '');
Please login to merge, or discard this patch.
Spacing   +52 added lines, -52 removed lines patch added patch discarded remove patch
@@ -44,7 +44,7 @@  discard block
 block discarded – undo
44 44
 // need to send an initial message to force-init the event source,
45 45
 // which will then trigger its own CSRF check and produces its own CSRF error
46 46
 // message
47
-$eventSource->send('success', (string)$l->t('Preparing update'));
47
+$eventSource->send('success', (string) $l->t('Preparing update'));
48 48
 
49 49
 class FeedBackHandler {
50 50
 	/** @var integer */
@@ -80,21 +80,21 @@  discard block
 block discarded – undo
80 80
 				if (empty($desc)) {
81 81
 					$desc = $this->currentStep;
82 82
 				}
83
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
83
+				$this->eventSource->send('success', (string) $this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $desc]));
84 84
 				break;
85 85
 			case '\OC\Repair::finishProgress':
86 86
 				$this->progressStateMax = $this->progressStateStep;
87
-				$this->eventSource->send('success', (string)$this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
87
+				$this->eventSource->send('success', (string) $this->l10n->t('[%d / %d]: %s', [$this->progressStateStep, $this->progressStateMax, $this->currentStep]));
88 88
 				break;
89 89
 			case '\OC\Repair::step':
90 90
 				break;
91 91
 			case '\OC\Repair::info':
92 92
 				break;
93 93
 			case '\OC\Repair::warning':
94
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair warning: ') . $event->getArgument(0));
94
+				$this->eventSource->send('notice', (string) $this->l10n->t('Repair warning: ').$event->getArgument(0));
95 95
 				break;
96 96
 			case '\OC\Repair::error':
97
-				$this->eventSource->send('notice', (string)$this->l10n->t('Repair error: ') . $event->getArgument(0));
97
+				$this->eventSource->send('notice', (string) $this->l10n->t('Repair error: ').$event->getArgument(0));
98 98
 				break;
99 99
 		}
100 100
 	}
@@ -104,7 +104,7 @@  discard block
 block discarded – undo
104 104
 
105 105
 	$config = \OC::$server->getSystemConfig();
106 106
 	if ($config->getValue('upgrade.disable-web', false)) {
107
-		$eventSource->send('failure', (string)$l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
107
+		$eventSource->send('failure', (string) $l->t('Please use the command line updater because automatic updating is disabled in the config.php.'));
108 108
 		$eventSource->close();
109 109
 		exit();
110 110
 	}
@@ -127,12 +127,12 @@  discard block
 block discarded – undo
127 127
 	$dispatcher = \OC::$server->getEventDispatcher();
128 128
 	$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($eventSource, $l) {
129 129
 		if ($event instanceof GenericEvent) {
130
-			$eventSource->send('success', (string)$l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
130
+			$eventSource->send('success', (string) $l->t('[%d / %d]: %s', [$event[0], $event[1], $event->getSubject()]));
131 131
 		}
132 132
 	});
133 133
 	$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($eventSource, $l) {
134 134
 		if ($event instanceof GenericEvent) {
135
-			$eventSource->send('success', (string)$l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
135
+			$eventSource->send('success', (string) $l->t('[%d / %d]: Checking table %s', [$event[0], $event[1], $event->getSubject()]));
136 136
 		}
137 137
 	});
138 138
 	$feedBack = new FeedBackHandler($eventSource, $l);
@@ -144,70 +144,70 @@  discard block
 block discarded – undo
144 144
 	$dispatcher->addListener('\OC\Repair::warning', [$feedBack, 'handleRepairFeedback']);
145 145
 	$dispatcher->addListener('\OC\Repair::error', [$feedBack, 'handleRepairFeedback']);
146 146
 
147
-	$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($eventSource, $l) {
148
-		$eventSource->send('success', (string)$l->t('Turned on maintenance mode'));
147
+	$updater->listen('\OC\Updater', 'maintenanceEnabled', function() use ($eventSource, $l) {
148
+		$eventSource->send('success', (string) $l->t('Turned on maintenance mode'));
149 149
 	});
150
-	$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($eventSource, $l) {
151
-		$eventSource->send('success', (string)$l->t('Turned off maintenance mode'));
150
+	$updater->listen('\OC\Updater', 'maintenanceDisabled', function() use ($eventSource, $l) {
151
+		$eventSource->send('success', (string) $l->t('Turned off maintenance mode'));
152 152
 	});
153
-	$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($eventSource, $l) {
154
-		$eventSource->send('success', (string)$l->t('Maintenance mode is kept active'));
153
+	$updater->listen('\OC\Updater', 'maintenanceActive', function() use ($eventSource, $l) {
154
+		$eventSource->send('success', (string) $l->t('Maintenance mode is kept active'));
155 155
 	});
156
-	$updater->listen('\OC\Updater', 'waitForCronToFinish', function () use ($eventSource, $l) {
157
-		$eventSource->send('success', (string)$l->t('Waiting for cron to finish (checks again in 5 seconds)...'));
156
+	$updater->listen('\OC\Updater', 'waitForCronToFinish', function() use ($eventSource, $l) {
157
+		$eventSource->send('success', (string) $l->t('Waiting for cron to finish (checks again in 5 seconds)...'));
158 158
 	});
159
-	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use($eventSource, $l) {
160
-		$eventSource->send('success', (string)$l->t('Updating database schema'));
159
+	$updater->listen('\OC\Updater', 'dbUpgradeBefore', function() use($eventSource, $l) {
160
+		$eventSource->send('success', (string) $l->t('Updating database schema'));
161 161
 	});
162
-	$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($eventSource, $l) {
163
-		$eventSource->send('success', (string)$l->t('Updated database'));
162
+	$updater->listen('\OC\Updater', 'dbUpgrade', function() use ($eventSource, $l) {
163
+		$eventSource->send('success', (string) $l->t('Updated database'));
164 164
 	});
165
-	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($eventSource, $l) {
166
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
165
+	$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function() use($eventSource, $l) {
166
+		$eventSource->send('success', (string) $l->t('Checking whether the database schema can be updated (this can take a long time depending on the database size)'));
167 167
 	});
168
-	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($eventSource, $l) {
169
-		$eventSource->send('success', (string)$l->t('Checked database schema update'));
168
+	$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function() use ($eventSource, $l) {
169
+		$eventSource->send('success', (string) $l->t('Checked database schema update'));
170 170
 	});
171
-	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($eventSource, $l) {
172
-		$eventSource->send('success', (string)$l->t('Checking updates of apps'));
171
+	$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function() use ($eventSource, $l) {
172
+		$eventSource->send('success', (string) $l->t('Checking updates of apps'));
173 173
 	});
174
-	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($eventSource, $l) {
175
-		$eventSource->send('success', (string)$l->t('Checking for update of app "%s" in appstore', [$app]));
174
+	$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function($app) use ($eventSource, $l) {
175
+		$eventSource->send('success', (string) $l->t('Checking for update of app "%s" in appstore', [$app]));
176 176
 	});
177
-	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($eventSource, $l) {
178
-		$eventSource->send('success', (string)$l->t('Update app "%s" from appstore', [$app]));
177
+	$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function($app) use ($eventSource, $l) {
178
+		$eventSource->send('success', (string) $l->t('Update app "%s" from appstore', [$app]));
179 179
 	});
180
-	$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($eventSource, $l) {
181
-		$eventSource->send('success', (string)$l->t('Checked for update of app "%s" in appstore', [$app]));
180
+	$updater->listen('\OC\Updater', 'checkAppStoreApp', function($app) use ($eventSource, $l) {
181
+		$eventSource->send('success', (string) $l->t('Checked for update of app "%s" in appstore', [$app]));
182 182
 	});
183
-	$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($eventSource, $l) {
184
-		$eventSource->send('success', (string)$l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
183
+	$updater->listen('\OC\Updater', 'appSimulateUpdate', function($app) use ($eventSource, $l) {
184
+		$eventSource->send('success', (string) $l->t('Checking whether the database schema for %s can be updated (this can take a long time depending on the database size)', [$app]));
185 185
 	});
186
-	$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($eventSource, $l) {
187
-		$eventSource->send('success', (string)$l->t('Checked database schema update for apps'));
186
+	$updater->listen('\OC\Updater', 'appUpgradeCheck', function() use ($eventSource, $l) {
187
+		$eventSource->send('success', (string) $l->t('Checked database schema update for apps'));
188 188
 	});
189
-	$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($eventSource, $l) {
190
-		$eventSource->send('success', (string)$l->t('Updated "%s" to %s', array($app, $version)));
189
+	$updater->listen('\OC\Updater', 'appUpgrade', function($app, $version) use ($eventSource, $l) {
190
+		$eventSource->send('success', (string) $l->t('Updated "%s" to %s', array($app, $version)));
191 191
 	});
192
-	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use (&$incompatibleApps) {
193
-		$incompatibleApps[]= $app;
192
+	$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function($app) use (&$incompatibleApps) {
193
+		$incompatibleApps[] = $app;
194 194
 	});
195
-	$updater->listen('\OC\Updater', 'failure', function ($message) use ($eventSource, $config) {
195
+	$updater->listen('\OC\Updater', 'failure', function($message) use ($eventSource, $config) {
196 196
 		$eventSource->send('failure', $message);
197 197
 		$eventSource->close();
198 198
 		$config->setSystemValue('maintenance', false);
199 199
 	});
200
-	$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
201
-		$eventSource->send('success', (string)$l->t('Set log level to debug'));
200
+	$updater->listen('\OC\Updater', 'setDebugLogLevel', function($logLevel, $logLevelName) use($eventSource, $l) {
201
+		$eventSource->send('success', (string) $l->t('Set log level to debug'));
202 202
 	});
203
-	$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($eventSource, $l) {
204
-		$eventSource->send('success', (string)$l->t('Reset log level'));
203
+	$updater->listen('\OC\Updater', 'resetLogLevel', function($logLevel, $logLevelName) use($eventSource, $l) {
204
+		$eventSource->send('success', (string) $l->t('Reset log level'));
205 205
 	});
206
-	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($eventSource, $l) {
207
-		$eventSource->send('success', (string)$l->t('Starting code integrity check'));
206
+	$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function() use($eventSource, $l) {
207
+		$eventSource->send('success', (string) $l->t('Starting code integrity check'));
208 208
 	});
209
-	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($eventSource, $l) {
210
-		$eventSource->send('success', (string)$l->t('Finished code integrity check'));
209
+	$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function() use($eventSource, $l) {
210
+		$eventSource->send('success', (string) $l->t('Finished code integrity check'));
211 211
 	});
212 212
 
213 213
 	try {
@@ -217,7 +217,7 @@  discard block
 block discarded – undo
217 217
 			'level' => ILogger::ERROR,
218 218
 			'app' => 'update',
219 219
 		]);
220
-		$eventSource->send('failure', get_class($e) . ': ' . $e->getMessage());
220
+		$eventSource->send('failure', get_class($e).': '.$e->getMessage());
221 221
 		$eventSource->close();
222 222
 		exit();
223 223
 	}
@@ -229,10 +229,10 @@  discard block
 block discarded – undo
229 229
 
230 230
 	if (!empty($disabledApps)) {
231 231
 		$eventSource->send('notice',
232
-			(string)$l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
232
+			(string) $l->t('Following apps have been disabled: %s', [implode(', ', $disabledApps)]));
233 233
 	}
234 234
 } else {
235
-	$eventSource->send('notice', (string)$l->t('Already up to date'));
235
+	$eventSource->send('notice', (string) $l->t('Already up to date'));
236 236
 }
237 237
 
238 238
 $eventSource->send('done', '');
Please login to merge, or discard this patch.
lib/private/BackgroundJob/JobList.php 1 patch
Indentation   +332 added lines, -332 removed lines patch added patch discarded remove patch
@@ -39,336 +39,336 @@
 block discarded – undo
39 39
 
40 40
 class JobList implements IJobList {
41 41
 
42
-	/** @var IDBConnection */
43
-	protected $connection;
44
-
45
-	/**@var IConfig */
46
-	protected $config;
47
-
48
-	/**@var ITimeFactory */
49
-	protected $timeFactory;
50
-
51
-	/** @var int - 12 hours * 3600 seconds*/
52
-	private $jobTimeOut = 43200;
53
-
54
-	/**
55
-	 * @param IDBConnection $connection
56
-	 * @param IConfig $config
57
-	 * @param ITimeFactory $timeFactory
58
-	 */
59
-	public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) {
60
-		$this->connection = $connection;
61
-		$this->config = $config;
62
-		$this->timeFactory = $timeFactory;
63
-	}
64
-
65
-	/**
66
-	 * @param IJob|string $job
67
-	 * @param mixed $argument
68
-	 */
69
-	public function add($job, $argument = null) {
70
-		if (!$this->has($job, $argument)) {
71
-			if ($job instanceof IJob) {
72
-				$class = get_class($job);
73
-			} else {
74
-				$class = $job;
75
-			}
76
-
77
-			$argument = json_encode($argument);
78
-			if (strlen($argument) > 4000) {
79
-				throw new \InvalidArgumentException('Background job arguments can\'t exceed 4000 characters (json encoded)');
80
-			}
81
-
82
-			$query = $this->connection->getQueryBuilder();
83
-			$query->insert('jobs')
84
-				->values([
85
-					'class' => $query->createNamedParameter($class),
86
-					'argument' => $query->createNamedParameter($argument),
87
-					'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
88
-					'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT),
89
-				]);
90
-			$query->execute();
91
-		}
92
-	}
93
-
94
-	/**
95
-	 * @param IJob|string $job
96
-	 * @param mixed $argument
97
-	 */
98
-	public function remove($job, $argument = null) {
99
-		if ($job instanceof IJob) {
100
-			$class = get_class($job);
101
-		} else {
102
-			$class = $job;
103
-		}
104
-
105
-		$query = $this->connection->getQueryBuilder();
106
-		$query->delete('jobs')
107
-			->where($query->expr()->eq('class', $query->createNamedParameter($class)));
108
-		if (!is_null($argument)) {
109
-			$argument = json_encode($argument);
110
-			$query->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)));
111
-		}
112
-		$query->execute();
113
-	}
114
-
115
-	/**
116
-	 * @param int $id
117
-	 */
118
-	protected function removeById($id) {
119
-		$query = $this->connection->getQueryBuilder();
120
-		$query->delete('jobs')
121
-			->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
122
-		$query->execute();
123
-	}
124
-
125
-	/**
126
-	 * check if a job is in the list
127
-	 *
128
-	 * @param IJob|string $job
129
-	 * @param mixed $argument
130
-	 * @return bool
131
-	 */
132
-	public function has($job, $argument) {
133
-		if ($job instanceof IJob) {
134
-			$class = get_class($job);
135
-		} else {
136
-			$class = $job;
137
-		}
138
-		$argument = json_encode($argument);
139
-
140
-		$query = $this->connection->getQueryBuilder();
141
-		$query->select('id')
142
-			->from('jobs')
143
-			->where($query->expr()->eq('class', $query->createNamedParameter($class)))
144
-			->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)))
145
-			->setMaxResults(1);
146
-
147
-		$result = $query->execute();
148
-		$row = $result->fetch();
149
-		$result->closeCursor();
150
-
151
-		return (bool) $row;
152
-	}
153
-
154
-	/**
155
-	 * get all jobs in the list
156
-	 *
157
-	 * @return IJob[]
158
-	 * @deprecated 9.0.0 - This method is dangerous since it can cause load and
159
-	 * memory problems when creating too many instances.
160
-	 */
161
-	public function getAll() {
162
-		$query = $this->connection->getQueryBuilder();
163
-		$query->select('*')
164
-			->from('jobs');
165
-		$result = $query->execute();
166
-
167
-		$jobs = [];
168
-		while ($row = $result->fetch()) {
169
-			$job = $this->buildJob($row);
170
-			if ($job) {
171
-				$jobs[] = $job;
172
-			}
173
-		}
174
-		$result->closeCursor();
175
-
176
-		return $jobs;
177
-	}
178
-
179
-	/**
180
-	 * get the next job in the list
181
-	 *
182
-	 * @return IJob|null
183
-	 */
184
-	public function getNext() {
185
-		$query = $this->connection->getQueryBuilder();
186
-		$query->select('*')
187
-			->from('jobs')
188
-			->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
189
-			->orderBy('last_checked', 'ASC')
190
-			->setMaxResults(1);
191
-
192
-		$update = $this->connection->getQueryBuilder();
193
-		$update->update('jobs')
194
-			->set('reserved_at', $update->createNamedParameter($this->timeFactory->getTime()))
195
-			->set('last_checked', $update->createNamedParameter($this->timeFactory->getTime()))
196
-			->where($update->expr()->eq('id', $update->createParameter('jobid')))
197
-			->andWhere($update->expr()->eq('reserved_at', $update->createParameter('reserved_at')))
198
-			->andWhere($update->expr()->eq('last_checked', $update->createParameter('last_checked')));
199
-
200
-		$result = $query->execute();
201
-		$row = $result->fetch();
202
-		$result->closeCursor();
203
-
204
-		if ($row) {
205
-			$update->setParameter('jobid', $row['id']);
206
-			$update->setParameter('reserved_at', $row['reserved_at']);
207
-			$update->setParameter('last_checked', $row['last_checked']);
208
-			$count = $update->execute();
209
-
210
-			if ($count === 0) {
211
-				// Background job already executed elsewhere, try again.
212
-				return $this->getNext();
213
-			}
214
-			$job = $this->buildJob($row);
215
-
216
-			if ($job === null) {
217
-				// Background job from disabled app, try again.
218
-				return $this->getNext();
219
-			}
220
-
221
-			return $job;
222
-		} else {
223
-			return null;
224
-		}
225
-	}
226
-
227
-	/**
228
-	 * @param int $id
229
-	 * @return IJob|null
230
-	 */
231
-	public function getById($id) {
232
-		$query = $this->connection->getQueryBuilder();
233
-		$query->select('*')
234
-			->from('jobs')
235
-			->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
236
-		$result = $query->execute();
237
-		$row = $result->fetch();
238
-		$result->closeCursor();
239
-
240
-		if ($row) {
241
-			return $this->buildJob($row);
242
-		} else {
243
-			return null;
244
-		}
245
-	}
246
-
247
-	/**
248
-	 * get the job object from a row in the db
249
-	 *
250
-	 * @param array $row
251
-	 * @return IJob|null
252
-	 */
253
-	private function buildJob($row) {
254
-		try {
255
-			try {
256
-				// Try to load the job as a service
257
-				/** @var IJob $job */
258
-				$job = \OC::$server->query($row['class']);
259
-			} catch (QueryException $e) {
260
-				if (class_exists($row['class'])) {
261
-					$class = $row['class'];
262
-					$job = new $class();
263
-				} else {
264
-					// job from disabled app or old version of an app, no need to do anything
265
-					return null;
266
-				}
267
-			}
268
-
269
-			$job->setId($row['id']);
270
-			$job->setLastRun($row['last_run']);
271
-			$job->setArgument(json_decode($row['argument'], true));
272
-			return $job;
273
-		} catch (AutoloadNotAllowedException $e) {
274
-			// job is from a disabled app, ignore
275
-			return null;
276
-		}
277
-	}
278
-
279
-	/**
280
-	 * set the job that was last ran
281
-	 *
282
-	 * @param IJob $job
283
-	 */
284
-	public function setLastJob(IJob $job) {
285
-		$this->unlockJob($job);
286
-		$this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
287
-	}
288
-
289
-	/**
290
-	 * Remove the reservation for a job
291
-	 *
292
-	 * @param IJob $job
293
-	 * @suppress SqlInjectionChecker
294
-	 */
295
-	public function unlockJob(IJob $job) {
296
-		$query = $this->connection->getQueryBuilder();
297
-		$query->update('jobs')
298
-			->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
299
-			->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
300
-		$query->execute();
301
-	}
302
-
303
-	/**
304
-	 * get the id of the last ran job
305
-	 *
306
-	 * @return int
307
-	 * @deprecated 9.1.0 - The functionality behind the value is deprecated, it
308
-	 *    only tells you which job finished last, but since we now allow multiple
309
-	 *    executors to run in parallel, it's not used to calculate the next job.
310
-	 */
311
-	public function getLastJob() {
312
-		return (int) $this->config->getAppValue('backgroundjob', 'lastjob', 0);
313
-	}
314
-
315
-	/**
316
-	 * set the lastRun of $job to now
317
-	 *
318
-	 * @param IJob $job
319
-	 */
320
-	public function setLastRun(IJob $job) {
321
-		$query = $this->connection->getQueryBuilder();
322
-		$query->update('jobs')
323
-			->set('last_run', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
324
-			->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
325
-		$query->execute();
326
-	}
327
-
328
-	/**
329
-	 * @param IJob $job
330
-	 * @param $timeTaken
331
-	 */
332
-	public function setExecutionTime(IJob $job, $timeTaken) {
333
-		$query = $this->connection->getQueryBuilder();
334
-		$query->update('jobs')
335
-			->set('execution_duration', $query->createNamedParameter($timeTaken, IQueryBuilder::PARAM_INT))
336
-			->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
337
-		$query->execute();
338
-	}
339
-
340
-	/**
341
-	 * checks if a job is still running (reserved_at time is smaller than 12 hours ago)
342
-	 *
343
-	 * Background information:
344
-	 *
345
-	 * The 12 hours is the same timeout that is also used to re-schedule an non-terminated
346
-	 * job (see getNext()). The idea here is to give a job enough time to run very
347
-	 * long but still be able to recognize that it maybe crashed and re-schedule it
348
-	 * after the timeout. It's more likely to be crashed at that time than it ran
349
-	 * that long.
350
-	 *
351
-	 * In theory it could lead to an nearly endless loop (as in - at most 12 hours).
352
-	 * The cron command will not start new jobs when maintenance mode is active and
353
-	 * this method is only executed in maintenance mode (see where it is called in
354
-	 * the upgrader class. So this means in the worst case we wait 12 hours when a
355
-	 * job has crashed. On the other hand: then the instance should be fixed anyways.
356
-	 *
357
-	 * @return bool
358
-	 */
359
-	public function isAnyJobRunning(): bool {
360
-		$query = $this->connection->getQueryBuilder();
361
-		$query->select('*')
362
-			->from('jobs')
363
-			->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
364
-			->setMaxResults(1);
365
-		$result = $query->execute();
366
-		$row = $result->fetch();
367
-		$result->closeCursor();
368
-
369
-		if ($row) {
370
-			return true;
371
-		}
372
-		return false;
373
-	}
42
+    /** @var IDBConnection */
43
+    protected $connection;
44
+
45
+    /**@var IConfig */
46
+    protected $config;
47
+
48
+    /**@var ITimeFactory */
49
+    protected $timeFactory;
50
+
51
+    /** @var int - 12 hours * 3600 seconds*/
52
+    private $jobTimeOut = 43200;
53
+
54
+    /**
55
+     * @param IDBConnection $connection
56
+     * @param IConfig $config
57
+     * @param ITimeFactory $timeFactory
58
+     */
59
+    public function __construct(IDBConnection $connection, IConfig $config, ITimeFactory $timeFactory) {
60
+        $this->connection = $connection;
61
+        $this->config = $config;
62
+        $this->timeFactory = $timeFactory;
63
+    }
64
+
65
+    /**
66
+     * @param IJob|string $job
67
+     * @param mixed $argument
68
+     */
69
+    public function add($job, $argument = null) {
70
+        if (!$this->has($job, $argument)) {
71
+            if ($job instanceof IJob) {
72
+                $class = get_class($job);
73
+            } else {
74
+                $class = $job;
75
+            }
76
+
77
+            $argument = json_encode($argument);
78
+            if (strlen($argument) > 4000) {
79
+                throw new \InvalidArgumentException('Background job arguments can\'t exceed 4000 characters (json encoded)');
80
+            }
81
+
82
+            $query = $this->connection->getQueryBuilder();
83
+            $query->insert('jobs')
84
+                ->values([
85
+                    'class' => $query->createNamedParameter($class),
86
+                    'argument' => $query->createNamedParameter($argument),
87
+                    'last_run' => $query->createNamedParameter(0, IQueryBuilder::PARAM_INT),
88
+                    'last_checked' => $query->createNamedParameter($this->timeFactory->getTime(), IQueryBuilder::PARAM_INT),
89
+                ]);
90
+            $query->execute();
91
+        }
92
+    }
93
+
94
+    /**
95
+     * @param IJob|string $job
96
+     * @param mixed $argument
97
+     */
98
+    public function remove($job, $argument = null) {
99
+        if ($job instanceof IJob) {
100
+            $class = get_class($job);
101
+        } else {
102
+            $class = $job;
103
+        }
104
+
105
+        $query = $this->connection->getQueryBuilder();
106
+        $query->delete('jobs')
107
+            ->where($query->expr()->eq('class', $query->createNamedParameter($class)));
108
+        if (!is_null($argument)) {
109
+            $argument = json_encode($argument);
110
+            $query->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)));
111
+        }
112
+        $query->execute();
113
+    }
114
+
115
+    /**
116
+     * @param int $id
117
+     */
118
+    protected function removeById($id) {
119
+        $query = $this->connection->getQueryBuilder();
120
+        $query->delete('jobs')
121
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
122
+        $query->execute();
123
+    }
124
+
125
+    /**
126
+     * check if a job is in the list
127
+     *
128
+     * @param IJob|string $job
129
+     * @param mixed $argument
130
+     * @return bool
131
+     */
132
+    public function has($job, $argument) {
133
+        if ($job instanceof IJob) {
134
+            $class = get_class($job);
135
+        } else {
136
+            $class = $job;
137
+        }
138
+        $argument = json_encode($argument);
139
+
140
+        $query = $this->connection->getQueryBuilder();
141
+        $query->select('id')
142
+            ->from('jobs')
143
+            ->where($query->expr()->eq('class', $query->createNamedParameter($class)))
144
+            ->andWhere($query->expr()->eq('argument', $query->createNamedParameter($argument)))
145
+            ->setMaxResults(1);
146
+
147
+        $result = $query->execute();
148
+        $row = $result->fetch();
149
+        $result->closeCursor();
150
+
151
+        return (bool) $row;
152
+    }
153
+
154
+    /**
155
+     * get all jobs in the list
156
+     *
157
+     * @return IJob[]
158
+     * @deprecated 9.0.0 - This method is dangerous since it can cause load and
159
+     * memory problems when creating too many instances.
160
+     */
161
+    public function getAll() {
162
+        $query = $this->connection->getQueryBuilder();
163
+        $query->select('*')
164
+            ->from('jobs');
165
+        $result = $query->execute();
166
+
167
+        $jobs = [];
168
+        while ($row = $result->fetch()) {
169
+            $job = $this->buildJob($row);
170
+            if ($job) {
171
+                $jobs[] = $job;
172
+            }
173
+        }
174
+        $result->closeCursor();
175
+
176
+        return $jobs;
177
+    }
178
+
179
+    /**
180
+     * get the next job in the list
181
+     *
182
+     * @return IJob|null
183
+     */
184
+    public function getNext() {
185
+        $query = $this->connection->getQueryBuilder();
186
+        $query->select('*')
187
+            ->from('jobs')
188
+            ->where($query->expr()->lte('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
189
+            ->orderBy('last_checked', 'ASC')
190
+            ->setMaxResults(1);
191
+
192
+        $update = $this->connection->getQueryBuilder();
193
+        $update->update('jobs')
194
+            ->set('reserved_at', $update->createNamedParameter($this->timeFactory->getTime()))
195
+            ->set('last_checked', $update->createNamedParameter($this->timeFactory->getTime()))
196
+            ->where($update->expr()->eq('id', $update->createParameter('jobid')))
197
+            ->andWhere($update->expr()->eq('reserved_at', $update->createParameter('reserved_at')))
198
+            ->andWhere($update->expr()->eq('last_checked', $update->createParameter('last_checked')));
199
+
200
+        $result = $query->execute();
201
+        $row = $result->fetch();
202
+        $result->closeCursor();
203
+
204
+        if ($row) {
205
+            $update->setParameter('jobid', $row['id']);
206
+            $update->setParameter('reserved_at', $row['reserved_at']);
207
+            $update->setParameter('last_checked', $row['last_checked']);
208
+            $count = $update->execute();
209
+
210
+            if ($count === 0) {
211
+                // Background job already executed elsewhere, try again.
212
+                return $this->getNext();
213
+            }
214
+            $job = $this->buildJob($row);
215
+
216
+            if ($job === null) {
217
+                // Background job from disabled app, try again.
218
+                return $this->getNext();
219
+            }
220
+
221
+            return $job;
222
+        } else {
223
+            return null;
224
+        }
225
+    }
226
+
227
+    /**
228
+     * @param int $id
229
+     * @return IJob|null
230
+     */
231
+    public function getById($id) {
232
+        $query = $this->connection->getQueryBuilder();
233
+        $query->select('*')
234
+            ->from('jobs')
235
+            ->where($query->expr()->eq('id', $query->createNamedParameter($id, IQueryBuilder::PARAM_INT)));
236
+        $result = $query->execute();
237
+        $row = $result->fetch();
238
+        $result->closeCursor();
239
+
240
+        if ($row) {
241
+            return $this->buildJob($row);
242
+        } else {
243
+            return null;
244
+        }
245
+    }
246
+
247
+    /**
248
+     * get the job object from a row in the db
249
+     *
250
+     * @param array $row
251
+     * @return IJob|null
252
+     */
253
+    private function buildJob($row) {
254
+        try {
255
+            try {
256
+                // Try to load the job as a service
257
+                /** @var IJob $job */
258
+                $job = \OC::$server->query($row['class']);
259
+            } catch (QueryException $e) {
260
+                if (class_exists($row['class'])) {
261
+                    $class = $row['class'];
262
+                    $job = new $class();
263
+                } else {
264
+                    // job from disabled app or old version of an app, no need to do anything
265
+                    return null;
266
+                }
267
+            }
268
+
269
+            $job->setId($row['id']);
270
+            $job->setLastRun($row['last_run']);
271
+            $job->setArgument(json_decode($row['argument'], true));
272
+            return $job;
273
+        } catch (AutoloadNotAllowedException $e) {
274
+            // job is from a disabled app, ignore
275
+            return null;
276
+        }
277
+    }
278
+
279
+    /**
280
+     * set the job that was last ran
281
+     *
282
+     * @param IJob $job
283
+     */
284
+    public function setLastJob(IJob $job) {
285
+        $this->unlockJob($job);
286
+        $this->config->setAppValue('backgroundjob', 'lastjob', $job->getId());
287
+    }
288
+
289
+    /**
290
+     * Remove the reservation for a job
291
+     *
292
+     * @param IJob $job
293
+     * @suppress SqlInjectionChecker
294
+     */
295
+    public function unlockJob(IJob $job) {
296
+        $query = $this->connection->getQueryBuilder();
297
+        $query->update('jobs')
298
+            ->set('reserved_at', $query->expr()->literal(0, IQueryBuilder::PARAM_INT))
299
+            ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
300
+        $query->execute();
301
+    }
302
+
303
+    /**
304
+     * get the id of the last ran job
305
+     *
306
+     * @return int
307
+     * @deprecated 9.1.0 - The functionality behind the value is deprecated, it
308
+     *    only tells you which job finished last, but since we now allow multiple
309
+     *    executors to run in parallel, it's not used to calculate the next job.
310
+     */
311
+    public function getLastJob() {
312
+        return (int) $this->config->getAppValue('backgroundjob', 'lastjob', 0);
313
+    }
314
+
315
+    /**
316
+     * set the lastRun of $job to now
317
+     *
318
+     * @param IJob $job
319
+     */
320
+    public function setLastRun(IJob $job) {
321
+        $query = $this->connection->getQueryBuilder();
322
+        $query->update('jobs')
323
+            ->set('last_run', $query->createNamedParameter(time(), IQueryBuilder::PARAM_INT))
324
+            ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
325
+        $query->execute();
326
+    }
327
+
328
+    /**
329
+     * @param IJob $job
330
+     * @param $timeTaken
331
+     */
332
+    public function setExecutionTime(IJob $job, $timeTaken) {
333
+        $query = $this->connection->getQueryBuilder();
334
+        $query->update('jobs')
335
+            ->set('execution_duration', $query->createNamedParameter($timeTaken, IQueryBuilder::PARAM_INT))
336
+            ->where($query->expr()->eq('id', $query->createNamedParameter($job->getId(), IQueryBuilder::PARAM_INT)));
337
+        $query->execute();
338
+    }
339
+
340
+    /**
341
+     * checks if a job is still running (reserved_at time is smaller than 12 hours ago)
342
+     *
343
+     * Background information:
344
+     *
345
+     * The 12 hours is the same timeout that is also used to re-schedule an non-terminated
346
+     * job (see getNext()). The idea here is to give a job enough time to run very
347
+     * long but still be able to recognize that it maybe crashed and re-schedule it
348
+     * after the timeout. It's more likely to be crashed at that time than it ran
349
+     * that long.
350
+     *
351
+     * In theory it could lead to an nearly endless loop (as in - at most 12 hours).
352
+     * The cron command will not start new jobs when maintenance mode is active and
353
+     * this method is only executed in maintenance mode (see where it is called in
354
+     * the upgrader class. So this means in the worst case we wait 12 hours when a
355
+     * job has crashed. On the other hand: then the instance should be fixed anyways.
356
+     *
357
+     * @return bool
358
+     */
359
+    public function isAnyJobRunning(): bool {
360
+        $query = $this->connection->getQueryBuilder();
361
+        $query->select('*')
362
+            ->from('jobs')
363
+            ->where($query->expr()->gt('reserved_at', $query->createNamedParameter($this->timeFactory->getTime() - $this->jobTimeOut, IQueryBuilder::PARAM_INT)))
364
+            ->setMaxResults(1);
365
+        $result = $query->execute();
366
+        $row = $result->fetch();
367
+        $result->closeCursor();
368
+
369
+        if ($row) {
370
+            return true;
371
+        }
372
+        return false;
373
+    }
374 374
 }
Please login to merge, or discard this patch.