Completed
Pull Request — master (#8503)
by Blizzz
28:23 queued 10:12
created
lib/private/App/AppManager.php 2 patches
Indentation   +402 added lines, -402 removed lines patch added patch discarded remove patch
@@ -44,406 +44,406 @@
 block discarded – undo
44 44
 
45 45
 class AppManager implements IAppManager {
46 46
 
47
-	/**
48
-	 * Apps with these types can not be enabled for certain groups only
49
-	 * @var string[]
50
-	 */
51
-	protected $protectedAppTypes = [
52
-		'filesystem',
53
-		'prelogin',
54
-		'authentication',
55
-		'logging',
56
-		'prevent_group_restriction',
57
-	];
58
-
59
-	/** @var IUserSession */
60
-	private $userSession;
61
-
62
-	/** @var AppConfig */
63
-	private $appConfig;
64
-
65
-	/** @var IGroupManager */
66
-	private $groupManager;
67
-
68
-	/** @var ICacheFactory */
69
-	private $memCacheFactory;
70
-
71
-	/** @var EventDispatcherInterface */
72
-	private $dispatcher;
73
-
74
-	/** @var string[] $appId => $enabled */
75
-	private $installedAppsCache;
76
-
77
-	/** @var string[] */
78
-	private $shippedApps;
79
-
80
-	/** @var string[] */
81
-	private $alwaysEnabled;
82
-
83
-	/** @var array */
84
-	private $appInfos = [];
85
-
86
-	/** @var array */
87
-	private $appVersions = [];
88
-
89
-	/**
90
-	 * @param IUserSession $userSession
91
-	 * @param AppConfig $appConfig
92
-	 * @param IGroupManager $groupManager
93
-	 * @param ICacheFactory $memCacheFactory
94
-	 * @param EventDispatcherInterface $dispatcher
95
-	 */
96
-	public function __construct(IUserSession $userSession,
97
-								AppConfig $appConfig,
98
-								IGroupManager $groupManager,
99
-								ICacheFactory $memCacheFactory,
100
-								EventDispatcherInterface $dispatcher) {
101
-		$this->userSession = $userSession;
102
-		$this->appConfig = $appConfig;
103
-		$this->groupManager = $groupManager;
104
-		$this->memCacheFactory = $memCacheFactory;
105
-		$this->dispatcher = $dispatcher;
106
-	}
107
-
108
-	/**
109
-	 * @return string[] $appId => $enabled
110
-	 */
111
-	private function getInstalledAppsValues() {
112
-		if (!$this->installedAppsCache) {
113
-			$values = $this->appConfig->getValues(false, 'enabled');
114
-
115
-			$alwaysEnabledApps = $this->getAlwaysEnabledApps();
116
-			foreach($alwaysEnabledApps as $appId) {
117
-				$values[$appId] = 'yes';
118
-			}
119
-
120
-			$this->installedAppsCache = array_filter($values, function ($value) {
121
-				return $value !== 'no';
122
-			});
123
-			ksort($this->installedAppsCache);
124
-		}
125
-		return $this->installedAppsCache;
126
-	}
127
-
128
-	/**
129
-	 * List all installed apps
130
-	 *
131
-	 * @return string[]
132
-	 */
133
-	public function getInstalledApps() {
134
-		return array_keys($this->getInstalledAppsValues());
135
-	}
136
-
137
-	/**
138
-	 * List all apps enabled for a user
139
-	 *
140
-	 * @param \OCP\IUser $user
141
-	 * @return string[]
142
-	 */
143
-	public function getEnabledAppsForUser(IUser $user) {
144
-		$apps = $this->getInstalledAppsValues();
145
-		$appsForUser = array_filter($apps, function ($enabled) use ($user) {
146
-			return $this->checkAppForUser($enabled, $user);
147
-		});
148
-		return array_keys($appsForUser);
149
-	}
150
-
151
-	/**
152
-	 * Check if an app is enabled for user
153
-	 *
154
-	 * @param string $appId
155
-	 * @param \OCP\IUser $user (optional) if not defined, the currently logged in user will be used
156
-	 * @return bool
157
-	 */
158
-	public function isEnabledForUser($appId, $user = null) {
159
-		if ($this->isAlwaysEnabled($appId)) {
160
-			return true;
161
-		}
162
-		if ($user === null) {
163
-			$user = $this->userSession->getUser();
164
-		}
165
-		$installedApps = $this->getInstalledAppsValues();
166
-		if (isset($installedApps[$appId])) {
167
-			return $this->checkAppForUser($installedApps[$appId], $user);
168
-		} else {
169
-			return false;
170
-		}
171
-	}
172
-
173
-	/**
174
-	 * @param string $enabled
175
-	 * @param IUser $user
176
-	 * @return bool
177
-	 */
178
-	private function checkAppForUser($enabled, $user) {
179
-		if ($enabled === 'yes') {
180
-			return true;
181
-		} elseif ($user === null) {
182
-			return false;
183
-		} else {
184
-			if(empty($enabled)){
185
-				return false;
186
-			}
187
-
188
-			$groupIds = json_decode($enabled);
189
-
190
-			if (!is_array($groupIds)) {
191
-				$jsonError = json_last_error();
192
-				\OC::$server->getLogger()->warning('AppManger::checkAppForUser - can\'t decode group IDs: ' . print_r($enabled, true) . ' - json error code: ' . $jsonError, ['app' => 'lib']);
193
-				return false;
194
-			}
195
-
196
-			$userGroups = $this->groupManager->getUserGroupIds($user);
197
-			foreach ($userGroups as $groupId) {
198
-				if (in_array($groupId, $groupIds, true)) {
199
-					return true;
200
-				}
201
-			}
202
-			return false;
203
-		}
204
-	}
205
-
206
-	/**
207
-	 * Check if an app is installed in the instance
208
-	 *
209
-	 * @param string $appId
210
-	 * @return bool
211
-	 */
212
-	public function isInstalled($appId) {
213
-		$installedApps = $this->getInstalledAppsValues();
214
-		return isset($installedApps[$appId]);
215
-	}
216
-
217
-	/**
218
-	 * Enable an app for every user
219
-	 *
220
-	 * @param string $appId
221
-	 * @throws AppPathNotFoundException
222
-	 */
223
-	public function enableApp($appId) {
224
-		// Check if app exists
225
-		$this->getAppPath($appId);
226
-
227
-		$this->installedAppsCache[$appId] = 'yes';
228
-		$this->appConfig->setValue($appId, 'enabled', 'yes');
229
-		$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent(
230
-			ManagerEvent::EVENT_APP_ENABLE, $appId
231
-		));
232
-		$this->clearAppsCache();
233
-	}
234
-
235
-	/**
236
-	 * Whether a list of types contains a protected app type
237
-	 *
238
-	 * @param string[] $types
239
-	 * @return bool
240
-	 */
241
-	public function hasProtectedAppType($types) {
242
-		if (empty($types)) {
243
-			return false;
244
-		}
245
-
246
-		$protectedTypes = array_intersect($this->protectedAppTypes, $types);
247
-		return !empty($protectedTypes);
248
-	}
249
-
250
-	/**
251
-	 * Enable an app only for specific groups
252
-	 *
253
-	 * @param string $appId
254
-	 * @param \OCP\IGroup[] $groups
255
-	 * @throws \Exception if app can't be enabled for groups
256
-	 */
257
-	public function enableAppForGroups($appId, $groups) {
258
-		$info = $this->getAppInfo($appId);
259
-		if (!empty($info['types'])) {
260
-			$protectedTypes = array_intersect($this->protectedAppTypes, $info['types']);
261
-			if (!empty($protectedTypes)) {
262
-				throw new \Exception("$appId can't be enabled for groups.");
263
-			}
264
-		}
265
-
266
-		$groupIds = array_map(function ($group) {
267
-			/** @var \OCP\IGroup $group */
268
-			return $group->getGID();
269
-		}, $groups);
270
-		$this->installedAppsCache[$appId] = json_encode($groupIds);
271
-		$this->appConfig->setValue($appId, 'enabled', json_encode($groupIds));
272
-		$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent(
273
-			ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups
274
-		));
275
-		$this->clearAppsCache();
276
-	}
277
-
278
-	/**
279
-	 * Disable an app for every user
280
-	 *
281
-	 * @param string $appId
282
-	 * @throws \Exception if app can't be disabled
283
-	 */
284
-	public function disableApp($appId) {
285
-		if ($this->isAlwaysEnabled($appId)) {
286
-			throw new \Exception("$appId can't be disabled.");
287
-		}
288
-		unset($this->installedAppsCache[$appId]);
289
-		$this->appConfig->setValue($appId, 'enabled', 'no');
290
-		$this->dispatcher->dispatch(ManagerEvent::EVENT_APP_DISABLE, new ManagerEvent(
291
-			ManagerEvent::EVENT_APP_DISABLE, $appId
292
-		));
293
-		$this->clearAppsCache();
294
-	}
295
-
296
-	/**
297
-	 * Get the directory for the given app.
298
-	 *
299
-	 * @param string $appId
300
-	 * @return string
301
-	 * @throws AppPathNotFoundException if app folder can't be found
302
-	 */
303
-	public function getAppPath($appId) {
304
-		$appPath = \OC_App::getAppPath($appId);
305
-		if($appPath === false) {
306
-			throw new AppPathNotFoundException('Could not find path for ' . $appId);
307
-		}
308
-		return $appPath;
309
-	}
310
-
311
-	/**
312
-	 * Clear the cached list of apps when enabling/disabling an app
313
-	 */
314
-	public function clearAppsCache() {
315
-		$settingsMemCache = $this->memCacheFactory->createDistributed('settings');
316
-		$settingsMemCache->clear('listApps');
317
-	}
318
-
319
-	/**
320
-	 * Returns a list of apps that need upgrade
321
-	 *
322
-	 * @param string $version Nextcloud version as array of version components
323
-	 * @return array list of app info from apps that need an upgrade
324
-	 *
325
-	 * @internal
326
-	 */
327
-	public function getAppsNeedingUpgrade($version) {
328
-		$appsToUpgrade = [];
329
-		$apps = $this->getInstalledApps();
330
-		foreach ($apps as $appId) {
331
-			$appInfo = $this->getAppInfo($appId);
332
-			$appDbVersion = $this->appConfig->getValue($appId, 'installed_version');
333
-			if ($appDbVersion
334
-				&& isset($appInfo['version'])
335
-				&& version_compare($appInfo['version'], $appDbVersion, '>')
336
-				&& \OC_App::isAppCompatible($version, $appInfo)
337
-			) {
338
-				$appsToUpgrade[] = $appInfo;
339
-			}
340
-		}
341
-
342
-		return $appsToUpgrade;
343
-	}
344
-
345
-	/**
346
-	 * Returns the app information from "appinfo/info.xml".
347
-	 *
348
-	 * @param string $appId app id
349
-	 *
350
-	 * @param bool $path
351
-	 * @param null $lang
352
-	 * @return array app info
353
-	 */
354
-	public function getAppInfo(string $appId, bool $path = false, $lang = null): array {
355
-		if ($path) {
356
-			$file = $appId;
357
-		} else {
358
-			if ($lang === null && isset($this->appInfos[$appId])) {
359
-				return $this->appInfos[$appId];
360
-			}
361
-			try {
362
-				$appPath = $this->getAppPath($appId);
363
-			} catch (AppPathNotFoundException $e) {
364
-				return [];
365
-			}
366
-			$file = $appPath . '/appinfo/info.xml';
367
-		}
368
-
369
-		$parser = new InfoParser($this->memCacheFactory->createLocal('core.appinfo'));
370
-		$data = $parser->parse($file);
371
-
372
-		if (is_array($data)) {
373
-			$data = \OC_App::parseAppInfo($data, $lang);
374
-		}
375
-
376
-		if ($lang === null) {
377
-			$this->appInfos[$appId] = $data;
378
-		}
379
-
380
-		return $data;
381
-	}
382
-
383
-	public function getAppVersion(string $appId, bool $useCache = true): string {
384
-		if(!$useCache || !isset($this->appVersions[$appId])) {
385
-			$appInfo = \OC::$server->getAppManager()->getAppInfo($appId);
386
-			$this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
387
-		}
388
-		return $this->appVersions[$appId];
389
-	}
390
-
391
-	/**
392
-	 * Returns a list of apps incompatible with the given version
393
-	 *
394
-	 * @param string $version Nextcloud version as array of version components
395
-	 *
396
-	 * @return array list of app info from incompatible apps
397
-	 *
398
-	 * @internal
399
-	 */
400
-	public function getIncompatibleApps(string $version): array {
401
-		$apps = $this->getInstalledApps();
402
-		$incompatibleApps = array();
403
-		foreach ($apps as $appId) {
404
-			$info = $this->getAppInfo($appId);
405
-			if (!\OC_App::isAppCompatible($version, $info)) {
406
-				$incompatibleApps[] = $info;
407
-			}
408
-		}
409
-		return $incompatibleApps;
410
-	}
411
-
412
-	/**
413
-	 * @inheritdoc
414
-	 * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::isShipped()
415
-	 */
416
-	public function isShipped($appId) {
417
-		$this->loadShippedJson();
418
-		return in_array($appId, $this->shippedApps, true);
419
-	}
420
-
421
-	private function isAlwaysEnabled($appId) {
422
-		$alwaysEnabled = $this->getAlwaysEnabledApps();
423
-		return in_array($appId, $alwaysEnabled, true);
424
-	}
425
-
426
-	/**
427
-	 * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::loadShippedJson()
428
-	 * @throws \Exception
429
-	 */
430
-	private function loadShippedJson() {
431
-		if ($this->shippedApps === null) {
432
-			$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
433
-			if (!file_exists($shippedJson)) {
434
-				throw new \Exception("File not found: $shippedJson");
435
-			}
436
-			$content = json_decode(file_get_contents($shippedJson), true);
437
-			$this->shippedApps = $content['shippedApps'];
438
-			$this->alwaysEnabled = $content['alwaysEnabled'];
439
-		}
440
-	}
441
-
442
-	/**
443
-	 * @inheritdoc
444
-	 */
445
-	public function getAlwaysEnabledApps() {
446
-		$this->loadShippedJson();
447
-		return $this->alwaysEnabled;
448
-	}
47
+    /**
48
+     * Apps with these types can not be enabled for certain groups only
49
+     * @var string[]
50
+     */
51
+    protected $protectedAppTypes = [
52
+        'filesystem',
53
+        'prelogin',
54
+        'authentication',
55
+        'logging',
56
+        'prevent_group_restriction',
57
+    ];
58
+
59
+    /** @var IUserSession */
60
+    private $userSession;
61
+
62
+    /** @var AppConfig */
63
+    private $appConfig;
64
+
65
+    /** @var IGroupManager */
66
+    private $groupManager;
67
+
68
+    /** @var ICacheFactory */
69
+    private $memCacheFactory;
70
+
71
+    /** @var EventDispatcherInterface */
72
+    private $dispatcher;
73
+
74
+    /** @var string[] $appId => $enabled */
75
+    private $installedAppsCache;
76
+
77
+    /** @var string[] */
78
+    private $shippedApps;
79
+
80
+    /** @var string[] */
81
+    private $alwaysEnabled;
82
+
83
+    /** @var array */
84
+    private $appInfos = [];
85
+
86
+    /** @var array */
87
+    private $appVersions = [];
88
+
89
+    /**
90
+     * @param IUserSession $userSession
91
+     * @param AppConfig $appConfig
92
+     * @param IGroupManager $groupManager
93
+     * @param ICacheFactory $memCacheFactory
94
+     * @param EventDispatcherInterface $dispatcher
95
+     */
96
+    public function __construct(IUserSession $userSession,
97
+                                AppConfig $appConfig,
98
+                                IGroupManager $groupManager,
99
+                                ICacheFactory $memCacheFactory,
100
+                                EventDispatcherInterface $dispatcher) {
101
+        $this->userSession = $userSession;
102
+        $this->appConfig = $appConfig;
103
+        $this->groupManager = $groupManager;
104
+        $this->memCacheFactory = $memCacheFactory;
105
+        $this->dispatcher = $dispatcher;
106
+    }
107
+
108
+    /**
109
+     * @return string[] $appId => $enabled
110
+     */
111
+    private function getInstalledAppsValues() {
112
+        if (!$this->installedAppsCache) {
113
+            $values = $this->appConfig->getValues(false, 'enabled');
114
+
115
+            $alwaysEnabledApps = $this->getAlwaysEnabledApps();
116
+            foreach($alwaysEnabledApps as $appId) {
117
+                $values[$appId] = 'yes';
118
+            }
119
+
120
+            $this->installedAppsCache = array_filter($values, function ($value) {
121
+                return $value !== 'no';
122
+            });
123
+            ksort($this->installedAppsCache);
124
+        }
125
+        return $this->installedAppsCache;
126
+    }
127
+
128
+    /**
129
+     * List all installed apps
130
+     *
131
+     * @return string[]
132
+     */
133
+    public function getInstalledApps() {
134
+        return array_keys($this->getInstalledAppsValues());
135
+    }
136
+
137
+    /**
138
+     * List all apps enabled for a user
139
+     *
140
+     * @param \OCP\IUser $user
141
+     * @return string[]
142
+     */
143
+    public function getEnabledAppsForUser(IUser $user) {
144
+        $apps = $this->getInstalledAppsValues();
145
+        $appsForUser = array_filter($apps, function ($enabled) use ($user) {
146
+            return $this->checkAppForUser($enabled, $user);
147
+        });
148
+        return array_keys($appsForUser);
149
+    }
150
+
151
+    /**
152
+     * Check if an app is enabled for user
153
+     *
154
+     * @param string $appId
155
+     * @param \OCP\IUser $user (optional) if not defined, the currently logged in user will be used
156
+     * @return bool
157
+     */
158
+    public function isEnabledForUser($appId, $user = null) {
159
+        if ($this->isAlwaysEnabled($appId)) {
160
+            return true;
161
+        }
162
+        if ($user === null) {
163
+            $user = $this->userSession->getUser();
164
+        }
165
+        $installedApps = $this->getInstalledAppsValues();
166
+        if (isset($installedApps[$appId])) {
167
+            return $this->checkAppForUser($installedApps[$appId], $user);
168
+        } else {
169
+            return false;
170
+        }
171
+    }
172
+
173
+    /**
174
+     * @param string $enabled
175
+     * @param IUser $user
176
+     * @return bool
177
+     */
178
+    private function checkAppForUser($enabled, $user) {
179
+        if ($enabled === 'yes') {
180
+            return true;
181
+        } elseif ($user === null) {
182
+            return false;
183
+        } else {
184
+            if(empty($enabled)){
185
+                return false;
186
+            }
187
+
188
+            $groupIds = json_decode($enabled);
189
+
190
+            if (!is_array($groupIds)) {
191
+                $jsonError = json_last_error();
192
+                \OC::$server->getLogger()->warning('AppManger::checkAppForUser - can\'t decode group IDs: ' . print_r($enabled, true) . ' - json error code: ' . $jsonError, ['app' => 'lib']);
193
+                return false;
194
+            }
195
+
196
+            $userGroups = $this->groupManager->getUserGroupIds($user);
197
+            foreach ($userGroups as $groupId) {
198
+                if (in_array($groupId, $groupIds, true)) {
199
+                    return true;
200
+                }
201
+            }
202
+            return false;
203
+        }
204
+    }
205
+
206
+    /**
207
+     * Check if an app is installed in the instance
208
+     *
209
+     * @param string $appId
210
+     * @return bool
211
+     */
212
+    public function isInstalled($appId) {
213
+        $installedApps = $this->getInstalledAppsValues();
214
+        return isset($installedApps[$appId]);
215
+    }
216
+
217
+    /**
218
+     * Enable an app for every user
219
+     *
220
+     * @param string $appId
221
+     * @throws AppPathNotFoundException
222
+     */
223
+    public function enableApp($appId) {
224
+        // Check if app exists
225
+        $this->getAppPath($appId);
226
+
227
+        $this->installedAppsCache[$appId] = 'yes';
228
+        $this->appConfig->setValue($appId, 'enabled', 'yes');
229
+        $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE, new ManagerEvent(
230
+            ManagerEvent::EVENT_APP_ENABLE, $appId
231
+        ));
232
+        $this->clearAppsCache();
233
+    }
234
+
235
+    /**
236
+     * Whether a list of types contains a protected app type
237
+     *
238
+     * @param string[] $types
239
+     * @return bool
240
+     */
241
+    public function hasProtectedAppType($types) {
242
+        if (empty($types)) {
243
+            return false;
244
+        }
245
+
246
+        $protectedTypes = array_intersect($this->protectedAppTypes, $types);
247
+        return !empty($protectedTypes);
248
+    }
249
+
250
+    /**
251
+     * Enable an app only for specific groups
252
+     *
253
+     * @param string $appId
254
+     * @param \OCP\IGroup[] $groups
255
+     * @throws \Exception if app can't be enabled for groups
256
+     */
257
+    public function enableAppForGroups($appId, $groups) {
258
+        $info = $this->getAppInfo($appId);
259
+        if (!empty($info['types'])) {
260
+            $protectedTypes = array_intersect($this->protectedAppTypes, $info['types']);
261
+            if (!empty($protectedTypes)) {
262
+                throw new \Exception("$appId can't be enabled for groups.");
263
+            }
264
+        }
265
+
266
+        $groupIds = array_map(function ($group) {
267
+            /** @var \OCP\IGroup $group */
268
+            return $group->getGID();
269
+        }, $groups);
270
+        $this->installedAppsCache[$appId] = json_encode($groupIds);
271
+        $this->appConfig->setValue($appId, 'enabled', json_encode($groupIds));
272
+        $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, new ManagerEvent(
273
+            ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, $appId, $groups
274
+        ));
275
+        $this->clearAppsCache();
276
+    }
277
+
278
+    /**
279
+     * Disable an app for every user
280
+     *
281
+     * @param string $appId
282
+     * @throws \Exception if app can't be disabled
283
+     */
284
+    public function disableApp($appId) {
285
+        if ($this->isAlwaysEnabled($appId)) {
286
+            throw new \Exception("$appId can't be disabled.");
287
+        }
288
+        unset($this->installedAppsCache[$appId]);
289
+        $this->appConfig->setValue($appId, 'enabled', 'no');
290
+        $this->dispatcher->dispatch(ManagerEvent::EVENT_APP_DISABLE, new ManagerEvent(
291
+            ManagerEvent::EVENT_APP_DISABLE, $appId
292
+        ));
293
+        $this->clearAppsCache();
294
+    }
295
+
296
+    /**
297
+     * Get the directory for the given app.
298
+     *
299
+     * @param string $appId
300
+     * @return string
301
+     * @throws AppPathNotFoundException if app folder can't be found
302
+     */
303
+    public function getAppPath($appId) {
304
+        $appPath = \OC_App::getAppPath($appId);
305
+        if($appPath === false) {
306
+            throw new AppPathNotFoundException('Could not find path for ' . $appId);
307
+        }
308
+        return $appPath;
309
+    }
310
+
311
+    /**
312
+     * Clear the cached list of apps when enabling/disabling an app
313
+     */
314
+    public function clearAppsCache() {
315
+        $settingsMemCache = $this->memCacheFactory->createDistributed('settings');
316
+        $settingsMemCache->clear('listApps');
317
+    }
318
+
319
+    /**
320
+     * Returns a list of apps that need upgrade
321
+     *
322
+     * @param string $version Nextcloud version as array of version components
323
+     * @return array list of app info from apps that need an upgrade
324
+     *
325
+     * @internal
326
+     */
327
+    public function getAppsNeedingUpgrade($version) {
328
+        $appsToUpgrade = [];
329
+        $apps = $this->getInstalledApps();
330
+        foreach ($apps as $appId) {
331
+            $appInfo = $this->getAppInfo($appId);
332
+            $appDbVersion = $this->appConfig->getValue($appId, 'installed_version');
333
+            if ($appDbVersion
334
+                && isset($appInfo['version'])
335
+                && version_compare($appInfo['version'], $appDbVersion, '>')
336
+                && \OC_App::isAppCompatible($version, $appInfo)
337
+            ) {
338
+                $appsToUpgrade[] = $appInfo;
339
+            }
340
+        }
341
+
342
+        return $appsToUpgrade;
343
+    }
344
+
345
+    /**
346
+     * Returns the app information from "appinfo/info.xml".
347
+     *
348
+     * @param string $appId app id
349
+     *
350
+     * @param bool $path
351
+     * @param null $lang
352
+     * @return array app info
353
+     */
354
+    public function getAppInfo(string $appId, bool $path = false, $lang = null): array {
355
+        if ($path) {
356
+            $file = $appId;
357
+        } else {
358
+            if ($lang === null && isset($this->appInfos[$appId])) {
359
+                return $this->appInfos[$appId];
360
+            }
361
+            try {
362
+                $appPath = $this->getAppPath($appId);
363
+            } catch (AppPathNotFoundException $e) {
364
+                return [];
365
+            }
366
+            $file = $appPath . '/appinfo/info.xml';
367
+        }
368
+
369
+        $parser = new InfoParser($this->memCacheFactory->createLocal('core.appinfo'));
370
+        $data = $parser->parse($file);
371
+
372
+        if (is_array($data)) {
373
+            $data = \OC_App::parseAppInfo($data, $lang);
374
+        }
375
+
376
+        if ($lang === null) {
377
+            $this->appInfos[$appId] = $data;
378
+        }
379
+
380
+        return $data;
381
+    }
382
+
383
+    public function getAppVersion(string $appId, bool $useCache = true): string {
384
+        if(!$useCache || !isset($this->appVersions[$appId])) {
385
+            $appInfo = \OC::$server->getAppManager()->getAppInfo($appId);
386
+            $this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
387
+        }
388
+        return $this->appVersions[$appId];
389
+    }
390
+
391
+    /**
392
+     * Returns a list of apps incompatible with the given version
393
+     *
394
+     * @param string $version Nextcloud version as array of version components
395
+     *
396
+     * @return array list of app info from incompatible apps
397
+     *
398
+     * @internal
399
+     */
400
+    public function getIncompatibleApps(string $version): array {
401
+        $apps = $this->getInstalledApps();
402
+        $incompatibleApps = array();
403
+        foreach ($apps as $appId) {
404
+            $info = $this->getAppInfo($appId);
405
+            if (!\OC_App::isAppCompatible($version, $info)) {
406
+                $incompatibleApps[] = $info;
407
+            }
408
+        }
409
+        return $incompatibleApps;
410
+    }
411
+
412
+    /**
413
+     * @inheritdoc
414
+     * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::isShipped()
415
+     */
416
+    public function isShipped($appId) {
417
+        $this->loadShippedJson();
418
+        return in_array($appId, $this->shippedApps, true);
419
+    }
420
+
421
+    private function isAlwaysEnabled($appId) {
422
+        $alwaysEnabled = $this->getAlwaysEnabledApps();
423
+        return in_array($appId, $alwaysEnabled, true);
424
+    }
425
+
426
+    /**
427
+     * In case you change this method, also change \OC\App\CodeChecker\InfoChecker::loadShippedJson()
428
+     * @throws \Exception
429
+     */
430
+    private function loadShippedJson() {
431
+        if ($this->shippedApps === null) {
432
+            $shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
433
+            if (!file_exists($shippedJson)) {
434
+                throw new \Exception("File not found: $shippedJson");
435
+            }
436
+            $content = json_decode(file_get_contents($shippedJson), true);
437
+            $this->shippedApps = $content['shippedApps'];
438
+            $this->alwaysEnabled = $content['alwaysEnabled'];
439
+        }
440
+    }
441
+
442
+    /**
443
+     * @inheritdoc
444
+     */
445
+    public function getAlwaysEnabledApps() {
446
+        $this->loadShippedJson();
447
+        return $this->alwaysEnabled;
448
+    }
449 449
 }
Please login to merge, or discard this patch.
Spacing   +11 added lines, -11 removed lines patch added patch discarded remove patch
@@ -113,11 +113,11 @@  discard block
 block discarded – undo
113 113
 			$values = $this->appConfig->getValues(false, 'enabled');
114 114
 
115 115
 			$alwaysEnabledApps = $this->getAlwaysEnabledApps();
116
-			foreach($alwaysEnabledApps as $appId) {
116
+			foreach ($alwaysEnabledApps as $appId) {
117 117
 				$values[$appId] = 'yes';
118 118
 			}
119 119
 
120
-			$this->installedAppsCache = array_filter($values, function ($value) {
120
+			$this->installedAppsCache = array_filter($values, function($value) {
121 121
 				return $value !== 'no';
122 122
 			});
123 123
 			ksort($this->installedAppsCache);
@@ -142,7 +142,7 @@  discard block
 block discarded – undo
142 142
 	 */
143 143
 	public function getEnabledAppsForUser(IUser $user) {
144 144
 		$apps = $this->getInstalledAppsValues();
145
-		$appsForUser = array_filter($apps, function ($enabled) use ($user) {
145
+		$appsForUser = array_filter($apps, function($enabled) use ($user) {
146 146
 			return $this->checkAppForUser($enabled, $user);
147 147
 		});
148 148
 		return array_keys($appsForUser);
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
 		} elseif ($user === null) {
182 182
 			return false;
183 183
 		} else {
184
-			if(empty($enabled)){
184
+			if (empty($enabled)) {
185 185
 				return false;
186 186
 			}
187 187
 
@@ -189,7 +189,7 @@  discard block
 block discarded – undo
189 189
 
190 190
 			if (!is_array($groupIds)) {
191 191
 				$jsonError = json_last_error();
192
-				\OC::$server->getLogger()->warning('AppManger::checkAppForUser - can\'t decode group IDs: ' . print_r($enabled, true) . ' - json error code: ' . $jsonError, ['app' => 'lib']);
192
+				\OC::$server->getLogger()->warning('AppManger::checkAppForUser - can\'t decode group IDs: '.print_r($enabled, true).' - json error code: '.$jsonError, ['app' => 'lib']);
193 193
 				return false;
194 194
 			}
195 195
 
@@ -263,7 +263,7 @@  discard block
 block discarded – undo
263 263
 			}
264 264
 		}
265 265
 
266
-		$groupIds = array_map(function ($group) {
266
+		$groupIds = array_map(function($group) {
267 267
 			/** @var \OCP\IGroup $group */
268 268
 			return $group->getGID();
269 269
 		}, $groups);
@@ -302,8 +302,8 @@  discard block
 block discarded – undo
302 302
 	 */
303 303
 	public function getAppPath($appId) {
304 304
 		$appPath = \OC_App::getAppPath($appId);
305
-		if($appPath === false) {
306
-			throw new AppPathNotFoundException('Could not find path for ' . $appId);
305
+		if ($appPath === false) {
306
+			throw new AppPathNotFoundException('Could not find path for '.$appId);
307 307
 		}
308 308
 		return $appPath;
309 309
 	}
@@ -363,7 +363,7 @@  discard block
 block discarded – undo
363 363
 			} catch (AppPathNotFoundException $e) {
364 364
 				return [];
365 365
 			}
366
-			$file = $appPath . '/appinfo/info.xml';
366
+			$file = $appPath.'/appinfo/info.xml';
367 367
 		}
368 368
 
369 369
 		$parser = new InfoParser($this->memCacheFactory->createLocal('core.appinfo'));
@@ -381,7 +381,7 @@  discard block
 block discarded – undo
381 381
 	}
382 382
 
383 383
 	public function getAppVersion(string $appId, bool $useCache = true): string {
384
-		if(!$useCache || !isset($this->appVersions[$appId])) {
384
+		if (!$useCache || !isset($this->appVersions[$appId])) {
385 385
 			$appInfo = \OC::$server->getAppManager()->getAppInfo($appId);
386 386
 			$this->appVersions[$appId] = ($appInfo !== null && isset($appInfo['version'])) ? $appInfo['version'] : '0';
387 387
 		}
@@ -429,7 +429,7 @@  discard block
 block discarded – undo
429 429
 	 */
430 430
 	private function loadShippedJson() {
431 431
 		if ($this->shippedApps === null) {
432
-			$shippedJson = \OC::$SERVERROOT . '/core/shipped.json';
432
+			$shippedJson = \OC::$SERVERROOT.'/core/shipped.json';
433 433
 			if (!file_exists($shippedJson)) {
434 434
 				throw new \Exception("File not found: $shippedJson");
435 435
 			}
Please login to merge, or discard this patch.