Completed
Push — master ( b63ea2...ba9711 )
by Morris
14:27
created

AppSettingsController::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 23
nc 1
nop 12
dl 0
loc 24
rs 8.9713
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, ownCloud, Inc.
4
 * @copyright Copyright (c) 2016, Lukas Reschke <[email protected]>
5
 *
6
 * @author Christoph Wurst <[email protected]>
7
 * @author Felix A. Epp <[email protected]>
8
 * @author Jan-Christoph Borchardt <[email protected]>
9
 * @author Joas Schilling <[email protected]>
10
 * @author Julius Härtl <[email protected]>
11
 * @author Lukas Reschke <[email protected]>
12
 * @author Morris Jobke <[email protected]>
13
 * @author Roeland Jago Douma <[email protected]>
14
 * @author Thomas Müller <[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\Settings\Controller;
33
34
use OC\App\AppStore\Bundles\BundleFetcher;
35
use OC\App\AppStore\Fetcher\AppFetcher;
36
use OC\App\AppStore\Fetcher\CategoryFetcher;
37
use OC\App\AppStore\Version\VersionParser;
38
use OC\App\DependencyAnalyzer;
39
use OC\App\Platform;
40
use OC\Installer;
41
use OCP\App\IAppManager;
42
use \OCP\AppFramework\Controller;
43
use OCP\AppFramework\Http\ContentSecurityPolicy;
44
use OCP\AppFramework\Http\JSONResponse;
45
use OCP\AppFramework\Http\TemplateResponse;
46
use OCP\INavigationManager;
47
use OCP\IRequest;
48
use OCP\IL10N;
49
use OCP\IConfig;
50
use OCP\IURLGenerator;
51
use OCP\L10N\IFactory;
52
53
/**
54
 * @package OC\Settings\Controller
55
 */
56
class AppSettingsController extends Controller {
57
	const CAT_ENABLED = 0;
58
	const CAT_DISABLED = 1;
59
	const CAT_ALL_INSTALLED = 2;
60
	const CAT_APP_BUNDLES = 3;
61
	const CAT_UPDATES = 4;
62
63
	/** @var \OCP\IL10N */
64
	private $l10n;
65
	/** @var IConfig */
66
	private $config;
67
	/** @var INavigationManager */
68
	private $navigationManager;
69
	/** @var IAppManager */
70
	private $appManager;
71
	/** @var CategoryFetcher */
72
	private $categoryFetcher;
73
	/** @var AppFetcher */
74
	private $appFetcher;
75
	/** @var IFactory */
76
	private $l10nFactory;
77
	/** @var BundleFetcher */
78
	private $bundleFetcher;
79
	/** @var Installer */
80
	private $installer;
81
	/** @var IURLGenerator */
82
	private $urlGenerator;
83
84
	/**
85
	 * @param string $appName
86
	 * @param IRequest $request
87
	 * @param IL10N $l10n
88
	 * @param IConfig $config
89
	 * @param INavigationManager $navigationManager
90
	 * @param IAppManager $appManager
91
	 * @param CategoryFetcher $categoryFetcher
92
	 * @param AppFetcher $appFetcher
93
	 * @param IFactory $l10nFactory
94
	 * @param BundleFetcher $bundleFetcher
95
	 * @param Installer $installer
96
	 * @param IURLGenerator $urlGenerator
97
	 */
98
	public function __construct(string $appName,
99
								IRequest $request,
100
								IL10N $l10n,
101
								IConfig $config,
102
								INavigationManager $navigationManager,
103
								IAppManager $appManager,
104
								CategoryFetcher $categoryFetcher,
105
								AppFetcher $appFetcher,
106
								IFactory $l10nFactory,
107
								BundleFetcher $bundleFetcher,
108
								Installer $installer,
109
								IURLGenerator $urlGenerator) {
110
		parent::__construct($appName, $request);
111
		$this->l10n = $l10n;
112
		$this->config = $config;
113
		$this->navigationManager = $navigationManager;
114
		$this->appManager = $appManager;
115
		$this->categoryFetcher = $categoryFetcher;
116
		$this->appFetcher = $appFetcher;
117
		$this->l10nFactory = $l10nFactory;
118
		$this->bundleFetcher = $bundleFetcher;
119
		$this->installer = $installer;
120
		$this->urlGenerator = $urlGenerator;
121
	}
122
123
	/**
124
	 * @NoCSRFRequired
125
	 *
126
	 * @param string $category
127
	 * @return TemplateResponse
128
	 */
129
	public function viewApps($category = '') {
130
		if ($category === '') {
131
			$category = 'installed';
132
		}
133
134
		$params = [];
135
		$params['category'] = $category;
136
		$params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
137
		$params['urlGenerator'] = $this->urlGenerator;
138
		$this->navigationManager->setActiveEntry('core_apps');
139
140
		$templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
141
		$policy = new ContentSecurityPolicy();
142
		$policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
143
		$templateResponse->setContentSecurityPolicy($policy);
144
145
		return $templateResponse;
146
	}
147
148
	private function getAllCategories() {
149
		$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
150
151
		$updateCount = count($this->getAppsWithUpdates());
152
		$formattedCategories = [
153
			['id' => self::CAT_ALL_INSTALLED, 'ident' => 'installed', 'displayName' => (string)$this->l10n->t('Your apps')],
154
			['id' => self::CAT_UPDATES, 'ident' => 'updates', 'displayName' => (string)$this->l10n->t('Updates'), 'counter' => $updateCount],
155
			['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled apps')],
156
			['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Disabled apps')],
157
			['id' => self::CAT_APP_BUNDLES, 'ident' => 'app-bundles', 'displayName' => (string)$this->l10n->t('App bundles')],
158
		];
159
		$categories = $this->categoryFetcher->get();
160
		foreach($categories as $category) {
161
			$formattedCategories[] = [
162
				'id' => $category['id'],
163
				'ident' => $category['id'],
164
				'displayName' => isset($category['translations'][$currentLanguage]['name']) ? $category['translations'][$currentLanguage]['name'] : $category['translations']['en']['name'],
165
			];
166
		}
167
168
		return $formattedCategories;
169
	}
170
171
	/**
172
	 * Get all available categories
173
	 *
174
	 * @return JSONResponse
175
	 */
176
	public function listCategories() {
177
		return new JSONResponse($this->getAllCategories());
178
	}
179
180
	/**
181
	 * Get all apps for a category
182
	 *
183
	 * @param string $requestedCategory
184
	 * @return array
185
	 */
186
	private function getAppsForCategory($requestedCategory) {
187
		$versionParser = new VersionParser();
188
		$formattedApps = [];
189
		$apps = $this->appFetcher->get();
190
		foreach($apps as $app) {
191
			if (isset($app['isFeatured'])) {
192
				$app['featured'] = $app['isFeatured'];
193
			}
194
195
			// Skip all apps not in the requested category
196
			$isInCategory = false;
197
			foreach($app['categories'] as $category) {
198
				if($category === $requestedCategory) {
199
					$isInCategory = true;
200
				}
201
			}
202
			if(!$isInCategory) {
203
				continue;
204
			}
205
206
			$nextCloudVersion = $versionParser->getVersion($app['releases'][0]['rawPlatformVersionSpec']);
207
			$nextCloudVersionDependencies = [];
208
			if($nextCloudVersion->getMinimumVersion() !== '') {
209
				$nextCloudVersionDependencies['nextcloud']['@attributes']['min-version'] = $nextCloudVersion->getMinimumVersion();
210
			}
211
			if($nextCloudVersion->getMaximumVersion() !== '') {
212
				$nextCloudVersionDependencies['nextcloud']['@attributes']['max-version'] = $nextCloudVersion->getMaximumVersion();
213
			}
214
			$phpVersion = $versionParser->getVersion($app['releases'][0]['rawPhpVersionSpec']);
215
			$existsLocally = \OC_App::getAppPath($app['id']) !== false;
216
			$phpDependencies = [];
217
			if($phpVersion->getMinimumVersion() !== '') {
218
				$phpDependencies['php']['@attributes']['min-version'] = $phpVersion->getMinimumVersion();
219
			}
220
			if($phpVersion->getMaximumVersion() !== '') {
221
				$phpDependencies['php']['@attributes']['max-version'] = $phpVersion->getMaximumVersion();
222
			}
223
			if(isset($app['releases'][0]['minIntSize'])) {
224
				$phpDependencies['php']['@attributes']['min-int-size'] = $app['releases'][0]['minIntSize'];
225
			}
226
			$authors = '';
227
			foreach($app['authors'] as $key => $author) {
228
				$authors .= $author['name'];
229
				if($key !== count($app['authors']) - 1) {
230
					$authors .= ', ';
231
				}
232
			}
233
234
			$currentLanguage = substr(\OC::$server->getL10NFactory()->findLanguage(), 0, 2);
235
			$enabledValue = $this->config->getAppValue($app['id'], 'enabled', 'no');
236
			$groups = null;
237
			if($enabledValue !== 'no' && $enabledValue !== 'yes') {
238
				$groups = $enabledValue;
239
			}
240
241
			$currentVersion = '';
242
			if($this->appManager->isInstalled($app['id'])) {
243
				$currentVersion = \OC_App::getAppVersion($app['id']);
244
			} else {
245
				$currentLanguage = $app['releases'][0]['version'];
246
			}
247
248
			$formattedApps[] = [
249
				'id' => $app['id'],
250
				'name' => isset($app['translations'][$currentLanguage]['name']) ? $app['translations'][$currentLanguage]['name'] : $app['translations']['en']['name'],
251
				'description' => isset($app['translations'][$currentLanguage]['description']) ? $app['translations'][$currentLanguage]['description'] : $app['translations']['en']['description'],
252
				'license' => $app['releases'][0]['licenses'],
253
				'author' => $authors,
254
				'shipped' => false,
255
				'version' => $currentVersion,
256
				'default_enable' => '',
257
				'types' => [],
258
				'documentation' => [
259
					'admin' => $app['adminDocs'],
260
					'user' => $app['userDocs'],
261
					'developer' => $app['developerDocs']
262
				],
263
				'website' => $app['website'],
264
				'bugs' => $app['issueTracker'],
265
				'detailpage' => $app['website'],
266
				'dependencies' => array_merge(
267
					$nextCloudVersionDependencies,
268
					$phpDependencies
269
				),
270
				'level' => ($app['featured'] === true) ? 200 : 100,
271
				'missingMaxOwnCloudVersion' => false,
272
				'missingMinOwnCloudVersion' => false,
273
				'canInstall' => true,
274
				'preview' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($app['screenshots'][0]['url']) : '',
275
				'score' => $app['ratingOverall'],
276
				'ratingNumOverall' => $app['ratingNumOverall'],
277
				'ratingNumThresholdReached' => $app['ratingNumOverall'] > 5 ? true : false,
278
				'removable' => $existsLocally,
279
				'active' => $this->appManager->isEnabledForUser($app['id']),
280
				'needsDownload' => !$existsLocally,
281
				'groups' => $groups,
282
				'fromAppStore' => true,
283
			];
284
285
286
			$newVersion = $this->installer->isUpdateAvailable($app['id']);
287
			if($newVersion && $this->appManager->isInstalled($app['id'])) {
288
				$formattedApps[count($formattedApps)-1]['update'] = $newVersion;
289
			}
290
		}
291
292
		return $formattedApps;
293
	}
294
295
	private function getAppsWithUpdates() {
296
		$appClass = new \OC_App();
297
		$apps = $appClass->listAllApps();
298
		foreach($apps as $key => $app) {
299
			$newVersion = $this->installer->isUpdateAvailable($app['id']);
300
			if($newVersion !== false) {
301
				$apps[$key]['update'] = $newVersion;
302
			} else {
303
				unset($apps[$key]);
304
			}
305
		}
306 View Code Duplication
		usort($apps, function ($a, $b) {
307
			$a = (string)$a['name'];
308
			$b = (string)$b['name'];
309
			if ($a === $b) {
310
				return 0;
311
			}
312
			return ($a < $b) ? -1 : 1;
313
		});
314
		return $apps;
315
	}
316
317
	/**
318
	 * Get all available apps in a category
319
	 *
320
	 * @param string $category
321
	 * @return JSONResponse
322
	 */
323
	public function listApps($category = '') {
324
		$appClass = new \OC_App();
325
326
		switch ($category) {
327
			// installed apps
328
			case 'installed':
329
				$apps = $appClass->listAllApps();
330
331 View Code Duplication
				foreach($apps as $key => $app) {
332
					$newVersion = $this->installer->isUpdateAvailable($app['id']);
333
					$apps[$key]['update'] = $newVersion;
334
				}
335
336 View Code Duplication
				usort($apps, function ($a, $b) {
337
					$a = (string)$a['name'];
338
					$b = (string)$b['name'];
339
					if ($a === $b) {
340
						return 0;
341
					}
342
					return ($a < $b) ? -1 : 1;
343
				});
344
				break;
345
			// updates
346
			case 'updates':
347
				$apps = $this->getAppsWithUpdates();
348
				break;
349
			// enabled apps
350
			case 'enabled':
351
				$apps = $appClass->listAllApps();
352
				$apps = array_filter($apps, function ($app) {
353
					return $app['active'];
354
				});
355
356 View Code Duplication
				foreach($apps as $key => $app) {
357
					$newVersion = $this->installer->isUpdateAvailable($app['id']);
358
					$apps[$key]['update'] = $newVersion;
359
				}
360
361 View Code Duplication
				usort($apps, function ($a, $b) {
362
					$a = (string)$a['name'];
363
					$b = (string)$b['name'];
364
					if ($a === $b) {
365
						return 0;
366
					}
367
					return ($a < $b) ? -1 : 1;
368
				});
369
				break;
370
			// disabled  apps
371
			case 'disabled':
372
				$apps = $appClass->listAllApps();
373
				$apps = array_filter($apps, function ($app) {
374
					return !$app['active'];
375
				});
376
377
				$apps = array_map(function ($app) {
378
					$newVersion = $this->installer->isUpdateAvailable($app['id']);
379
					if ($newVersion !== false) {
380
						$app['update'] = $newVersion;
381
					}
382
					return $app;
383
				}, $apps);
384
385 View Code Duplication
				usort($apps, function ($a, $b) {
386
					$a = (string)$a['name'];
387
					$b = (string)$b['name'];
388
					if ($a === $b) {
389
						return 0;
390
					}
391
					return ($a < $b) ? -1 : 1;
392
				});
393
				break;
394
			case 'app-bundles':
395
				$bundles = $this->bundleFetcher->getBundles();
396
				$apps = [];
397
				foreach($bundles as $bundle) {
398
					$newCategory = true;
399
					$allApps = $appClass->listAllApps();
400
					$categories = $this->getAllCategories();
401
					foreach($categories as $singleCategory) {
402
						$newApps = $this->getAppsForCategory($singleCategory['id']);
403
						foreach($allApps as $app) {
404
							foreach($newApps as $key => $newApp) {
405
								if($app['id'] === $newApp['id']) {
406
									unset($newApps[$key]);
407
								}
408
							}
409
						}
410
						$allApps = array_merge($allApps, $newApps);
411
					}
412
413
					foreach($bundle->getAppIdentifiers() as $identifier) {
414
						foreach($allApps as $app) {
415
							if($app['id'] === $identifier) {
416
								if($newCategory) {
417
									$app['newCategory'] = true;
418
									$app['categoryName'] = $bundle->getName();
419
								}
420
								$app['bundleId'] = $bundle->getIdentifier();
421
								$newCategory = false;
422
								$apps[] = $app;
423
								continue;
424
							}
425
						}
426
					}
427
				}
428
				break;
429
			default:
430
				$apps = $this->getAppsForCategory($category);
431
432
				// sort by score
433
				usort($apps, function ($a, $b) {
434
					$a = (int)$a['score'];
435
					$b = (int)$b['score'];
436
					if ($a === $b) {
437
						return 0;
438
					}
439
					return ($a > $b) ? -1 : 1;
440
				});
441
				break;
442
		}
443
444
		// fix groups to be an array
445
		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
446
		$apps = array_map(function($app) use ($dependencyAnalyzer) {
447
448
			// fix groups
449
			$groups = array();
450
			if (is_string($app['groups'])) {
451
				$groups = json_decode($app['groups']);
452
			}
453
			$app['groups'] = $groups;
454
			$app['canUnInstall'] = !$app['active'] && $app['removable'];
455
456
			// fix licence vs license
457
			if (isset($app['license']) && !isset($app['licence'])) {
458
				$app['licence'] = $app['license'];
459
			}
460
461
			// analyse dependencies
462
			$missing = $dependencyAnalyzer->analyze($app);
463
			$app['canInstall'] = empty($missing);
464
			$app['missingDependencies'] = $missing;
465
466
			$app['missingMinOwnCloudVersion'] = !isset($app['dependencies']['nextcloud']['@attributes']['min-version']);
467
			$app['missingMaxOwnCloudVersion'] = !isset($app['dependencies']['nextcloud']['@attributes']['max-version']);
468
469
			return $app;
470
		}, $apps);
471
472
		return new JSONResponse(['apps' => $apps, 'status' => 'success']);
473
	}
474
}
475