Completed
Push — master ( 263507...4d99fa )
by Julius
15:25
created

Updater::doCoreUpgrade()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 9
rs 9.6666
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 * @copyright Copyright (c) 2016, Lukas Reschke <[email protected]>
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Frank Karlitschek <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Lukas Reschke <[email protected]>
11
 * @author Morris Jobke <[email protected]>
12
 * @author Robin Appelman <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Steffen Lindner <[email protected]>
15
 * @author Thomas Müller <[email protected]>
16
 * @author Victor Dubiniuk <[email protected]>
17
 * @author Vincent Petry <[email protected]>
18
 *
19
 * @license AGPL-3.0
20
 *
21
 * This code is free software: you can redistribute it and/or modify
22
 * it under the terms of the GNU Affero General Public License, version 3,
23
 * as published by the Free Software Foundation.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28
 * GNU Affero General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Affero General Public License, version 3,
31
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
32
 *
33
 */
34
35
namespace OC;
36
37
use OC\DB\MigrationService;
38
use OC\Hooks\BasicEmitter;
39
use OC\IntegrityCheck\Checker;
40
use OC_App;
41
use OCP\IConfig;
42
use OCP\ILogger;
43
use OCP\Util;
44
use Symfony\Component\EventDispatcher\GenericEvent;
45
46
/**
47
 * Class that handles autoupdating of ownCloud
48
 *
49
 * Hooks provided in scope \OC\Updater
50
 *  - maintenanceStart()
51
 *  - maintenanceEnd()
52
 *  - dbUpgrade()
53
 *  - failure(string $message)
54
 */
55
class Updater extends BasicEmitter {
56
57
	/** @var ILogger $log */
58
	private $log;
59
60
	/** @var IConfig */
61
	private $config;
62
63
	/** @var Checker */
64
	private $checker;
65
66
	/** @var Installer */
67
	private $installer;
68
69
	private $logLevelNames = [
70
		0 => 'Debug',
71
		1 => 'Info',
72
		2 => 'Warning',
73
		3 => 'Error',
74
		4 => 'Fatal',
75
	];
76
77
	/**
78
	 * @param IConfig $config
79
	 * @param Checker $checker
80
	 * @param ILogger $log
81
	 * @param Installer $installer
82
	 */
83
	public function __construct(IConfig $config,
84
								Checker $checker,
85
								ILogger $log = null,
86
								Installer $installer) {
87
		$this->log = $log;
88
		$this->config = $config;
89
		$this->checker = $checker;
90
		$this->installer = $installer;
91
	}
92
93
	/**
94
	 * runs the update actions in maintenance mode, does not upgrade the source files
95
	 * except the main .htaccess file
96
	 *
97
	 * @return bool true if the operation succeeded, false otherwise
98
	 */
99
	public function upgrade() {
100
		$this->emitRepairEvents();
101
		$this->logAllEvents();
102
103
		$logLevel = $this->config->getSystemValue('loglevel', Util::WARN);
104
		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
105
		$this->config->setSystemValue('loglevel', Util::DEBUG);
106
107
		$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
108
109
		if(!$wasMaintenanceModeEnabled) {
110
			$this->config->setSystemValue('maintenance', true);
111
			$this->emit('\OC\Updater', 'maintenanceEnabled');
112
		}
113
114
		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
115
		$currentVersion = implode('.', \OCP\Util::getVersion());
116
		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
117
118
		$success = true;
119
		try {
120
			$this->doUpgrade($currentVersion, $installedVersion);
121
		} catch (HintException $exception) {
122
			$this->log->logException($exception, ['app' => 'core']);
123
			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
124
			$success = false;
125
		} catch (\Exception $exception) {
126
			$this->log->logException($exception, ['app' => 'core']);
127
			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
128
			$success = false;
129
		}
130
131
		$this->emit('\OC\Updater', 'updateEnd', array($success));
132
133
		if(!$wasMaintenanceModeEnabled && $success) {
134
			$this->config->setSystemValue('maintenance', false);
135
			$this->emit('\OC\Updater', 'maintenanceDisabled');
136
		} else {
137
			$this->emit('\OC\Updater', 'maintenanceActive');
138
		}
139
140
		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
141
		$this->config->setSystemValue('loglevel', $logLevel);
142
		$this->config->setSystemValue('installed', true);
143
144
		return $success;
145
	}
146
147
	/**
148
	 * Return version from which this version is allowed to upgrade from
149
	 *
150
	 * @return array allowed previous versions per vendor
151
	 */
152
	private function getAllowedPreviousVersions() {
153
		// this should really be a JSON file
154
		require \OC::$SERVERROOT . '/version.php';
155
		/** @var array $OC_VersionCanBeUpgradedFrom */
156
		return $OC_VersionCanBeUpgradedFrom;
0 ignored issues
show
Bug introduced by
The variable $OC_VersionCanBeUpgradedFrom does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
157
	}
158
159
	/**
160
	 * Return vendor from which this version was published
161
	 *
162
	 * @return string Get the vendor
163
	 */
164
	private function getVendor() {
165
		// this should really be a JSON file
166
		require \OC::$SERVERROOT . '/version.php';
167
		/** @var string $vendor */
168
		return (string) $vendor;
0 ignored issues
show
Bug introduced by
The variable $vendor does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
169
	}
170
171
	/**
172
	 * Whether an upgrade to a specified version is possible
173
	 * @param string $oldVersion
174
	 * @param string $newVersion
175
	 * @param array $allowedPreviousVersions
176
	 * @return bool
177
	 */
178
	public function isUpgradePossible($oldVersion, $newVersion, array $allowedPreviousVersions) {
179
		$version = explode('.', $oldVersion);
180
		$majorMinor = $version[0] . '.' . $version[1];
181
182
		$currentVendor = $this->config->getAppValue('core', 'vendor', '');
183
184
		// Vendor was not set correctly on install, so we have to white-list known versions
185
		if ($currentVendor === '') {
186
			if (in_array($oldVersion, [
187
				'11.0.2.7',
188
				'11.0.1.2',
189
				'11.0.0.10',
190
			], true)) {
191
				$currentVendor = 'nextcloud';
192
			} else if (isset($allowedPreviousVersions['owncloud'][$oldVersion])) {
193
				$currentVendor = 'owncloud';
194
			}
195
		}
196
197
		if ($currentVendor === 'nextcloud') {
198
			return isset($allowedPreviousVersions[$currentVendor][$majorMinor])
199
				&& (version_compare($oldVersion, $newVersion, '<=') ||
200
					$this->config->getSystemValue('debug', false));
201
		}
202
203
		// Check if the instance can be migrated
204
		return isset($allowedPreviousVersions[$currentVendor][$majorMinor]) ||
205
			isset($allowedPreviousVersions[$currentVendor][$oldVersion]);
206
	}
207
208
	/**
209
	 * runs the update actions in maintenance mode, does not upgrade the source files
210
	 * except the main .htaccess file
211
	 *
212
	 * @param string $currentVersion current version to upgrade to
213
	 * @param string $installedVersion previous version from which to upgrade from
214
	 *
215
	 * @throws \Exception
216
	 */
217
	private function doUpgrade($currentVersion, $installedVersion) {
218
		// Stop update if the update is over several major versions
219
		$allowedPreviousVersions = $this->getAllowedPreviousVersions();
220
		if (!$this->isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersions)) {
221
			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
222
		}
223
224
		// Update .htaccess files
225
		try {
226
			Setup::updateHtaccess();
227
			Setup::protectDataDirectory();
228
		} catch (\Exception $e) {
229
			throw new \Exception($e->getMessage());
230
		}
231
232
		// create empty file in data dir, so we can later find
233
		// out that this is indeed an ownCloud data directory
234
		// (in case it didn't exist before)
235
		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
236
237
		// pre-upgrade repairs
238
		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
239
		$repair->run();
240
241
		$this->doCoreUpgrade();
242
243
		try {
244
			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
245
			Setup::installBackgroundJobs();
246
		} catch (\Exception $e) {
247
			throw new \Exception($e->getMessage());
248
		}
249
250
		// update all shipped apps
251
		$this->checkAppsRequirements();
252
		$this->doAppUpgrade();
253
254
		// Update the appfetchers version so it downloads the correct list from the appstore
255
		\OC::$server->getAppFetcher()->setVersion($currentVersion);
256
257
		// upgrade appstore apps
258
		$this->upgradeAppStoreApps(\OC::$server->getAppManager()->getInstalledApps());
259
260
		// install new shipped apps on upgrade
261
		OC_App::loadApps('authentication');
262
		$errors = Installer::installShippedApps(true);
263
		foreach ($errors as $appId => $exception) {
264
			/** @var \Exception $exception */
265
			$this->log->logException($exception, ['app' => $appId]);
266
			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
267
		}
268
269
		// post-upgrade repairs
270
		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
271
		$repair->run();
272
273
		//Invalidate update feed
274
		$this->config->setAppValue('core', 'lastupdatedat', 0);
275
276
		// Check for code integrity if not disabled
277
		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
278
			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
279
			$this->checker->runInstanceVerification();
280
			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
281
		}
282
283
		// only set the final version if everything went well
284
		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
285
		$this->config->setAppValue('core', 'vendor', $this->getVendor());
286
	}
287
288
	protected function doCoreUpgrade() {
289
		$this->emit('\OC\Updater', 'dbUpgradeBefore');
290
291
		// execute core migrations
292
		$ms = new MigrationService('core', \OC::$server->getDatabaseConnection());
293
		$ms->migrate();
294
295
		$this->emit('\OC\Updater', 'dbUpgrade');
296
	}
297
298
	/**
299
	 * @param string $version the oc version to check app compatibility with
300
	 */
301
	protected function checkAppUpgrade($version) {
302
		$apps = \OC_App::getEnabledApps();
303
		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
304
305
		$appManager = \OC::$server->getAppManager();
306
		foreach ($apps as $appId) {
307
			$info = \OC_App::getAppInfo($appId);
308
			$compatible = \OC_App::isAppCompatible($version, $info);
0 ignored issues
show
Bug introduced by
It seems like $info defined by \OC_App::getAppInfo($appId) on line 307 can also be of type null; however, OC_App::isAppCompatible() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
309
			$isShipped = $appManager->isShipped($appId);
310
311
			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
312
				/**
313
				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
314
				 * are not possible anymore within it. - Consider this when touching the code.
315
				 * @link https://github.com/owncloud/core/issues/10980
316
				 * @see \OC_App::updateApp
317
				 */
318
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
319
					$this->includePreUpdate($appId);
320
				}
321
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
322
					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
323
					\OC_DB::simulateUpdateDbFromStructure(\OC_App::getAppPath($appId) . '/appinfo/database.xml');
0 ignored issues
show
Bug introduced by
The method simulateUpdateDbFromStructure() does not exist on OC_DB. Did you maybe mean updateDbFromStructure()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
324
				}
325
			}
326
		}
327
328
		$this->emit('\OC\Updater', 'appUpgradeCheck');
329
	}
330
331
	/**
332
	 * Includes the pre-update file. Done here to prevent namespace mixups.
333
	 * @param string $appId
334
	 */
335
	private function includePreUpdate($appId) {
336
		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
337
	}
338
339
	/**
340
	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
341
	 * (types authentication, filesystem, logging, in that order) afterwards.
342
	 *
343
	 * @throws NeedsUpdateException
344
	 */
345
	protected function doAppUpgrade() {
346
		$apps = \OC_App::getEnabledApps();
347
		$priorityTypes = array('authentication', 'filesystem', 'logging');
348
		$pseudoOtherType = 'other';
349
		$stacks = array($pseudoOtherType => array());
350
351
		foreach ($apps as $appId) {
352
			$priorityType = false;
353
			foreach ($priorityTypes as $type) {
354
				if(!isset($stacks[$type])) {
355
					$stacks[$type] = array();
356
				}
357
				if (\OC_App::isType($appId, $type)) {
358
					$stacks[$type][] = $appId;
359
					$priorityType = true;
360
					break;
361
				}
362
			}
363
			if (!$priorityType) {
364
				$stacks[$pseudoOtherType][] = $appId;
365
			}
366
		}
367
		foreach ($stacks as $type => $stack) {
368
			foreach ($stack as $appId) {
369
				if (\OC_App::shouldUpgrade($appId)) {
370
					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
371
					\OC_App::updateApp($appId);
372
					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
373
				}
374
				if($type !== $pseudoOtherType) {
375
					// load authentication, filesystem and logging apps after
376
					// upgrading them. Other apps my need to rely on modifying
377
					// user and/or filesystem aspects.
378
					\OC_App::loadApp($appId);
379
				}
380
			}
381
		}
382
	}
383
384
	/**
385
	 * check if the current enabled apps are compatible with the current
386
	 * ownCloud version. disable them if not.
387
	 * This is important if you upgrade ownCloud and have non ported 3rd
388
	 * party apps installed.
389
	 *
390
	 * @return array
391
	 * @throws \Exception
392
	 */
393
	private function checkAppsRequirements() {
394
		$isCoreUpgrade = $this->isCodeUpgrade();
395
		$apps = OC_App::getEnabledApps();
396
		$version = Util::getVersion();
397
		$disabledApps = [];
398
		$appManager = \OC::$server->getAppManager();
399
		foreach ($apps as $app) {
400
			// check if the app is compatible with this version of ownCloud
401
			$info = OC_App::getAppInfo($app);
402
			if(!OC_App::isAppCompatible($version, $info)) {
0 ignored issues
show
Documentation introduced by
$version is of type array, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like $info defined by \OC_App::getAppInfo($app) on line 401 can also be of type null; however, OC_App::isAppCompatible() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
403
				if ($appManager->isShipped($app)) {
404
					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
405
				}
406
				OC_App::disable($app);
407
				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
408
			}
409
			// no need to disable any app in case this is a non-core upgrade
410
			if (!$isCoreUpgrade) {
411
				continue;
412
			}
413
			// shipped apps will remain enabled
414
			if ($appManager->isShipped($app)) {
415
				continue;
416
			}
417
			// authentication and session apps will remain enabled as well
418
			if (OC_App::isType($app, ['session', 'authentication'])) {
419
				continue;
420
			}
421
		}
422
		return $disabledApps;
423
	}
424
425
	/**
426
	 * @return bool
427
	 */
428
	private function isCodeUpgrade() {
429
		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
430
		$currentVersion = implode('.', Util::getVersion());
431
		if (version_compare($currentVersion, $installedVersion, '>')) {
432
			return true;
433
		}
434
		return false;
435
	}
436
437
	/**
438
	 * @param array $disabledApps
439
	 * @throws \Exception
440
	 */
441
	private function upgradeAppStoreApps(array $disabledApps) {
442
		foreach($disabledApps as $app) {
443
			try {
444
				$this->emit('\OC\Updater', 'checkAppStoreAppBefore', [$app]);
445
				if ($this->installer->isUpdateAvailable($app)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->installer->isUpdateAvailable($app) of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
446
					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
447
					$this->installer->updateAppstoreApp($app);
448
				}
449
				$this->emit('\OC\Updater', 'checkAppStoreApp', [$app]);
450
			} catch (\Exception $ex) {
451
				$this->log->logException($ex, ['app' => 'core']);
452
			}
453
		}
454
	}
455
456
	/**
457
	 * Forward messages emitted by the repair routine
458
	 */
459
	private function emitRepairEvents() {
460
		$dispatcher = \OC::$server->getEventDispatcher();
461
		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
462
			if ($event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
463
				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
464
			}
465
		});
466
		$dispatcher->addListener('\OC\Repair::error', function ($event) {
467
			if ($event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
468
				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
469
			}
470
		});
471
		$dispatcher->addListener('\OC\Repair::info', function ($event) {
472
			if ($event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
473
				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
474
			}
475
		});
476
		$dispatcher->addListener('\OC\Repair::step', function ($event) {
477
			if ($event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
478
				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
479
			}
480
		});
481
	}
482
483
	private function logAllEvents() {
484
		$log = $this->log;
485
486
		$dispatcher = \OC::$server->getEventDispatcher();
487 View Code Duplication
		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
488
			if (!$event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
489
				return;
490
			}
491
			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
492
		});
493 View Code Duplication
		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
494
			if (!$event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
495
				return;
496
			}
497
			$log->info('\OC\DB\Migrator::checkTable: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
498
		});
499
500
		$repairListener = function($event) use ($log) {
501
			if (!$event instanceof GenericEvent) {
0 ignored issues
show
Bug introduced by
The class Symfony\Component\EventDispatcher\GenericEvent does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
502
				return;
503
			}
504
			switch ($event->getSubject()) {
505
				case '\OC\Repair::startProgress':
506
					$log->info('\OC\Repair::startProgress: Starting ... ' . $event->getArgument(1) .  ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
507
					break;
508
				case '\OC\Repair::advance':
509
					$desc = $event->getArgument(1);
510
					if (empty($desc)) {
511
						$desc = '';
512
					}
513
					$log->info('\OC\Repair::advance: ' . $desc . ' (' . $event->getArgument(0) . ')', ['app' => 'updater']);
514
515
					break;
516
				case '\OC\Repair::finishProgress':
517
					$log->info('\OC\Repair::finishProgress', ['app' => 'updater']);
518
					break;
519
				case '\OC\Repair::step':
520
					$log->info('\OC\Repair::step: Repair step: ' . $event->getArgument(0), ['app' => 'updater']);
521
					break;
522
				case '\OC\Repair::info':
523
					$log->info('\OC\Repair::info: Repair info: ' . $event->getArgument(0), ['app' => 'updater']);
524
					break;
525
				case '\OC\Repair::warning':
526
					$log->warning('\OC\Repair::warning: Repair warning: ' . $event->getArgument(0), ['app' => 'updater']);
527
					break;
528
				case '\OC\Repair::error':
529
					$log->error('\OC\Repair::error: Repair error: ' . $event->getArgument(0), ['app' => 'updater']);
530
					break;
531
			}
532
		};
533
534
		$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
535
		$dispatcher->addListener('\OC\Repair::advance', $repairListener);
536
		$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
537
		$dispatcher->addListener('\OC\Repair::step', $repairListener);
538
		$dispatcher->addListener('\OC\Repair::info', $repairListener);
539
		$dispatcher->addListener('\OC\Repair::warning', $repairListener);
540
		$dispatcher->addListener('\OC\Repair::error', $repairListener);
541
542
543
		$this->listen('\OC\Updater', 'maintenanceEnabled', function () use($log) {
544
			$log->info('\OC\Updater::maintenanceEnabled: Turned on maintenance mode', ['app' => 'updater']);
545
		});
546
		$this->listen('\OC\Updater', 'maintenanceDisabled', function () use($log) {
547
			$log->info('\OC\Updater::maintenanceDisabled: Turned off maintenance mode', ['app' => 'updater']);
548
		});
549
		$this->listen('\OC\Updater', 'maintenanceActive', function () use($log) {
550
			$log->info('\OC\Updater::maintenanceActive: Maintenance mode is kept active', ['app' => 'updater']);
551
		});
552
		$this->listen('\OC\Updater', 'updateEnd', function ($success) use($log) {
553
			if ($success) {
554
				$log->info('\OC\Updater::updateEnd: Update successful', ['app' => 'updater']);
555
			} else {
556
				$log->error('\OC\Updater::updateEnd: Update failed', ['app' => 'updater']);
557
			}
558
		});
559
		$this->listen('\OC\Updater', 'dbUpgradeBefore', function () use($log) {
560
			$log->info('\OC\Updater::dbUpgradeBefore: Updating database schema', ['app' => 'updater']);
561
		});
562
		$this->listen('\OC\Updater', 'dbUpgrade', function () use($log) {
563
			$log->info('\OC\Updater::dbUpgrade: Updated database', ['app' => 'updater']);
564
		});
565
		$this->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use($log) {
566
			$log->info('\OC\Updater::dbSimulateUpgradeBefore: Checking whether the database schema can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
567
		});
568
		$this->listen('\OC\Updater', 'dbSimulateUpgrade', function () use($log) {
569
			$log->info('\OC\Updater::dbSimulateUpgrade: Checked database schema update', ['app' => 'updater']);
570
		});
571
		$this->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use($log) {
572
			$log->info('\OC\Updater::incompatibleAppDisabled: Disabled incompatible app: ' . $app, ['app' => 'updater']);
573
		});
574
		$this->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use($log) {
575
			$log->info('\OC\Updater::checkAppStoreAppBefore: Checking for update of app "' . $app . '" in appstore', ['app' => 'updater']);
576
		});
577
		$this->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use($log) {
578
			$log->info('\OC\Updater::upgradeAppStoreApp: Update app "' . $app . '" from appstore', ['app' => 'updater']);
579
		});
580
		$this->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use($log) {
581
			$log->info('\OC\Updater::checkAppStoreApp: Checked for update of app "' . $app . '" in appstore', ['app' => 'updater']);
582
		});
583
		$this->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($log) {
584
			$log->info('\OC\Updater::appUpgradeCheckBefore: Checking updates of apps', ['app' => 'updater']);
585
		});
586
		$this->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($log) {
587
			$log->info('\OC\Updater::appSimulateUpdate: Checking whether the database schema for <' . $app . '> can be updated (this can take a long time depending on the database size)', ['app' => 'updater']);
588
		});
589
		$this->listen('\OC\Updater', 'appUpgradeCheck', function () use ($log) {
590
			$log->info('\OC\Updater::appUpgradeCheck: Checked database schema update for apps', ['app' => 'updater']);
591
		});
592
		$this->listen('\OC\Updater', 'appUpgradeStarted', function ($app) use ($log) {
593
			$log->info('\OC\Updater::appUpgradeStarted: Updating <' . $app . '> ...', ['app' => 'updater']);
594
		});
595
		$this->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($log) {
596
			$log->info('\OC\Updater::appUpgrade: Updated <' . $app . '> to ' . $version, ['app' => 'updater']);
597
		});
598
		$this->listen('\OC\Updater', 'failure', function ($message) use($log) {
599
			$log->error('\OC\Updater::failure: ' . $message, ['app' => 'updater']);
600
		});
601
		$this->listen('\OC\Updater', 'setDebugLogLevel', function () use($log) {
602
			$log->info('\OC\Updater::setDebugLogLevel: Set log level to debug', ['app' => 'updater']);
603
		});
604
		$this->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use($log) {
605
			$log->info('\OC\Updater::resetLogLevel: Reset log level to ' . $logLevelName . '(' . $logLevel . ')', ['app' => 'updater']);
606
		});
607
		$this->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use($log) {
608
			$log->info('\OC\Updater::startCheckCodeIntegrity: Starting code integrity check...', ['app' => 'updater']);
609
		});
610
		$this->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use($log) {
611
			$log->info('\OC\Updater::finishedCheckCodeIntegrity: Finished code integrity check', ['app' => 'updater']);
612
		});
613
614
	}
615
616
}
617
618