Passed
Push — master ( 97e6fe...de415f )
by Joas
16:06 queued 13s
created

ThemingDefaults::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 31
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 20
nc 1
nop 9
dl 0
loc 31
rs 9.6
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 Bjoern Schiessle <[email protected]>
4
 * @copyright Copyright (c) 2017 Lukas Reschke <[email protected]>
5
 *
6
 * @author Arthur Schiwon <[email protected]>
7
 * @author Bjoern Schiessle <[email protected]>
8
 * @author Christoph Wurst <[email protected]>
9
 * @author Daniel Kesselberg <[email protected]>
10
 * @author Guillaume COMPAGNON <[email protected]>
11
 * @author Jan-Christoph Borchardt <[email protected]>
12
 * @author Joachim Bauch <[email protected]>
13
 * @author Joas Schilling <[email protected]>
14
 * @author John Molakvoæ <[email protected]>
15
 * @author Julien Veyssier <[email protected]>
16
 * @author Julius Haertl <[email protected]>
17
 * @author Julius Härtl <[email protected]>
18
 * @author Lukas Reschke <[email protected]>
19
 * @author Michael Weimann <[email protected]>
20
 * @author Morris Jobke <[email protected]>
21
 * @author Patrik Kernstock <[email protected]>
22
 * @author Robin Appelman <[email protected]>
23
 * @author Roeland Jago Douma <[email protected]>
24
 *
25
 * @license GNU AGPL version 3 or any later version
26
 *
27
 * This program is free software: you can redistribute it and/or modify
28
 * it under the terms of the GNU Affero General Public License as
29
 * published by the Free Software Foundation, either version 3 of the
30
 * License, or (at your option) any later version.
31
 *
32
 * This program is distributed in the hope that it will be useful,
33
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
34
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35
 * GNU Affero General Public License for more details.
36
 *
37
 * You should have received a copy of the GNU Affero General Public License
38
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
39
 *
40
 */
41
namespace OCA\Theming;
42
43
use OCA\Theming\AppInfo\Application;
44
use OCA\Theming\Service\BackgroundService;
45
use OCP\App\AppPathNotFoundException;
46
use OCP\App\IAppManager;
47
use OCP\Files\NotFoundException;
48
use OCP\Files\SimpleFS\ISimpleFile;
49
use OCP\ICacheFactory;
50
use OCP\IConfig;
51
use OCP\IL10N;
52
use OCP\INavigationManager;
53
use OCP\IURLGenerator;
54
use OCP\IUserSession;
55
56
class ThemingDefaults extends \OC_Defaults {
57
58
	private IConfig $config;
59
	private IL10N $l;
60
	private ImageManager $imageManager;
61
	private IUserSession $userSession;
62
	private IURLGenerator $urlGenerator;
63
	private ICacheFactory $cacheFactory;
64
	private Util $util;
65
	private IAppManager $appManager;
66
	private INavigationManager $navigationManager;
67
68
	private string $name;
69
	private string $title;
70
	private string $entity;
71
	private string $productName;
72
	private string $url;
73
	private string $color;
74
75
	private string $iTunesAppId;
76
	private string $iOSClientUrl;
77
	private string $AndroidClientUrl;
78
	private string $FDroidClientUrl;
79
80
	/**
81
	 * ThemingDefaults constructor.
82
	 *
83
	 * @param IConfig $config
84
	 * @param IL10N $l
85
	 * @param ImageManager $imageManager
86
	 * @param IUserSession $userSession
87
	 * @param IURLGenerator $urlGenerator
88
	 * @param ICacheFactory $cacheFactory
89
	 * @param Util $util
90
	 * @param IAppManager $appManager
91
	 */
92
	public function __construct(IConfig $config,
93
								IL10N $l,
94
								IUserSession $userSession,
95
								IURLGenerator $urlGenerator,
96
								ICacheFactory $cacheFactory,
97
								Util $util,
98
								ImageManager $imageManager,
99
								IAppManager $appManager,
100
								INavigationManager $navigationManager
101
	) {
102
		parent::__construct();
103
		$this->config = $config;
104
		$this->l = $l;
105
		$this->imageManager = $imageManager;
106
		$this->userSession = $userSession;
107
		$this->urlGenerator = $urlGenerator;
108
		$this->cacheFactory = $cacheFactory;
109
		$this->util = $util;
110
		$this->appManager = $appManager;
111
		$this->navigationManager = $navigationManager;
112
113
		$this->name = parent::getName();
114
		$this->title = parent::getTitle();
115
		$this->entity = parent::getEntity();
116
		$this->productName = parent::getProductName();
117
		$this->url = parent::getBaseUrl();
118
		$this->color = parent::getColorPrimary();
119
		$this->iTunesAppId = parent::getiTunesAppId();
120
		$this->iOSClientUrl = parent::getiOSClientUrl();
121
		$this->AndroidClientUrl = parent::getAndroidClientUrl();
122
		$this->FDroidClientUrl = parent::getFDroidClientUrl();
123
	}
124
125
	public function getName() {
126
		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
127
	}
128
129
	public function getHTMLName() {
130
		return $this->config->getAppValue('theming', 'name', $this->name);
131
	}
132
133
	public function getTitle() {
134
		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
135
	}
136
137
	public function getEntity() {
138
		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
139
	}
140
141
	public function getProductName() {
142
		return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
143
	}
144
145
	public function getBaseUrl() {
146
		return $this->config->getAppValue('theming', 'url', $this->url);
147
	}
148
149
	/**
150
	 * We pass a string and sanitizeHTML will return a string too in that case
151
	 * @psalm-suppress InvalidReturnStatement
152
	 * @psalm-suppress InvalidReturnType
153
	 */
154
	public function getSlogan(?string $lang = null) {
155
		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
156
	}
157
158
	public function getImprintUrl() {
159
		return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
160
	}
161
162
	public function getPrivacyUrl() {
163
		return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
164
	}
165
166
	public function getShortFooter() {
167
		$slogan = $this->getSlogan();
168
		$baseUrl = $this->getBaseUrl();
169
		if ($baseUrl !== '') {
170
			$footer = '<a href="' . $baseUrl . '" target="_blank"' .
171
				' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
172
		} else {
173
			$footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
174
		}
175
		$footer .= ($slogan !== '' ? ' – ' . $slogan : '');
176
177
		$links = [
178
			[
179
				'text' => $this->l->t('Legal notice'),
180
				'url' => (string)$this->getImprintUrl()
181
			],
182
			[
183
				'text' => $this->l->t('Privacy policy'),
184
				'url' => (string)$this->getPrivacyUrl()
185
			],
186
		];
187
188
		$navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
189
		$guestNavigation = array_map(function ($nav) {
190
			return [
191
				'text' => $nav['name'],
192
				'url' => $nav['href']
193
			];
194
		}, $navigation);
195
		$links = array_merge($links, $guestNavigation);
196
197
		$legalLinks = '';
198
		$divider = '';
199
		foreach ($links as $link) {
200
			if ($link['url'] !== ''
201
				&& filter_var($link['url'], FILTER_VALIDATE_URL)
202
			) {
203
				$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
204
					' rel="noreferrer noopener">' . $link['text'] . '</a>';
205
				$divider = ' · ';
206
			}
207
		}
208
		if ($legalLinks !== '') {
209
			$footer .= '<br/>' . $legalLinks;
210
		}
211
212
		return $footer;
213
	}
214
215
	/**
216
	 * Color that is used for the header as well as for mail headers
217
	 */
218
	public function getColorPrimary(): string {
219
		$user = $this->userSession->getUser();
220
221
		// admin-defined primary color
222
		$defaultColor = $this->getDefaultColorPrimary();
223
224
		if ($this->isUserThemingDisabled()) {
225
			return $defaultColor;
226
		}
227
228
		// user-defined primary color
229
		if (!empty($user)) {
230
			$themingBackgroundColor = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'background_color', '');
231
			// If the user selected a specific colour
232
			if (preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $themingBackgroundColor)) {
233
				return $themingBackgroundColor;
234
			}
235
		}
236
237
		// If the default color is not valid, return the default background one
238
		if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $defaultColor)) {
239
			return BackgroundService::DEFAULT_COLOR;
240
		}
241
242
		// Finally, return the system global primary color
243
		return $defaultColor;
244
	}
245
246
	/**
247
	 * Return the default color primary
248
	 */
249
	public function getDefaultColorPrimary(): string {
250
		$color = $this->config->getAppValue(Application::APP_ID, 'color', '');
251
		if (!preg_match('/^\#([0-9a-f]{3}|[0-9a-f]{6})$/i', $color)) {
252
			$color = '#0082c9';
253
		}
254
		return $color;
255
	}
256
257
	/**
258
	 * Themed logo url
259
	 *
260
	 * @param bool $useSvg Whether to point to the SVG image or a fallback
261
	 * @return string
262
	 */
263
	public function getLogo($useSvg = true): string {
264
		$logo = $this->config->getAppValue('theming', 'logoMime', '');
265
266
		// short cut to avoid setting up the filesystem just to check if the logo is there
267
		//
268
		// explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
269
		// otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
270
		// needs to be called then)
271
		if ($useSvg === true && $logo !== false) {
272
			$logoExists = true;
273
		} else {
274
			try {
275
				$this->imageManager->getImage('logo', $useSvg);
276
				$logoExists = true;
277
			} catch (\Exception $e) {
278
				$logoExists = false;
279
			}
280
		}
281
282
		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
283
284
		if (!$logo || !$logoExists) {
285
			if ($useSvg) {
286
				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
287
			} else {
288
				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
289
			}
290
			return $logo . '?v=' . $cacheBusterCounter;
291
		}
292
293
		return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
294
	}
295
296
	/**
297
	 * Themed background image url
298
	 *
299
	 * @return string
300
	 */
301
	public function getBackground(): string {
302
		return $this->imageManager->getImageUrl('background');
303
	}
304
305
	/**
306
	 * @return string
307
	 */
308
	public function getiTunesAppId() {
309
		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
310
	}
311
312
	/**
313
	 * @return string
314
	 */
315
	public function getiOSClientUrl() {
316
		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
317
	}
318
319
	/**
320
	 * @return string
321
	 */
322
	public function getAndroidClientUrl() {
323
		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
324
	}
325
326
	/**
327
	 * @return string
328
	 */
329
	public function getFDroidClientUrl() {
330
		return $this->config->getAppValue('theming', 'FDroidClientUrl', $this->FDroidClientUrl);
331
	}
332
333
	/**
334
	 * @return array scss variables to overwrite
335
	 */
336
	public function getScssVariables() {
337
		$cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
338
		$cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
339
		if ($value = $cache->get('getScssVariables')) {
340
			return $value;
341
		}
342
343
		$variables = [
344
			'theming-cachebuster' => "'" . $cacheBuster . "'",
345
			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
346
			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
347
			'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
348
			'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
349
		];
350
351
		$variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
352
		$variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
353
		$variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
354
		$variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
355
		$variables['image-login-plain'] = 'false';
356
357
		if ($this->config->getAppValue('theming', 'color', '') !== '') {
358
			$variables['color-primary'] = $this->getColorPrimary();
359
			$variables['color-primary-text'] = $this->getTextColorPrimary();
360
			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
361
		}
362
363
		if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
364
			$variables['image-login-plain'] = 'true';
365
		}
366
367
		$variables['has-legal-links'] = 'false';
368
		if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
369
			$variables['has-legal-links'] = 'true';
370
		}
371
372
		$cache->set('getScssVariables', $variables);
373
		return $variables;
374
	}
375
376
	/**
377
	 * Check if the image should be replaced by the theming app
378
	 * and return the new image location then
379
	 *
380
	 * @param string $app name of the app
381
	 * @param string $image filename of the image
382
	 * @return bool|string false if image should not replaced, otherwise the location of the image
383
	 */
384
	public function replaceImagePath($app, $image) {
385
		if ($app === '' || $app === 'files_sharing') {
386
			$app = 'core';
387
		}
388
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
0 ignored issues
show
Unused Code introduced by
The assignment to $cacheBusterValue is dead and can be removed.
Loading history...
389
390
		$route = false;
391
		if ($image === 'favicon.ico' && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
392
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
393
		}
394
		if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($this->imageManager->shouldReplaceIcons() || $this->getCustomFavicon() !== null)) {
395
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
396
		}
397
		if ($image === 'manifest.json') {
398
			try {
399
				$appPath = $this->appManager->getAppPath($app);
400
				if (file_exists($appPath . '/img/manifest.json')) {
401
					return false;
402
				}
403
			} catch (AppPathNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
404
			}
405
			$route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest', ['app' => $app ]);
406
		}
407
		if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
408
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
409
		}
410
411
		if ($route) {
412
			return $route . '?v=' . $this->util->getCacheBuster();
413
		}
414
415
		return false;
416
	}
417
418
	protected function getCustomFavicon(): ?ISimpleFile {
419
		try {
420
			return $this->imageManager->getImage('favicon');
421
		} catch (NotFoundException $e) {
422
			return null;
423
		}
424
	}
425
426
	/**
427
	 * Increases the cache buster key
428
	 */
429
	public function increaseCacheBuster(): void {
430
		$cacheBusterKey = (int)$this->config->getAppValue('theming', 'cachebuster', '0');
431
		$this->config->setAppValue('theming', 'cachebuster', (string)($cacheBusterKey + 1));
432
		$this->cacheFactory->createDistributed('theming-')->clear();
433
		$this->cacheFactory->createDistributed('imagePath')->clear();
434
	}
435
436
	/**
437
	 * Update setting in the database
438
	 *
439
	 * @param string $setting
440
	 * @param string $value
441
	 */
442
	public function set($setting, $value): void {
443
		$this->config->setAppValue('theming', $setting, $value);
444
		$this->increaseCacheBuster();
445
	}
446
447
	/**
448
	 * Revert all settings to the default value
449
	 */
450
	public function undoAll(): void {
451
		$this->config->deleteAppValues('theming');
452
		$this->increaseCacheBuster();
453
	}
454
455
	/**
456
	 * Revert settings to the default value
457
	 *
458
	 * @param string $setting setting which should be reverted
459
	 * @return string default value
460
	 */
461
	public function undo($setting): string {
462
		$this->config->deleteAppValue('theming', $setting);
463
		$this->increaseCacheBuster();
464
465
		$returnValue = '';
466
		switch ($setting) {
467
			case 'name':
468
				$returnValue = $this->getEntity();
469
				break;
470
			case 'url':
471
				$returnValue = $this->getBaseUrl();
472
				break;
473
			case 'slogan':
474
				$returnValue = $this->getSlogan();
475
				break;
476
			case 'color':
477
				$returnValue = $this->getDefaultColorPrimary();
478
				break;
479
			case 'logo':
480
			case 'logoheader':
481
			case 'background':
482
			case 'favicon':
483
				$this->imageManager->delete($setting);
484
				break;
485
		}
486
487
		return $returnValue;
488
	}
489
490
	/**
491
	 * Color of text in the header and primary buttons
492
	 *
493
	 * @return string
494
	 */
495
	public function getTextColorPrimary() {
496
		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
497
	}
498
499
	/**
500
	 * Color of text in the header and primary buttons
501
	 *
502
	 * @return string
503
	 */
504
	public function getDefaultTextColorPrimary() {
505
		return $this->util->invertTextColor($this->getDefaultColorPrimary()) ? '#000000' : '#ffffff';
506
	}
507
508
	/**
509
	 * Has the admin disabled user customization
510
	 */
511
	public function isUserThemingDisabled(): bool {
512
		return $this->config->getAppValue('theming', 'disable-user-theming', 'no') === 'yes';
513
	}
514
}
515