|
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 OCA\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 OC_App; |
|
42
|
|
|
use OCP\App\IAppManager; |
|
43
|
|
|
use \OCP\AppFramework\Controller; |
|
44
|
|
|
use OCP\AppFramework\Http; |
|
45
|
|
|
use OCP\AppFramework\Http\ContentSecurityPolicy; |
|
46
|
|
|
use OCP\AppFramework\Http\JSONResponse; |
|
47
|
|
|
use OCP\AppFramework\Http\TemplateResponse; |
|
48
|
|
|
use OCP\ILogger; |
|
49
|
|
|
use OCP\INavigationManager; |
|
50
|
|
|
use OCP\IRequest; |
|
51
|
|
|
use OCP\IL10N; |
|
52
|
|
|
use OCP\IConfig; |
|
53
|
|
|
use OCP\IURLGenerator; |
|
54
|
|
|
use OCP\L10N\IFactory; |
|
55
|
|
|
|
|
56
|
|
|
class AppSettingsController extends Controller { |
|
57
|
|
|
|
|
58
|
|
|
/** @var \OCP\IL10N */ |
|
59
|
|
|
private $l10n; |
|
60
|
|
|
/** @var IConfig */ |
|
61
|
|
|
private $config; |
|
62
|
|
|
/** @var INavigationManager */ |
|
63
|
|
|
private $navigationManager; |
|
64
|
|
|
/** @var IAppManager */ |
|
65
|
|
|
private $appManager; |
|
66
|
|
|
/** @var CategoryFetcher */ |
|
67
|
|
|
private $categoryFetcher; |
|
68
|
|
|
/** @var AppFetcher */ |
|
69
|
|
|
private $appFetcher; |
|
70
|
|
|
/** @var IFactory */ |
|
71
|
|
|
private $l10nFactory; |
|
72
|
|
|
/** @var BundleFetcher */ |
|
73
|
|
|
private $bundleFetcher; |
|
74
|
|
|
/** @var Installer */ |
|
75
|
|
|
private $installer; |
|
76
|
|
|
/** @var IURLGenerator */ |
|
77
|
|
|
private $urlGenerator; |
|
78
|
|
|
/** @var ILogger */ |
|
79
|
|
|
private $logger; |
|
80
|
|
|
|
|
81
|
|
|
/** @var array */ |
|
82
|
|
|
private $allApps = []; |
|
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
|
|
|
* @param ILogger $logger |
|
98
|
|
|
*/ |
|
99
|
|
|
public function __construct(string $appName, |
|
100
|
|
|
IRequest $request, |
|
101
|
|
|
IL10N $l10n, |
|
102
|
|
|
IConfig $config, |
|
103
|
|
|
INavigationManager $navigationManager, |
|
104
|
|
|
IAppManager $appManager, |
|
105
|
|
|
CategoryFetcher $categoryFetcher, |
|
106
|
|
|
AppFetcher $appFetcher, |
|
107
|
|
|
IFactory $l10nFactory, |
|
108
|
|
|
BundleFetcher $bundleFetcher, |
|
109
|
|
|
Installer $installer, |
|
110
|
|
|
IURLGenerator $urlGenerator, |
|
111
|
|
|
ILogger $logger) { |
|
112
|
|
|
parent::__construct($appName, $request); |
|
113
|
|
|
$this->l10n = $l10n; |
|
114
|
|
|
$this->config = $config; |
|
115
|
|
|
$this->navigationManager = $navigationManager; |
|
116
|
|
|
$this->appManager = $appManager; |
|
117
|
|
|
$this->categoryFetcher = $categoryFetcher; |
|
118
|
|
|
$this->appFetcher = $appFetcher; |
|
119
|
|
|
$this->l10nFactory = $l10nFactory; |
|
120
|
|
|
$this->bundleFetcher = $bundleFetcher; |
|
121
|
|
|
$this->installer = $installer; |
|
122
|
|
|
$this->urlGenerator = $urlGenerator; |
|
123
|
|
|
$this->logger = $logger; |
|
124
|
|
|
} |
|
125
|
|
|
|
|
126
|
|
|
/** |
|
127
|
|
|
* @NoCSRFRequired |
|
128
|
|
|
* |
|
129
|
|
|
* @return TemplateResponse |
|
130
|
|
|
*/ |
|
131
|
|
|
public function viewApps(): TemplateResponse { |
|
132
|
|
|
\OC_Util::addScript('settings', 'apps'); |
|
133
|
|
|
$params = []; |
|
134
|
|
|
$params['appstoreEnabled'] = $this->config->getSystemValue('appstoreenabled', true) === true; |
|
135
|
|
|
$params['updateCount'] = count($this->getAppsWithUpdates()); |
|
136
|
|
|
$params['developerDocumentation'] = $this->urlGenerator->linkToDocs('developer-manual'); |
|
137
|
|
|
$params['bundles'] = $this->getBundles(); |
|
138
|
|
|
$this->navigationManager->setActiveEntry('core_apps'); |
|
139
|
|
|
|
|
140
|
|
|
$templateResponse = new TemplateResponse('settings', 'settings-vue', ['serverData' => $params]); |
|
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 getAppsWithUpdates() { |
|
149
|
|
|
$appClass = new \OC_App(); |
|
150
|
|
|
$apps = $appClass->listAllApps(); |
|
151
|
|
|
foreach($apps as $key => $app) { |
|
152
|
|
|
$newVersion = $this->installer->isUpdateAvailable($app['id']); |
|
153
|
|
|
if($newVersion === false) { |
|
154
|
|
|
unset($apps[$key]); |
|
155
|
|
|
} |
|
156
|
|
|
} |
|
157
|
|
|
return $apps; |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
private function getBundles() { |
|
161
|
|
|
$result = []; |
|
162
|
|
|
$bundles = $this->bundleFetcher->getBundles(); |
|
163
|
|
|
foreach ($bundles as $bundle) { |
|
164
|
|
|
$result[] = [ |
|
165
|
|
|
'name' => $bundle->getName(), |
|
166
|
|
|
'id' => $bundle->getIdentifier(), |
|
167
|
|
|
'appIdentifiers' => $bundle->getAppIdentifiers() |
|
168
|
|
|
]; |
|
169
|
|
|
} |
|
170
|
|
|
return $result; |
|
171
|
|
|
|
|
172
|
|
|
} |
|
173
|
|
|
|
|
174
|
|
|
/** |
|
175
|
|
|
* Get all available categories |
|
176
|
|
|
* |
|
177
|
|
|
* @return JSONResponse |
|
178
|
|
|
*/ |
|
179
|
|
|
public function listCategories(): JSONResponse { |
|
180
|
|
|
return new JSONResponse($this->getAllCategories()); |
|
181
|
|
|
} |
|
182
|
|
|
|
|
183
|
|
|
private function getAllCategories() { |
|
184
|
|
|
$currentLanguage = substr($this->l10nFactory->findLanguage(), 0, 2); |
|
185
|
|
|
|
|
186
|
|
|
$formattedCategories = []; |
|
187
|
|
|
$categories = $this->categoryFetcher->get(); |
|
188
|
|
|
foreach($categories as $category) { |
|
189
|
|
|
$formattedCategories[] = [ |
|
190
|
|
|
'id' => $category['id'], |
|
191
|
|
|
'ident' => $category['id'], |
|
192
|
|
|
'displayName' => isset($category['translations'][$currentLanguage]['name']) ? $category['translations'][$currentLanguage]['name'] : $category['translations']['en']['name'], |
|
193
|
|
|
]; |
|
194
|
|
|
} |
|
195
|
|
|
|
|
196
|
|
|
return $formattedCategories; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
private function fetchApps() { |
|
200
|
|
|
$appClass = new \OC_App(); |
|
201
|
|
|
$apps = $appClass->listAllApps(); |
|
202
|
|
|
foreach ($apps as $app) { |
|
203
|
|
|
$app['installed'] = true; |
|
204
|
|
|
$this->allApps[$app['id']] = $app; |
|
205
|
|
|
} |
|
206
|
|
|
|
|
207
|
|
|
$apps = $this->getAppsForCategory(''); |
|
208
|
|
|
foreach ($apps as $app) { |
|
209
|
|
|
$app['appstore'] = true; |
|
210
|
|
|
if (!array_key_exists($app['id'], $this->allApps)) { |
|
211
|
|
|
$this->allApps[$app['id']] = $app; |
|
212
|
|
|
} else { |
|
213
|
|
|
$this->allApps[$app['id']] = array_merge($app, $this->allApps[$app['id']]); |
|
214
|
|
|
} |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
// add bundle information |
|
218
|
|
|
$bundles = $this->bundleFetcher->getBundles(); |
|
219
|
|
|
foreach($bundles as $bundle) { |
|
220
|
|
|
foreach($bundle->getAppIdentifiers() as $identifier) { |
|
221
|
|
|
foreach($this->allApps as &$app) { |
|
222
|
|
|
if($app['id'] === $identifier) { |
|
223
|
|
|
$app['bundleId'] = $bundle->getIdentifier(); |
|
224
|
|
|
continue; |
|
225
|
|
|
} |
|
226
|
|
|
} |
|
227
|
|
|
} |
|
228
|
|
|
} |
|
229
|
|
|
} |
|
230
|
|
|
|
|
231
|
|
|
private function getAllApps() { |
|
232
|
|
|
return $this->allApps; |
|
233
|
|
|
} |
|
234
|
|
|
/** |
|
235
|
|
|
* Get all available apps in a category |
|
236
|
|
|
* |
|
237
|
|
|
* @param string $category |
|
238
|
|
|
* @return JSONResponse |
|
239
|
|
|
* @throws \Exception |
|
240
|
|
|
*/ |
|
241
|
|
|
public function listApps(): JSONResponse { |
|
242
|
|
|
|
|
243
|
|
|
$this->fetchApps(); |
|
244
|
|
|
$apps = $this->getAllApps(); |
|
245
|
|
|
|
|
246
|
|
|
$dependencyAnalyzer = new DependencyAnalyzer(new Platform($this->config), $this->l10n); |
|
247
|
|
|
|
|
248
|
|
|
// Extend existing app details |
|
249
|
|
|
$apps = array_map(function($appData) use ($dependencyAnalyzer) { |
|
250
|
|
|
if (isset($appData['appstoreData'])) { |
|
251
|
|
|
$appstoreData = $appData['appstoreData']; |
|
252
|
|
|
$appData['screenshot'] = isset($appstoreData['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/' . base64_encode($appstoreData['screenshots'][0]['url']) : ''; |
|
253
|
|
|
$appData['category'] = $appstoreData['categories']; |
|
254
|
|
|
} |
|
255
|
|
|
|
|
256
|
|
|
$newVersion = $this->installer->isUpdateAvailable($appData['id']); |
|
257
|
|
|
if($newVersion) { |
|
258
|
|
|
$appData['update'] = $newVersion; |
|
259
|
|
|
} |
|
260
|
|
|
|
|
261
|
|
|
// fix groups to be an array |
|
262
|
|
|
$groups = array(); |
|
263
|
|
|
if (is_string($appData['groups'])) { |
|
264
|
|
|
$groups = json_decode($appData['groups']); |
|
265
|
|
|
} |
|
266
|
|
|
$appData['groups'] = $groups; |
|
267
|
|
|
$appData['canUnInstall'] = !$appData['active'] && $appData['removable']; |
|
268
|
|
|
|
|
269
|
|
|
// fix licence vs license |
|
270
|
|
|
if (isset($appData['license']) && !isset($appData['licence'])) { |
|
271
|
|
|
$appData['licence'] = $appData['license']; |
|
272
|
|
|
} |
|
273
|
|
|
|
|
274
|
|
|
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); |
|
275
|
|
|
$ignoreMax = in_array($appData['id'], $ignoreMaxApps); |
|
276
|
|
|
|
|
277
|
|
|
// analyse dependencies |
|
278
|
|
|
$missing = $dependencyAnalyzer->analyze($appData, $ignoreMax); |
|
279
|
|
|
$appData['canInstall'] = empty($missing); |
|
280
|
|
|
$appData['missingDependencies'] = $missing; |
|
281
|
|
|
|
|
282
|
|
|
$appData['missingMinOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['min-version']); |
|
283
|
|
|
$appData['missingMaxOwnCloudVersion'] = !isset($appData['dependencies']['nextcloud']['@attributes']['max-version']); |
|
284
|
|
|
$appData['isCompatible'] = $dependencyAnalyzer->isMarkedCompatible($appData); |
|
285
|
|
|
|
|
286
|
|
|
return $appData; |
|
287
|
|
|
}, $apps); |
|
288
|
|
|
|
|
289
|
|
|
usort($apps, [$this, 'sortApps']); |
|
290
|
|
|
|
|
291
|
|
|
return new JSONResponse(['apps' => $apps, 'status' => 'success']); |
|
292
|
|
|
} |
|
293
|
|
|
|
|
294
|
|
|
/** |
|
295
|
|
|
* Get all apps for a category from the app store |
|
296
|
|
|
* |
|
297
|
|
|
* @param string $requestedCategory |
|
298
|
|
|
* @return array |
|
299
|
|
|
* @throws \Exception |
|
300
|
|
|
*/ |
|
301
|
|
|
private function getAppsForCategory($requestedCategory = ''): array { |
|
302
|
|
|
$versionParser = new VersionParser(); |
|
303
|
|
|
$formattedApps = []; |
|
304
|
|
|
$apps = $this->appFetcher->get(); |
|
305
|
|
|
foreach($apps as $app) { |
|
306
|
|
|
// Skip all apps not in the requested category |
|
307
|
|
|
if ($requestedCategory !== '') { |
|
308
|
|
|
$isInCategory = false; |
|
309
|
|
|
foreach($app['categories'] as $category) { |
|
310
|
|
|
if($category === $requestedCategory) { |
|
311
|
|
|
$isInCategory = true; |
|
312
|
|
|
} |
|
313
|
|
|
} |
|
314
|
|
|
if(!$isInCategory) { |
|
315
|
|
|
continue; |
|
316
|
|
|
} |
|
317
|
|
|
} |
|
318
|
|
|
|
|
319
|
|
|
if (!isset($app['releases'][0]['rawPlatformVersionSpec'])) { |
|
320
|
|
|
continue; |
|
321
|
|
|
} |
|
322
|
|
|
$nextCloudVersion = $versionParser->getVersion($app['releases'][0]['rawPlatformVersionSpec']); |
|
323
|
|
|
$nextCloudVersionDependencies = []; |
|
324
|
|
|
if($nextCloudVersion->getMinimumVersion() !== '') { |
|
325
|
|
|
$nextCloudVersionDependencies['nextcloud']['@attributes']['min-version'] = $nextCloudVersion->getMinimumVersion(); |
|
326
|
|
|
} |
|
327
|
|
|
if($nextCloudVersion->getMaximumVersion() !== '') { |
|
328
|
|
|
$nextCloudVersionDependencies['nextcloud']['@attributes']['max-version'] = $nextCloudVersion->getMaximumVersion(); |
|
329
|
|
|
} |
|
330
|
|
|
$phpVersion = $versionParser->getVersion($app['releases'][0]['rawPhpVersionSpec']); |
|
331
|
|
|
$existsLocally = \OC_App::getAppPath($app['id']) !== false; |
|
|
|
|
|
|
332
|
|
|
$phpDependencies = []; |
|
333
|
|
|
if($phpVersion->getMinimumVersion() !== '') { |
|
334
|
|
|
$phpDependencies['php']['@attributes']['min-version'] = $phpVersion->getMinimumVersion(); |
|
335
|
|
|
} |
|
336
|
|
|
if($phpVersion->getMaximumVersion() !== '') { |
|
337
|
|
|
$phpDependencies['php']['@attributes']['max-version'] = $phpVersion->getMaximumVersion(); |
|
338
|
|
|
} |
|
339
|
|
|
if(isset($app['releases'][0]['minIntSize'])) { |
|
340
|
|
|
$phpDependencies['php']['@attributes']['min-int-size'] = $app['releases'][0]['minIntSize']; |
|
341
|
|
|
} |
|
342
|
|
|
$authors = ''; |
|
343
|
|
|
foreach($app['authors'] as $key => $author) { |
|
344
|
|
|
$authors .= $author['name']; |
|
345
|
|
|
if($key !== count($app['authors']) - 1) { |
|
346
|
|
|
$authors .= ', '; |
|
347
|
|
|
} |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
$currentLanguage = substr(\OC::$server->getL10NFactory()->findLanguage(), 0, 2); |
|
351
|
|
|
$enabledValue = $this->config->getAppValue($app['id'], 'enabled', 'no'); |
|
352
|
|
|
$groups = null; |
|
353
|
|
|
if($enabledValue !== 'no' && $enabledValue !== 'yes') { |
|
354
|
|
|
$groups = $enabledValue; |
|
355
|
|
|
} |
|
356
|
|
|
|
|
357
|
|
|
$currentVersion = ''; |
|
358
|
|
|
if($this->appManager->isInstalled($app['id'])) { |
|
359
|
|
|
$currentVersion = $this->appManager->getAppVersion($app['id']); |
|
360
|
|
|
} else { |
|
361
|
|
|
$currentLanguage = $app['releases'][0]['version']; |
|
362
|
|
|
} |
|
363
|
|
|
|
|
364
|
|
|
$formattedApps[] = [ |
|
365
|
|
|
'id' => $app['id'], |
|
366
|
|
|
'name' => isset($app['translations'][$currentLanguage]['name']) ? $app['translations'][$currentLanguage]['name'] : $app['translations']['en']['name'], |
|
367
|
|
|
'description' => isset($app['translations'][$currentLanguage]['description']) ? $app['translations'][$currentLanguage]['description'] : $app['translations']['en']['description'], |
|
368
|
|
|
'summary' => isset($app['translations'][$currentLanguage]['summary']) ? $app['translations'][$currentLanguage]['summary'] : $app['translations']['en']['summary'], |
|
369
|
|
|
'license' => $app['releases'][0]['licenses'], |
|
370
|
|
|
'author' => $authors, |
|
371
|
|
|
'shipped' => false, |
|
372
|
|
|
'version' => $currentVersion, |
|
373
|
|
|
'default_enable' => '', |
|
374
|
|
|
'types' => [], |
|
375
|
|
|
'documentation' => [ |
|
376
|
|
|
'admin' => $app['adminDocs'], |
|
377
|
|
|
'user' => $app['userDocs'], |
|
378
|
|
|
'developer' => $app['developerDocs'] |
|
379
|
|
|
], |
|
380
|
|
|
'website' => $app['website'], |
|
381
|
|
|
'bugs' => $app['issueTracker'], |
|
382
|
|
|
'detailpage' => $app['website'], |
|
383
|
|
|
'dependencies' => array_merge( |
|
384
|
|
|
$nextCloudVersionDependencies, |
|
385
|
|
|
$phpDependencies |
|
386
|
|
|
), |
|
387
|
|
|
'level' => ($app['isFeatured'] === true) ? 200 : 100, |
|
388
|
|
|
'missingMaxOwnCloudVersion' => false, |
|
389
|
|
|
'missingMinOwnCloudVersion' => false, |
|
390
|
|
|
'canInstall' => true, |
|
391
|
|
|
'screenshot' => isset($app['screenshots'][0]['url']) ? 'https://usercontent.apps.nextcloud.com/'.base64_encode($app['screenshots'][0]['url']) : '', |
|
392
|
|
|
'score' => $app['ratingOverall'], |
|
393
|
|
|
'ratingNumOverall' => $app['ratingNumOverall'], |
|
394
|
|
|
'ratingNumThresholdReached' => $app['ratingNumOverall'] > 5, |
|
395
|
|
|
'removable' => $existsLocally, |
|
396
|
|
|
'active' => $this->appManager->isEnabledForUser($app['id']), |
|
397
|
|
|
'needsDownload' => !$existsLocally, |
|
398
|
|
|
'groups' => $groups, |
|
399
|
|
|
'fromAppStore' => true, |
|
400
|
|
|
'appstoreData' => $app, |
|
401
|
|
|
]; |
|
402
|
|
|
} |
|
403
|
|
|
|
|
404
|
|
|
return $formattedApps; |
|
405
|
|
|
} |
|
406
|
|
|
|
|
407
|
|
|
/** |
|
408
|
|
|
* @PasswordConfirmationRequired |
|
409
|
|
|
* |
|
410
|
|
|
* @param string $appId |
|
411
|
|
|
* @param array $groups |
|
412
|
|
|
* @return JSONResponse |
|
413
|
|
|
*/ |
|
414
|
|
|
public function enableApp(string $appId, array $groups = []): JSONResponse { |
|
415
|
|
|
return $this->enableApps([$appId], $groups); |
|
416
|
|
|
} |
|
417
|
|
|
|
|
418
|
|
|
/** |
|
419
|
|
|
* Enable one or more apps |
|
420
|
|
|
* |
|
421
|
|
|
* apps will be enabled for specific groups only if $groups is defined |
|
422
|
|
|
* |
|
423
|
|
|
* @PasswordConfirmationRequired |
|
424
|
|
|
* @param array $appIds |
|
425
|
|
|
* @param array $groups |
|
426
|
|
|
* @return JSONResponse |
|
427
|
|
|
*/ |
|
428
|
|
|
public function enableApps(array $appIds, array $groups = []): JSONResponse { |
|
429
|
|
|
try { |
|
430
|
|
|
$updateRequired = false; |
|
431
|
|
|
|
|
432
|
|
|
foreach ($appIds as $appId) { |
|
433
|
|
|
$appId = OC_App::cleanAppId($appId); |
|
434
|
|
|
|
|
435
|
|
|
// Check if app is already downloaded |
|
436
|
|
|
/** @var Installer $installer */ |
|
437
|
|
|
$installer = \OC::$server->query(Installer::class); |
|
438
|
|
|
$isDownloaded = $installer->isDownloaded($appId); |
|
439
|
|
|
|
|
440
|
|
|
if(!$isDownloaded) { |
|
441
|
|
|
$installer->downloadApp($appId); |
|
442
|
|
|
} |
|
443
|
|
|
|
|
444
|
|
|
$installer->installApp($appId); |
|
445
|
|
|
|
|
446
|
|
|
if (count($groups) > 0) { |
|
447
|
|
|
$this->appManager->enableAppForGroups($appId, $this->getGroupList($groups)); |
|
448
|
|
|
} else { |
|
449
|
|
|
$this->appManager->enableApp($appId); |
|
450
|
|
|
} |
|
451
|
|
|
if (\OC_App::shouldUpgrade($appId)) { |
|
452
|
|
|
$updateRequired = true; |
|
453
|
|
|
} |
|
454
|
|
|
} |
|
455
|
|
|
return new JSONResponse(['data' => ['update_required' => $updateRequired]]); |
|
456
|
|
|
|
|
457
|
|
|
} catch (\Exception $e) { |
|
458
|
|
|
$this->logger->logException($e); |
|
459
|
|
|
return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR); |
|
460
|
|
|
} |
|
461
|
|
|
} |
|
462
|
|
|
|
|
463
|
|
|
private function getGroupList(array $groups) { |
|
464
|
|
|
$groupManager = \OC::$server->getGroupManager(); |
|
465
|
|
|
$groupsList = []; |
|
466
|
|
|
foreach ($groups as $group) { |
|
467
|
|
|
$groupItem = $groupManager->get($group); |
|
468
|
|
|
if ($groupItem instanceof \OCP\IGroup) { |
|
469
|
|
|
$groupsList[] = $groupManager->get($group); |
|
470
|
|
|
} |
|
471
|
|
|
} |
|
472
|
|
|
return $groupsList; |
|
473
|
|
|
} |
|
474
|
|
|
|
|
475
|
|
|
/** |
|
476
|
|
|
* @PasswordConfirmationRequired |
|
477
|
|
|
* |
|
478
|
|
|
* @param string $appId |
|
479
|
|
|
* @return JSONResponse |
|
480
|
|
|
*/ |
|
481
|
|
|
public function disableApp(string $appId): JSONResponse { |
|
482
|
|
|
return $this->disableApps([$appId]); |
|
483
|
|
|
} |
|
484
|
|
|
|
|
485
|
|
|
/** |
|
486
|
|
|
* @PasswordConfirmationRequired |
|
487
|
|
|
* |
|
488
|
|
|
* @param array $appIds |
|
489
|
|
|
* @return JSONResponse |
|
490
|
|
|
*/ |
|
491
|
|
|
public function disableApps(array $appIds): JSONResponse { |
|
492
|
|
|
try { |
|
493
|
|
|
foreach ($appIds as $appId) { |
|
494
|
|
|
$appId = OC_App::cleanAppId($appId); |
|
495
|
|
|
$this->appManager->disableApp($appId); |
|
496
|
|
|
} |
|
497
|
|
|
return new JSONResponse([]); |
|
498
|
|
|
} catch (\Exception $e) { |
|
499
|
|
|
$this->logger->logException($e); |
|
500
|
|
|
return new JSONResponse(['data' => ['message' => $e->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR); |
|
501
|
|
|
} |
|
502
|
|
|
} |
|
503
|
|
|
|
|
504
|
|
|
/** |
|
505
|
|
|
* @PasswordConfirmationRequired |
|
506
|
|
|
* |
|
507
|
|
|
* @param string $appId |
|
508
|
|
|
* @return JSONResponse |
|
509
|
|
|
*/ |
|
510
|
|
|
public function uninstallApp(string $appId): JSONResponse { |
|
511
|
|
|
$appId = OC_App::cleanAppId($appId); |
|
512
|
|
|
$result = $this->installer->removeApp($appId); |
|
513
|
|
|
if($result !== false) { |
|
514
|
|
|
$this->appManager->clearAppsCache(); |
|
515
|
|
|
return new JSONResponse(['data' => ['appid' => $appId]]); |
|
516
|
|
|
} |
|
517
|
|
|
return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t remove app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); |
|
518
|
|
|
} |
|
519
|
|
|
|
|
520
|
|
|
/** |
|
521
|
|
|
* @param string $appId |
|
522
|
|
|
* @return JSONResponse |
|
523
|
|
|
*/ |
|
524
|
|
|
public function updateApp(string $appId): JSONResponse { |
|
525
|
|
|
$appId = OC_App::cleanAppId($appId); |
|
526
|
|
|
|
|
527
|
|
|
$this->config->setSystemValue('maintenance', true); |
|
528
|
|
|
try { |
|
529
|
|
|
$result = $this->installer->updateAppstoreApp($appId); |
|
530
|
|
|
$this->config->setSystemValue('maintenance', false); |
|
531
|
|
|
} catch (\Exception $ex) { |
|
532
|
|
|
$this->config->setSystemValue('maintenance', false); |
|
533
|
|
|
return new JSONResponse(['data' => ['message' => $ex->getMessage()]], Http::STATUS_INTERNAL_SERVER_ERROR); |
|
534
|
|
|
} |
|
535
|
|
|
|
|
536
|
|
|
if ($result !== false) { |
|
537
|
|
|
return new JSONResponse(['data' => ['appid' => $appId]]); |
|
538
|
|
|
} |
|
539
|
|
|
return new JSONResponse(['data' => ['message' => $this->l10n->t('Couldn\'t update app.')]], Http::STATUS_INTERNAL_SERVER_ERROR); |
|
540
|
|
|
} |
|
541
|
|
|
|
|
542
|
|
|
private function sortApps($a, $b) { |
|
543
|
|
|
$a = (string)$a['name']; |
|
544
|
|
|
$b = (string)$b['name']; |
|
545
|
|
|
if ($a === $b) { |
|
546
|
|
|
return 0; |
|
547
|
|
|
} |
|
548
|
|
|
return ($a < $b) ? -1 : 1; |
|
549
|
|
|
} |
|
550
|
|
|
|
|
551
|
|
|
public function force(string $appId): JSONResponse { |
|
552
|
|
|
$appId = OC_App::cleanAppId($appId); |
|
553
|
|
|
|
|
554
|
|
|
$ignoreMaxApps = $this->config->getSystemValue('app_install_overwrite', []); |
|
555
|
|
|
if (!in_array($appId, $ignoreMaxApps, true)) { |
|
556
|
|
|
$ignoreMaxApps[] = $appId; |
|
557
|
|
|
$this->config->setSystemValue('app_install_overwrite', $ignoreMaxApps); |
|
558
|
|
|
} |
|
559
|
|
|
|
|
560
|
|
|
return new JSONResponse(); |
|
561
|
|
|
} |
|
562
|
|
|
|
|
563
|
|
|
} |
|
564
|
|
|
|
This function has been deprecated. The supplier of the function has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.