Completed
Push — master ( bcf587...5a9224 )
by Morris
19:50 queued 04:43
created

AppSettingsController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 17
nc 1
nop 9
dl 0
loc 18
rs 9.4285
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 Joas Schilling <[email protected]>
8
 * @author Lukas Reschke <[email protected]>
9
 * @author Morris Jobke <[email protected]>
10
 * @author Thomas Müller <[email protected]>
11
 *
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
28
namespace OC\Settings\Controller;
29
30
use OC\App\AppStore\Fetcher\AppFetcher;
31
use OC\App\AppStore\Fetcher\CategoryFetcher;
32
use OC\App\AppStore\Version\VersionParser;
33
use OC\App\DependencyAnalyzer;
34
use OC\App\Platform;
35
use OCP\App\IAppManager;
36
use \OCP\AppFramework\Controller;
37
use OCP\AppFramework\Http\ContentSecurityPolicy;
38
use OCP\AppFramework\Http\JSONResponse;
39
use OCP\AppFramework\Http\TemplateResponse;
40
use OCP\INavigationManager;
41
use OCP\IRequest;
42
use OCP\IL10N;
43
use OCP\IConfig;
44
use OCP\L10N\IFactory;
45
46
/**
47
 * @package OC\Settings\Controller
48
 */
49
class AppSettingsController extends Controller {
50
	const CAT_ENABLED = 0;
51
	const CAT_DISABLED = 1;
52
	const CAT_ALL_INSTALLED = 2;
53
54
	/** @var \OCP\IL10N */
55
	private $l10n;
56
	/** @var IConfig */
57
	private $config;
58
	/** @var INavigationManager */
59
	private $navigationManager;
60
	/** @var IAppManager */
61
	private $appManager;
62
	/** @var CategoryFetcher */
63
	private $categoryFetcher;
64
	/** @var AppFetcher */
65
	private $appFetcher;
66
	/** @var IFactory */
67
	private $l10nFactory;
68
69
	/**
70
	 * @param string $appName
71
	 * @param IRequest $request
72
	 * @param IL10N $l10n
73
	 * @param IConfig $config
74
	 * @param INavigationManager $navigationManager
75
	 * @param IAppManager $appManager
76
	 * @param CategoryFetcher $categoryFetcher
77
	 * @param AppFetcher $appFetcher
78
	 * @param IFactory $l10nFactory
79
	 */
80
	public function __construct($appName,
81
								IRequest $request,
82
								IL10N $l10n,
83
								IConfig $config,
84
								INavigationManager $navigationManager,
85
								IAppManager $appManager,
86
								CategoryFetcher $categoryFetcher,
87
								AppFetcher $appFetcher,
88
								IFactory $l10nFactory) {
89
		parent::__construct($appName, $request);
90
		$this->l10n = $l10n;
91
		$this->config = $config;
92
		$this->navigationManager = $navigationManager;
93
		$this->appManager = $appManager;
94
		$this->categoryFetcher = $categoryFetcher;
95
		$this->appFetcher = $appFetcher;
96
		$this->l10nFactory = $l10nFactory;
97
	}
98
99
	/**
100
	 * @NoCSRFRequired
101
	 *
102
	 * @param string $category
103
	 * @return TemplateResponse
104
	 */
105
	public function viewApps($category = '') {
106
		if ($category === '') {
107
			$category = 'installed';
108
		}
109
110
		$params = [];
111
		$params['category'] = $category;
112
		$params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true;
113
		$this->navigationManager->setActiveEntry('core_apps');
114
115
		$templateResponse = new TemplateResponse($this->appName, 'apps', $params, 'user');
116
		$policy = new ContentSecurityPolicy();
117
		$policy->addAllowedImageDomain('https://usercontent.apps.nextcloud.com');
118
		$templateResponse->setContentSecurityPolicy($policy);
119
120
		return $templateResponse;
121
	}
122
123
	/**
124
	 * Get all available categories
125
	 *
126
	 * @return JSONResponse
127
	 */
128
	public function listCategories() {
129
		$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2);
130
131
		$formattedCategories = [
132
			['id' => self::CAT_ALL_INSTALLED, 'ident' => 'installed', 'displayName' => (string)$this->l10n->t('Your apps')],
133
			['id' => self::CAT_ENABLED, 'ident' => 'enabled', 'displayName' => (string)$this->l10n->t('Enabled apps')],
134
			['id' => self::CAT_DISABLED, 'ident' => 'disabled', 'displayName' => (string)$this->l10n->t('Disabled apps')],
135
		];
136
		$categories = $this->categoryFetcher->get();
137
		foreach($categories as $category) {
138
			$formattedCategories[] = [
139
				'id' => $category['id'],
140
				'ident' => $category['id'],
141
				'displayName' => isset($category['translations'][$currentLanguage]['name']) ? $category['translations'][$currentLanguage]['name'] : $category['translations']['en']['name'],
142
			];
143
		}
144
145
		return new JSONResponse($formattedCategories);
146
	}
147
148
	/**
149
	 * Get all apps for a category
150
	 *
151
	 * @param string $requestedCategory
152
	 * @return array
153
	 */
154
	private function getAppsForCategory($requestedCategory) {
155
		$versionParser = new VersionParser();
156
		$formattedApps = [];
157
		$apps = $this->appFetcher->get();
158
		foreach($apps as $app) {
159
			if (isset($app['isFeatured'])) {
160
				$app['featured'] = $app['isFeatured'];
161
			}
162
163
			// Skip all apps not in the requested category
164
			$isInCategory = false;
165
			foreach($app['categories'] as $category) {
166
				if($category === $requestedCategory) {
167
					$isInCategory = true;
168
				}
169
			}
170
			if(!$isInCategory) {
171
				continue;
172
			}
173
174
			$nextCloudVersion = $versionParser->getVersion($app['releases'][0]['rawPlatformVersionSpec']);
175
			$nextCloudVersionDependencies = [];
176
			if($nextCloudVersion->getMinimumVersion() !== '') {
177
				$nextCloudVersionDependencies['nextcloud']['@attributes']['min-version'] = $nextCloudVersion->getMinimumVersion();
178
			}
179
			if($nextCloudVersion->getMaximumVersion() !== '') {
180
				$nextCloudVersionDependencies['nextcloud']['@attributes']['max-version'] = $nextCloudVersion->getMaximumVersion();
181
			}
182
			$phpVersion = $versionParser->getVersion($app['releases'][0]['rawPhpVersionSpec']);
183
			$existsLocally = (\OC_App::getAppPath($app['id']) !== false) ? true : false;
184
			$phpDependencies = [];
185
			if($phpVersion->getMinimumVersion() !== '') {
186
				$phpDependencies['php']['@attributes']['min-version'] = $phpVersion->getMinimumVersion();
187
			}
188
			if($phpVersion->getMaximumVersion() !== '') {
189
				$phpDependencies['php']['@attributes']['max-version'] = $phpVersion->getMaximumVersion();
190
			}
191
			if(isset($app['releases'][0]['minIntSize'])) {
192
				$phpDependencies['php']['@attributes']['min-int-size'] = $app['releases'][0]['minIntSize'];
193
			}
194
			$authors = '';
195
			foreach($app['authors'] as $key => $author) {
196
				$authors .= $author['name'];
197
				if($key !== count($app['authors']) - 1) {
198
					$authors .= ', ';
199
				}
200
			}
201
202
			$currentLanguage = substr(\OC::$server->getL10NFactory()->findLanguage(), 0, 2);
203
			$enabledValue = $this->config->getAppValue($app['id'], 'enabled', 'no');
204
			$groups = null;
205
			if($enabledValue !== 'no' && $enabledValue !== 'yes') {
206
				$groups = $enabledValue;
207
			}
208
209
			$currentVersion = '';
210
			if($this->appManager->isInstalled($app['id'])) {
211
				$currentVersion = \OC_App::getAppVersion($app['id']);
212
			} else {
213
				$currentLanguage = $app['releases'][0]['version'];
214
			}
215
216
			$formattedApps[] = [
217
				'id' => $app['id'],
218
				'name' => isset($app['translations'][$currentLanguage]['name']) ? $app['translations'][$currentLanguage]['name'] : $app['translations']['en']['name'],
219
				'description' => isset($app['translations'][$currentLanguage]['description']) ? $app['translations'][$currentLanguage]['description'] : $app['translations']['en']['description'],
220
				'license' => $app['releases'][0]['licenses'],
221
				'author' => $authors,
222
				'shipped' => false,
223
				'version' => $currentVersion,
224
				'default_enable' => '',
225
				'types' => [],
226
				'documentation' => [
227
					'admin' => $app['adminDocs'],
228
					'user' => $app['userDocs'],
229
					'developer' => $app['developerDocs']
230
				],
231
				'website' => $app['website'],
232
				'bugs' => $app['issueTracker'],
233
				'detailpage' => $app['website'],
234
				'dependencies' => array_merge(
235
					$nextCloudVersionDependencies,
236
					$phpDependencies
237
				),
238
				'level' => ($app['featured'] === true) ? 200 : 100,
239
				'missingMaxOwnCloudVersion' => false,
240
				'missingMinOwnCloudVersion' => false,
241
				'canInstall' => true,
242
				'preview' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($app['screenshots'][0]['url']) : '',
243
				'score' => $app['ratingOverall'],
244
				'ratingNumOverall' => $app['ratingNumOverall'],
245
				'ratingNumThresholdReached' => $app['ratingNumOverall'] > 5 ? true : false,
246
				'removable' => $existsLocally,
247
				'active' => $this->appManager->isEnabledForUser($app['id']),
248
				'needsDownload' => !$existsLocally,
249
				'groups' => $groups,
250
				'fromAppStore' => true,
251
			];
252
253
254
			$appFetcher = \OC::$server->getAppFetcher();
255
			$newVersion = \OC\Installer::isUpdateAvailable($app['id'], $appFetcher);
256
			if($newVersion && $this->appManager->isInstalled($app['id'])) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $newVersion 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...
257
				$formattedApps[count($formattedApps)-1]['update'] = $newVersion;
258
			}
259
		}
260
261
		return $formattedApps;
262
	}
263
264
	/**
265
	 * Get all available apps in a category
266
	 *
267
	 * @param string $category
268
	 * @return JSONResponse
269
	 */
270
	public function listApps($category = '') {
271
		$appClass = new \OC_App();
272
273
		switch ($category) {
274
			// installed apps
275
			case 'installed':
276
				$apps = $appClass->listAllApps();
277
278 View Code Duplication
				foreach($apps as $key => $app) {
279
					$newVersion = \OC\Installer::isUpdateAvailable($app['id'], $this->appFetcher);
280
					$apps[$key]['update'] = $newVersion;
281
				}
282
283 View Code Duplication
				usort($apps, function ($a, $b) {
284
					$a = (string)$a['name'];
285
					$b = (string)$b['name'];
286
					if ($a === $b) {
287
						return 0;
288
					}
289
					return ($a < $b) ? -1 : 1;
290
				});
291
				break;
292
			// enabled apps
293
			case 'enabled':
294
				$apps = $appClass->listAllApps();
295
				$apps = array_filter($apps, function ($app) {
296
					return $app['active'];
297
				});
298
299 View Code Duplication
				foreach($apps as $key => $app) {
300
					$newVersion = \OC\Installer::isUpdateAvailable($app['id'], $this->appFetcher);
301
					$apps[$key]['update'] = $newVersion;
302
				}
303
304 View Code Duplication
				usort($apps, function ($a, $b) {
305
					$a = (string)$a['name'];
306
					$b = (string)$b['name'];
307
					if ($a === $b) {
308
						return 0;
309
					}
310
					return ($a < $b) ? -1 : 1;
311
				});
312
				break;
313
			// disabled  apps
314
			case 'disabled':
315
				$apps = $appClass->listAllApps();
316
				$apps = array_filter($apps, function ($app) {
317
					return !$app['active'];
318
				});
319
320
				$apps = array_map(function ($app) {
321
					$newVersion = \OC\Installer::isUpdateAvailable($app['id'], $this->appFetcher);
322
					if ($newVersion !== false) {
323
						$app['update'] = $newVersion;
324
					}
325
					return $app;
326
				}, $apps);
327
328 View Code Duplication
				usort($apps, function ($a, $b) {
329
					$a = (string)$a['name'];
330
					$b = (string)$b['name'];
331
					if ($a === $b) {
332
						return 0;
333
					}
334
					return ($a < $b) ? -1 : 1;
335
				});
336
				break;
337
			default:
338
				$apps = $this->getAppsForCategory($category);
339
340
				// sort by score
341
				usort($apps, function ($a, $b) {
342
					$a = (int)$a['score'];
343
					$b = (int)$b['score'];
344
					if ($a === $b) {
345
						return 0;
346
					}
347
					return ($a > $b) ? -1 : 1;
348
				});
349
				break;
350
		}
351
352
		// fix groups to be an array
353
		$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n);
354
		$apps = array_map(function($app) use ($dependencyAnalyzer) {
355
356
			// fix groups
357
			$groups = array();
358
			if (is_string($app['groups'])) {
359
				$groups = json_decode($app['groups']);
360
			}
361
			$app['groups'] = $groups;
362
			$app['canUnInstall'] = !$app['active'] && $app['removable'];
363
364
			// fix licence vs license
365
			if (isset($app['license']) && !isset($app['licence'])) {
366
				$app['licence'] = $app['license'];
367
			}
368
369
			// analyse dependencies
370
			$missing = $dependencyAnalyzer->analyze($app);
371
			$app['canInstall'] = empty($missing);
372
			$app['missingDependencies'] = $missing;
373
374
			$app['missingMinOwnCloudVersion'] = !isset($app['dependencies']['nextcloud']['@attributes']['min-version']);
375
			$app['missingMaxOwnCloudVersion'] = !isset($app['dependencies']['nextcloud']['@attributes']['max-version']);
376
377
			return $app;
378
		}, $apps);
379
380
		return new JSONResponse(['apps' => $apps, 'status' => 'success']);
381
	}
382
}
383