Completed
Push — master ( 4a9cb8...f72f55 )
by Morris
12:46
created

Updater   F

Complexity

Total Complexity 72

Size/Duplication

Total Lines 563
Duplicated Lines 2.13 %

Coupling/Cohesion

Components 1
Dependencies 14

Importance

Changes 0
Metric Value
dl 12
loc 563
rs 3.924
c 0
b 0
f 0
wmc 72
lcom 1
cbo 14

16 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 2
A setSkip3rdPartyAppsDisable() 0 3 1
B upgrade() 0 47 6
A getVendor() 0 6 1
A getAllowedPreviousVersions() 0 6 1
A isUpgradePossible() 0 14 4
B doUpgrade() 0 67 6
A doCoreUpgrade() 0 8 1
C checkAppUpgrade() 0 28 7
A includePreUpdate() 0 3 1
D doAppUpgrade() 0 38 10
C checkAppsRequirements() 0 37 8
A isCodeUpgrade() 0 8 2
A upgradeAppStoreApps() 0 19 4
B emitRepairEvents() 0 23 5
D logAllEvents() 12 129 13

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Updater often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Updater, and based on these observations, apply Extract Interface, too.

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