Passed
Push — master ( 96e892...5b0e70 )
by Roeland
13:09
created

Manager::getSections()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 20
nc 12
nop 1
dl 0
loc 36
rs 8.6666
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Arthur Schiwon <[email protected]>
4
 *
5
 * @author Arthur Schiwon <[email protected]>
6
 * @author Joas Schilling <[email protected]>
7
 * @author Lukas Reschke <[email protected]>
8
 * @author Marius Blüm <[email protected]>
9
 * @author Morris Jobke <[email protected]>
10
 * @author Robin Appelman <[email protected]>
11
 * @author Roeland Jago Douma <[email protected]>
12
 *
13
 * @license GNU AGPL version 3 or any later version
14
 *
15
 * This program is free software: you can redistribute it and/or modify
16
 * it under the terms of the GNU Affero General Public License as
17
 * published by the Free Software Foundation, either version 3 of the
18
 * License, or (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU Affero General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Affero General Public License
26
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
27
 *
28
 */
29
30
namespace OC\Settings;
31
32
use Closure;
33
use OCP\AppFramework\QueryException;
34
use OCP\IL10N;
35
use OCP\ILogger;
36
use OCP\IServerContainer;
37
use OCP\IURLGenerator;
38
use OCP\L10N\IFactory;
39
use OCP\Settings\ISettings;
40
use OCP\Settings\IManager;
41
use OCP\Settings\ISection;
42
use OCP\Settings\ISubAdminSettings;
43
44
class Manager implements IManager {
45
46
	/** @var ILogger */
47
	private $log;
48
49
	/** @var IL10N */
50
	private $l;
51
52
	/** @var IFactory */
53
	private $l10nFactory;
54
55
	/** @var IURLGenerator */
56
	private $url;
57
58
	/** @var IServerContainer */
59
	private $container;
60
61
	public function __construct(
62
		ILogger $log,
63
		IFactory $l10nFactory,
64
		IURLGenerator $url,
65
		IServerContainer $container
66
	) {
67
		$this->log = $log;
68
		$this->l10nFactory = $l10nFactory;
69
		$this->url = $url;
70
		$this->container = $container;
71
	}
72
73
	/** @var array */
74
	protected $sectionClasses = [];
75
76
	/** @var array */
77
	protected $sections = [];
78
79
	/**
80
	 * @param string $type 'admin' or 'personal'
81
	 * @param string $section Class must implement OCP\Settings\ISection
82
	 *
83
	 * @return void
84
	 */
85
	public function registerSection(string $type, string $section) {
86
		if (!isset($this->sectionClasses[$type])) {
87
			$this->sectionClasses[$type] = [];
88
		}
89
90
		$this->sectionClasses[$type][] = $section;
91
	}
92
93
	/**
94
	 * @param string $type 'admin' or 'personal'
95
	 *
96
	 * @return ISection[]
97
	 */
98
	protected function getSections(string $type): array {
99
		if (!isset($this->sections[$type])) {
100
			$this->sections[$type] = [];
101
		}
102
103
		if (!isset($this->sectionClasses[$type])) {
104
			return $this->sections[$type];
105
		}
106
107
		foreach ($this->sectionClasses[$type] as $index => $class) {
108
			try {
109
				/** @var ISection $section */
110
				$section = \OC::$server->query($class);
111
			} catch (QueryException $e) {
112
				$this->log->logException($e, ['level' => ILogger::INFO]);
113
				continue;
114
			}
115
116
			if (!$section instanceof ISection) {
117
				$this->log->logException(new \InvalidArgumentException('Invalid settings section registered'), ['level' => ILogger::INFO]);
118
				continue;
119
			}
120
121
			$sectionID = $section->getID();
122
123
			if (isset($this->sections[$type][$sectionID])) {
124
				$this->log->logException(new \InvalidArgumentException('Section with the same ID already registered'), ['level' => ILogger::INFO]);
125
				continue;
126
			}
127
128
			$this->sections[$type][$sectionID] = $section;
129
130
			unset($this->sectionClasses[$type][$index]);
131
		}
132
133
		return $this->sections[$type];
134
	}
135
136
	/** @var array */
137
	protected $settingClasses = [];
138
139
	/** @var array */
140
	protected $settings = [];
141
142
	/**
143
	 * @param string $type 'admin' or 'personal'
144
	 * @param string $setting Class must implement OCP\Settings\ISetting
145
	 *
146
	 * @return void
147
	 */
148
	public function registerSetting(string $type, string $setting) {
149
		$this->settingClasses[$setting] = $type;
150
	}
151
152
	/**
153
	 * @param string $type 'admin' or 'personal'
154
	 * @param string $section
155
	 * @param Closure $filter optional filter to apply on all loaded ISettings
156
	 *
157
	 * @return ISettings[]
158
	 */
159
	protected function getSettings(string $type, string $section, Closure $filter = null): array {
160
		if (!isset($this->settings[$type])) {
161
			$this->settings[$type] = [];
162
		}
163
		if (!isset($this->settings[$type][$section])) {
164
			$this->settings[$type][$section] = [];
165
		}
166
167
		foreach ($this->settingClasses as $class => $settingsType) {
168
			if ($type !== $settingsType) {
169
				continue;
170
			}
171
172
			try {
173
				/** @var ISettings $setting */
174
				$setting = \OC::$server->query($class);
175
			} catch (QueryException $e) {
176
				$this->log->logException($e, ['level' => ILogger::INFO]);
177
				continue;
178
			}
179
180
			if (!$setting instanceof ISettings) {
181
				$this->log->logException(new \InvalidArgumentException('Invalid settings setting registered (' . $class . ')'), ['level' => ILogger::INFO]);
182
				continue;
183
			}
184
185
			if ($filter !== null && !$filter($setting)) {
186
				continue;
187
			}
188
			if ($setting->getSection() === null) {
189
				continue;
190
			}
191
192
			if (!isset($this->settings[$settingsType][$setting->getSection()])) {
193
				$this->settings[$settingsType][$setting->getSection()] = [];
194
			}
195
			$this->settings[$settingsType][$setting->getSection()][] = $setting;
196
197
			unset($this->settingClasses[$class]);
198
		}
199
200
		return $this->settings[$type][$section];
201
	}
202
203
	/**
204
	 * @inheritdoc
205
	 */
206
	public function getAdminSections(): array {
207
		if ($this->l === null) {
208
			$this->l = $this->l10nFactory->get('lib');
209
		}
210
211
		// built-in sections
212
		$sections = [
213
			0 => [new Section('overview', $this->l->t('Overview'), 0, $this->url->imagePath('settings', 'admin.svg'))],
214
			1 => [new Section('server', $this->l->t('Basic settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
215
			5 => [new Section('sharing', $this->l->t('Sharing'), 0, $this->url->imagePath('core', 'actions/share.svg'))],
216
			10 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('core', 'actions/password.svg'))],
217
			50 => [new Section('groupware', $this->l->t('Groupware'), 0, $this->url->imagePath('core', 'places/contacts.svg'))],
218
			98 => [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))],
219
		];
220
221
		$appSections = $this->getSections('admin');
222
223
		foreach ($appSections as $section) {
224
			/** @var ISection $section */
225
			if (!isset($sections[$section->getPriority()])) {
226
				$sections[$section->getPriority()] = [];
227
			}
228
229
			$sections[$section->getPriority()][] = $section;
230
		}
231
232
		ksort($sections);
233
234
		return $sections;
235
	}
236
237
	/**
238
	 * @param string $section
239
	 * @param Closure $filter
240
	 *
241
	 * @return ISection[]
242
	 */
243
	private function getBuiltInAdminSettings($section, Closure $filter = null): array {
244
		$forms = [];
245
246
		if ($section === 'overview') {
247
			/** @var ISettings $form */
248
			$form = $this->container->query(Admin\Overview::class);
249
			if ($filter === null || $filter($form)) {
250
				$forms[$form->getPriority()] = [$form];
251
			}
252
		}
253
		if ($section === 'server') {
254
			/** @var ISettings $form */
255
			$form = $this->container->query(Admin\Server::class);
256
			if ($filter === null || $filter($form)) {
257
				$forms[$form->getPriority()] = [$form];
258
			}
259
			$form = $this->container->query(Admin\Mail::class);
260
			if ($filter === null || $filter($form)) {
261
				$forms[$form->getPriority()] = [$form];
262
			}
263
		}
264
		if ($section === 'security') {
265
			/** @var ISettings $form */
266
			$form = $this->container->query(Admin\Security::class);
267
			if ($filter === null || $filter($form)) {
268
				$forms[$form->getPriority()] = [$form];
269
			}
270
		}
271
		if ($section === 'sharing') {
272
			/** @var ISettings $form */
273
			$form = $this->container->query(Admin\Sharing::class);
274
			if ($filter === null || $filter($form)) {
275
				$forms[$form->getPriority()] = [$form];
276
			}
277
		}
278
279
		return $forms;
280
	}
281
282
	/**
283
	 * @param string $section
284
	 *
285
	 * @return ISection[]
286
	 */
287
	private function getBuiltInPersonalSettings($section): array {
288
		$forms = [];
289
290
		if ($section === 'personal-info') {
291
			/** @var ISettings $form */
292
			$form = $this->container->query(Personal\PersonalInfo::class);
293
			$forms[$form->getPriority()] = [$form];
294
			$form = new Personal\ServerDevNotice();
295
			$forms[$form->getPriority()] = [$form];
296
		}
297
		if ($section === 'security') {
298
			/** @var ISettings $form */
299
			$form = $this->container->query(Personal\Security::class);
300
			$forms[$form->getPriority()] = [$form];
301
		}
302
		if ($section === 'additional') {
303
			/** @var ISettings $form */
304
			$form = $this->container->query(Personal\Additional::class);
305
			$forms[$form->getPriority()] = [$form];
306
		}
307
308
		return $forms;
309
	}
310
311
	/**
312
	 * @inheritdoc
313
	 */
314
	public function getAdminSettings($section, bool $subAdminOnly = false): array {
315
		if ($subAdminOnly) {
316
			$subAdminSettingsFilter = function(ISettings $settings) {
317
				return $settings instanceof ISubAdminSettings;
318
			};
319
			$settings = $this->getBuiltInAdminSettings($section, $subAdminSettingsFilter);
320
			$appSettings = $this->getSettings('admin', $section, $subAdminSettingsFilter);
321
		} else {
322
			$settings = $this->getBuiltInAdminSettings($section);
323
			$appSettings = $this->getSettings('admin', $section);
324
		}
325
326
		foreach ($appSettings as $setting) {
327
			if (!isset($settings[$setting->getPriority()])) {
328
				$settings[$setting->getPriority()] = [];
329
			}
330
			$settings[$setting->getPriority()][] = $setting;
331
		}
332
333
		ksort($settings);
334
		return $settings;
335
	}
336
337
	/**
338
	 * @inheritdoc
339
	 */
340
	public function getPersonalSections(): array {
341
		if ($this->l === null) {
342
			$this->l = $this->l10nFactory->get('lib');
343
		}
344
345
		$sections = [
346
			0 => [new Section('personal-info', $this->l->t('Personal info'), 0, $this->url->imagePath('core', 'actions/info.svg'))],
347
			5 => [new Section('security', $this->l->t('Security'), 0, $this->url->imagePath('settings', 'password.svg'))],
348
			15 => [new Section('sync-clients', $this->l->t('Mobile & desktop'), 0, $this->url->imagePath('core', 'clients/phone.svg'))],
349
		];
350
351
		$legacyForms = \OC_App::getForms('personal');
352
		if (!empty($legacyForms) && $this->hasLegacyPersonalSettingsToRender($legacyForms)) {
353
			$sections[98] = [new Section('additional', $this->l->t('Additional settings'), 0, $this->url->imagePath('core', 'actions/settings-dark.svg'))];
354
		}
355
356
		$appSections = $this->getSections('personal');
357
358
		foreach ($appSections as $section) {
359
			/** @var ISection $section */
360
			if (!isset($sections[$section->getPriority()])) {
361
				$sections[$section->getPriority()] = [];
362
			}
363
364
			$sections[$section->getPriority()][] = $section;
365
		}
366
367
		ksort($sections);
368
369
		return $sections;
370
	}
371
372
	/**
373
	 * @param string[] $forms
374
	 *
375
	 * @return bool
376
	 */
377
	private function hasLegacyPersonalSettingsToRender(array $forms): bool {
378
		foreach ($forms as $form) {
379
			if (trim($form) !== '') {
380
				return true;
381
			}
382
		}
383
		return false;
384
	}
385
386
	/**
387
	 * @inheritdoc
388
	 */
389
	public function getPersonalSettings($section): array {
390
		$settings = $this->getBuiltInPersonalSettings($section);
391
		$appSettings = $this->getSettings('personal', $section);
392
393
		foreach ($appSettings as $setting) {
394
			if (!isset($settings[$setting->getPriority()])) {
395
				$settings[$setting->getPriority()] = [];
396
			}
397
			$settings[$setting->getPriority()][] = $setting;
398
		}
399
400
		ksort($settings);
401
		return $settings;
402
	}
403
}
404