Completed
Push — stable10 ( fe3e76...c4bfdb )
by Lukas
54:21 queued 29:00
created

Updater::getVendor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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