Completed
Push — master ( f514bb...b3696f )
by Lukas
07:15
created

Updater::checkAppsRequirements()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 37
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 23
nc 12
nop 0
dl 0
loc 37
rs 5.3846
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 * @copyright Copyright (c) 2016, Lukas Reschke <[email protected]>
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Frank Karlitschek <[email protected]>
8
 * @author Joas Schilling <[email protected]>
9
 * @author Lukas Reschke <[email protected]>
10
 * @author Morris Jobke <[email protected]>
11
 * @author Robin Appelman <[email protected]>
12
 * @author Steffen Lindner <[email protected]>
13
 * @author Thomas Müller <[email protected]>
14
 * @author Victor Dubiniuk <[email protected]>
15
 * @author Vincent Petry <[email protected]>
16
 *
17
 * @license AGPL-3.0
18
 *
19
 * This code is free software: you can redistribute it and/or modify
20
 * it under the terms of the GNU Affero General Public License, version 3,
21
 * as published by the Free Software Foundation.
22
 *
23
 * This program is distributed in the hope that it will be useful,
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
 * GNU Affero General Public License for more details.
27
 *
28
 * You should have received a copy of the GNU Affero General Public License, version 3,
29
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
30
 *
31
 */
32
33
namespace OC;
34
35
use OC\Hooks\BasicEmitter;
36
use OC\IntegrityCheck\Checker;
37
use OC_App;
38
use OCP\IConfig;
39
use OCP\ILogger;
40
use OCP\Util;
41
use Symfony\Component\EventDispatcher\GenericEvent;
42
43
/**
44
 * Class that handles autoupdating of ownCloud
45
 *
46
 * Hooks provided in scope \OC\Updater
47
 *  - maintenanceStart()
48
 *  - maintenanceEnd()
49
 *  - dbUpgrade()
50
 *  - failure(string $message)
51
 */
52
class Updater extends BasicEmitter {
53
54
	/** @var ILogger $log */
55
	private $log;
56
57
	/** @var IConfig */
58
	private $config;
59
60
	/** @var Checker */
61
	private $checker;
62
63
	/** @var bool */
64
	private $skip3rdPartyAppsDisable;
65
66
	private $logLevelNames = [
67
		0 => 'Debug',
68
		1 => 'Info',
69
		2 => 'Warning',
70
		3 => 'Error',
71
		4 => 'Fatal',
72
	];
73
74
	/**
75
	 * @param IConfig $config
76
	 * @param Checker $checker
77
	 * @param ILogger $log
78
	 */
79
	public function __construct(IConfig $config,
80
								Checker $checker,
81
								ILogger $log = null) {
82
		$this->log = $log;
83
		$this->config = $config;
84
		$this->checker = $checker;
85
	}
86
87
	/**
88
	 * Sets whether the update disables 3rd party apps.
89
	 * This can be set to true to skip the disable.
90
	 *
91
	 * @param bool $flag false to not disable, true otherwise
92
	 */
93
	public function setSkip3rdPartyAppsDisable($flag) {
94
		$this->skip3rdPartyAppsDisable = $flag;
95
	}
96
97
	/**
98
	 * runs the update actions in maintenance mode, does not upgrade the source files
99
	 * except the main .htaccess file
100
	 *
101
	 * @return bool true if the operation succeeded, false otherwise
102
	 */
103
	public function upgrade() {
104
		$this->emitRepairEvents();
105
		$this->logAllEvents();
106
107
		$logLevel = $this->config->getSystemValue('loglevel', Util::WARN);
108
		$this->emit('\OC\Updater', 'setDebugLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
109
		$this->config->setSystemValue('loglevel', Util::DEBUG);
110
111
		$wasMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
112
113
		if(!$wasMaintenanceModeEnabled) {
114
			$this->config->setSystemValue('maintenance', true);
115
			$this->emit('\OC\Updater', 'maintenanceEnabled');
116
		}
117
118
		$installedVersion = $this->config->getSystemValue('version', '0.0.0');
119
		$currentVersion = implode('.', \OCP\Util::getVersion());
120
		$this->log->debug('starting upgrade from ' . $installedVersion . ' to ' . $currentVersion, array('app' => 'core'));
121
122
		$success = true;
123
		try {
124
			$this->doUpgrade($currentVersion, $installedVersion);
125
		} catch (HintException $exception) {
126
			$this->log->logException($exception, ['app' => 'core']);
127
			$this->emit('\OC\Updater', 'failure', array($exception->getMessage() . ': ' .$exception->getHint()));
128
			$success = false;
129
		} catch (\Exception $exception) {
130
			$this->log->logException($exception, ['app' => 'core']);
131
			$this->emit('\OC\Updater', 'failure', array(get_class($exception) . ': ' .$exception->getMessage()));
132
			$success = false;
133
		}
134
135
		$this->emit('\OC\Updater', 'updateEnd', array($success));
136
137
		if(!$wasMaintenanceModeEnabled && $success) {
138
			$this->config->setSystemValue('maintenance', false);
139
			$this->emit('\OC\Updater', 'maintenanceDisabled');
140
		} else {
141
			$this->emit('\OC\Updater', 'maintenanceActive');
142
		}
143
144
		$this->emit('\OC\Updater', 'resetLogLevel', [ $logLevel, $this->logLevelNames[$logLevel] ]);
145
		$this->config->setSystemValue('loglevel', $logLevel);
146
		$this->config->setSystemValue('installed', true);
147
148
		return $success;
149
	}
150
151
	/**
152
	 * Return version from which this version is allowed to upgrade from
153
	 *
154
	 * @return string allowed previous version
155
	 */
156
	private function getAllowedPreviousVersion() {
157
		// this should really be a JSON file
158
		require \OC::$SERVERROOT . '/version.php';
159
		/** @var array $OC_VersionCanBeUpgradedFrom */
160
		return implode('.', $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...
161
	}
162
163
	/**
164
	 * Return vendor from which this version was published
165
	 *
166
	 * @return string Get the vendor
167
	 */
168
	private function getVendor() {
169
		// this should really be a JSON file
170
		require \OC::$SERVERROOT . '/version.php';
171
		/** @var string $vendor */
172
		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...
173
	}
174
175
	/**
176
	 * Whether an upgrade to a specified version is possible
177
	 * @param string $oldVersion
178
	 * @param string $newVersion
179
	 * @param string $allowedPreviousVersion
180
	 * @return bool
181
	 */
182
	public function isUpgradePossible($oldVersion, $newVersion, $allowedPreviousVersion) {
183
		$allowedUpgrade = (version_compare($allowedPreviousVersion, $oldVersion, '<=')
184
			&& (version_compare($oldVersion, $newVersion, '<=') || $this->config->getSystemValue('debug', false)));
185
186
		if ($allowedUpgrade) {
187
			return $allowedUpgrade;
188
		}
189
190
		// Upgrade not allowed, someone switching vendor?
191
		if ($this->getVendor() !== $this->config->getAppValue('core', 'vendor', '')) {
192
			$oldVersion = explode('.', $oldVersion);
193
			$newVersion = explode('.', $newVersion);
194
195
			return $oldVersion[0] === $newVersion[0] && $oldVersion[1] === $newVersion[1];
196
		}
197
198
		return false;
199
	}
200
201
	/**
202
	 * runs the update actions in maintenance mode, does not upgrade the source files
203
	 * except the main .htaccess file
204
	 *
205
	 * @param string $currentVersion current version to upgrade to
206
	 * @param string $installedVersion previous version from which to upgrade from
207
	 *
208
	 * @throws \Exception
209
	 */
210
	private function doUpgrade($currentVersion, $installedVersion) {
211
		// Stop update if the update is over several major versions
212
		$allowedPreviousVersion = $this->getAllowedPreviousVersion();
213
		if (!self::isUpgradePossible($installedVersion, $currentVersion, $allowedPreviousVersion)) {
214
			throw new \Exception('Updates between multiple major versions and downgrades are unsupported.');
215
		}
216
217
		// Update .htaccess files
218
		try {
219
			Setup::updateHtaccess();
220
			Setup::protectDataDirectory();
221
		} catch (\Exception $e) {
222
			throw new \Exception($e->getMessage());
223
		}
224
225
		// create empty file in data dir, so we can later find
226
		// out that this is indeed an ownCloud data directory
227
		// (in case it didn't exist before)
228
		file_put_contents($this->config->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . '/.ocdata', '');
229
230
		// pre-upgrade repairs
231
		$repair = new Repair(Repair::getBeforeUpgradeRepairSteps(), \OC::$server->getEventDispatcher());
232
		$repair->run();
233
234
		$this->doCoreUpgrade();
235
236
		try {
237
			// TODO: replace with the new repair step mechanism https://github.com/owncloud/core/pull/24378
238
			Setup::installBackgroundJobs();
239
		} catch (\Exception $e) {
240
			throw new \Exception($e->getMessage());
241
		}
242
243
		// update all shipped apps
244
		$disabledApps = $this->checkAppsRequirements();
245
		$this->doAppUpgrade();
246
247
		// upgrade appstore apps
248
		$this->upgradeAppStoreApps($disabledApps);
249
250
		// install new shipped apps on upgrade
251
		OC_App::loadApps('authentication');
252
		$errors = Installer::installShippedApps(true);
253
		foreach ($errors as $appId => $exception) {
254
			/** @var \Exception $exception */
255
			$this->log->logException($exception, ['app' => $appId]);
256
			$this->emit('\OC\Updater', 'failure', [$appId . ': ' . $exception->getMessage()]);
257
		}
258
259
		// post-upgrade repairs
260
		$repair = new Repair(Repair::getRepairSteps(), \OC::$server->getEventDispatcher());
261
		$repair->run();
262
263
		//Invalidate update feed
264
		$this->config->setAppValue('core', 'lastupdatedat', 0);
265
266
		// Check for code integrity if not disabled
267
		if(\OC::$server->getIntegrityCodeChecker()->isCodeCheckEnforced()) {
268
			$this->emit('\OC\Updater', 'startCheckCodeIntegrity');
269
			$this->checker->runInstanceVerification();
270
			$this->emit('\OC\Updater', 'finishedCheckCodeIntegrity');
271
		}
272
273
		// only set the final version if everything went well
274
		$this->config->setSystemValue('version', implode('.', Util::getVersion()));
275
		$this->config->setAppValue('core', 'vendor', $this->getVendor());
276
	}
277
278
	protected function doCoreUpgrade() {
279
		$this->emit('\OC\Updater', 'dbUpgradeBefore');
280
281
		// do the real upgrade
282
		\OC_DB::updateDbFromStructure(\OC::$SERVERROOT . '/db_structure.xml');
283
284
		$this->emit('\OC\Updater', 'dbUpgrade');
285
	}
286
287
	/**
288
	 * @param string $version the oc version to check app compatibility with
289
	 */
290
	protected function checkAppUpgrade($version) {
291
		$apps = \OC_App::getEnabledApps();
292
		$this->emit('\OC\Updater', 'appUpgradeCheckBefore');
293
294
		foreach ($apps as $appId) {
295
			$info = \OC_App::getAppInfo($appId);
296
			$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 295 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...
297
			$isShipped = \OC_App::isShipped($appId);
298
299
			if ($compatible && $isShipped && \OC_App::shouldUpgrade($appId)) {
300
				/**
301
				 * FIXME: The preupdate check is performed before the database migration, otherwise database changes
302
				 * are not possible anymore within it. - Consider this when touching the code.
303
				 * @link https://github.com/owncloud/core/issues/10980
304
				 * @see \OC_App::updateApp
305
				 */
306
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/preupdate.php')) {
307
					$this->includePreUpdate($appId);
308
				}
309
				if (file_exists(\OC_App::getAppPath($appId) . '/appinfo/database.xml')) {
310
					$this->emit('\OC\Updater', 'appSimulateUpdate', array($appId));
311
					\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...
312
				}
313
			}
314
		}
315
316
		$this->emit('\OC\Updater', 'appUpgradeCheck');
317
	}
318
319
	/**
320
	 * Includes the pre-update file. Done here to prevent namespace mixups.
321
	 * @param string $appId
322
	 */
323
	private function includePreUpdate($appId) {
324
		include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php';
325
	}
326
327
	/**
328
	 * upgrades all apps within a major ownCloud upgrade. Also loads "priority"
329
	 * (types authentication, filesystem, logging, in that order) afterwards.
330
	 *
331
	 * @throws NeedsUpdateException
332
	 */
333
	protected function doAppUpgrade() {
334
		$apps = \OC_App::getEnabledApps();
335
		$priorityTypes = array('authentication', 'filesystem', 'logging');
336
		$pseudoOtherType = 'other';
337
		$stacks = array($pseudoOtherType => array());
338
339
		foreach ($apps as $appId) {
340
			$priorityType = false;
341
			foreach ($priorityTypes as $type) {
342
				if(!isset($stacks[$type])) {
343
					$stacks[$type] = array();
344
				}
345
				if (\OC_App::isType($appId, $type)) {
346
					$stacks[$type][] = $appId;
347
					$priorityType = true;
348
					break;
349
				}
350
			}
351
			if (!$priorityType) {
352
				$stacks[$pseudoOtherType][] = $appId;
353
			}
354
		}
355
		foreach ($stacks as $type => $stack) {
356
			foreach ($stack as $appId) {
357
				if (\OC_App::shouldUpgrade($appId)) {
358
					$this->emit('\OC\Updater', 'appUpgradeStarted', [$appId, \OC_App::getAppVersion($appId)]);
359
					\OC_App::updateApp($appId);
360
					$this->emit('\OC\Updater', 'appUpgrade', [$appId, \OC_App::getAppVersion($appId)]);
361
				}
362
				if($type !== $pseudoOtherType) {
363
					// load authentication, filesystem and logging apps after
364
					// upgrading them. Other apps my need to rely on modifying
365
					// user and/or filesystem aspects.
366
					\OC_App::loadApp($appId, false);
367
				}
368
			}
369
		}
370
	}
371
372
	/**
373
	 * check if the current enabled apps are compatible with the current
374
	 * ownCloud version. disable them if not.
375
	 * This is important if you upgrade ownCloud and have non ported 3rd
376
	 * party apps installed.
377
	 *
378
	 * @return array
379
	 * @throws \Exception
380
	 */
381
	private function checkAppsRequirements() {
382
		$isCoreUpgrade = $this->isCodeUpgrade();
383
		$apps = OC_App::getEnabledApps();
384
		$version = Util::getVersion();
385
		$disabledApps = [];
386
		foreach ($apps as $app) {
387
			// check if the app is compatible with this version of ownCloud
388
			$info = OC_App::getAppInfo($app);
389
			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 388 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...
390
				if (OC_App::isShipped($app)) {
391
					throw new \UnexpectedValueException('The files of the app "' . $app . '" were not correctly replaced before running the update');
392
				}
393
				OC_App::disable($app);
394
				$this->emit('\OC\Updater', 'incompatibleAppDisabled', array($app));
395
			}
396
			// no need to disable any app in case this is a non-core upgrade
397
			if (!$isCoreUpgrade) {
398
				continue;
399
			}
400
			// shipped apps will remain enabled
401
			if (OC_App::isShipped($app)) {
402
				continue;
403
			}
404
			// authentication and session apps will remain enabled as well
405
			if (OC_App::isType($app, ['session', 'authentication'])) {
406
				continue;
407
			}
408
409
			// disable any other 3rd party apps if not overriden
410
			if(!$this->skip3rdPartyAppsDisable) {
411
				\OC_App::disable($app);
412
				$disabledApps[]= $app;
413
				$this->emit('\OC\Updater', 'thirdPartyAppDisabled', array($app));
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
				$installer = new Installer(
439
					\OC::$server->getAppFetcher(),
440
					\OC::$server->getHTTPClientService(),
441
					\OC::$server->getTempManager(),
442
					$this->log
443
				);
444
				if (Installer::isUpdateAvailable($app, \OC::$server->getAppFetcher())) {
0 ignored issues
show
Bug Best Practice introduced by
The expression \OC\Installer::isUpdateA...erver->getAppFetcher()) 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...
445
					$this->emit('\OC\Updater', 'upgradeAppStoreApp', [$app]);
446
					$installer->updateAppstoreApp($app);
447
				}
448
			} catch (\Exception $ex) {
449
				$this->log->logException($ex, ['app' => 'core']);
450
			}
451
		}
452
	}
453
454
	/**
455
	 * Forward messages emitted by the repair routine
456
	 */
457
	private function emitRepairEvents() {
458
		$dispatcher = \OC::$server->getEventDispatcher();
459
		$dispatcher->addListener('\OC\Repair::warning', function ($event) {
460
			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...
461
				$this->emit('\OC\Updater', 'repairWarning', $event->getArguments());
462
			}
463
		});
464
		$dispatcher->addListener('\OC\Repair::error', function ($event) {
465
			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...
466
				$this->emit('\OC\Updater', 'repairError', $event->getArguments());
467
			}
468
		});
469
		$dispatcher->addListener('\OC\Repair::info', function ($event) {
470
			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...
471
				$this->emit('\OC\Updater', 'repairInfo', $event->getArguments());
472
			}
473
		});
474
		$dispatcher->addListener('\OC\Repair::step', function ($event) {
475
			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...
476
				$this->emit('\OC\Updater', 'repairStep', $event->getArguments());
477
			}
478
		});
479
	}
480
481
	private function logAllEvents() {
482
		$log = $this->log;
483
484
		$dispatcher = \OC::$server->getEventDispatcher();
485 View Code Duplication
		$dispatcher->addListener('\OC\DB\Migrator::executeSql', function($event) use ($log) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
486
			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...
487
				return;
488
			}
489
			$log->info('\OC\DB\Migrator::executeSql: ' . $event->getSubject() . ' (' . $event->getArgument(0) . ' of ' . $event->getArgument(1) . ')', ['app' => 'updater']);
490
		});
491 View Code Duplication
		$dispatcher->addListener('\OC\DB\Migrator::checkTable', function($event) use ($log) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

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