Passed
Push — master ( 51add7...7917f4 )
by Julius
13:12 queued 12s
created

ThemingDefaults::getProductName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
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 OCP\App\AppPathNotFoundException;
44
use OCP\App\IAppManager;
45
use OCP\Files\NotFoundException;
46
use OCP\ICacheFactory;
47
use OCP\IConfig;
48
use OCP\IL10N;
49
use OCP\INavigationManager;
50
use OCP\IURLGenerator;
51
52
class ThemingDefaults extends \OC_Defaults {
53
54
	/** @var IConfig */
55
	private $config;
56
	/** @var IL10N */
57
	private $l;
58
	/** @var ImageManager */
59
	private $imageManager;
60
	/** @var IURLGenerator */
61
	private $urlGenerator;
62
	/** @var ICacheFactory */
63
	private $cacheFactory;
64
	/** @var Util */
65
	private $util;
66
	/** @var IAppManager */
67
	private $appManager;
68
	/** @var INavigationManager */
69
	private $navigationManager;
70
71
	/** @var string */
72
	private $name;
73
	/** @var string */
74
	private $title;
75
	/** @var string */
76
	private $entity;
77
	/** @var string */
78
	private $productName;
79
	/** @var string */
80
	private $url;
81
	/** @var string */
82
	private $color;
83
84
	/** @var string */
85
	private $iTunesAppId;
86
	/** @var string */
87
	private $iOSClientUrl;
88
	/** @var string */
89
	private $AndroidClientUrl;
90
91
	/**
92
	 * ThemingDefaults constructor.
93
	 *
94
	 * @param IConfig $config
95
	 * @param IL10N $l
96
	 * @param ImageManager $imageManager
97
	 * @param IURLGenerator $urlGenerator
98
	 * @param ICacheFactory $cacheFactory
99
	 * @param Util $util
100
	 * @param IAppManager $appManager
101
	 */
102
	public function __construct(IConfig $config,
103
								IL10N $l,
104
								IURLGenerator $urlGenerator,
105
								ICacheFactory $cacheFactory,
106
								Util $util,
107
								ImageManager $imageManager,
108
								IAppManager $appManager,
109
								INavigationManager $navigationManager
110
	) {
111
		parent::__construct();
112
		$this->config = $config;
113
		$this->l = $l;
114
		$this->imageManager = $imageManager;
115
		$this->urlGenerator = $urlGenerator;
116
		$this->cacheFactory = $cacheFactory;
117
		$this->util = $util;
118
		$this->appManager = $appManager;
119
		$this->navigationManager = $navigationManager;
120
121
		$this->name = parent::getName();
122
		$this->title = parent::getTitle();
123
		$this->entity = parent::getEntity();
124
		$this->productName = parent::getName();
125
		$this->url = parent::getBaseUrl();
126
		$this->color = parent::getColorPrimary();
127
		$this->iTunesAppId = parent::getiTunesAppId();
128
		$this->iOSClientUrl = parent::getiOSClientUrl();
129
		$this->AndroidClientUrl = parent::getAndroidClientUrl();
130
	}
131
132
	public function getName() {
133
		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
134
	}
135
136
	public function getHTMLName() {
137
		return $this->config->getAppValue('theming', 'name', $this->name);
138
	}
139
140
	public function getTitle() {
141
		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
142
	}
143
144
	public function getEntity() {
145
		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
146
	}
147
148
	public function getProductName() {
149
		return strip_tags($this->config->getAppValue('theming', 'productName', $this->productName));
150
	}
151
152
	public function getBaseUrl() {
153
		return $this->config->getAppValue('theming', 'url', $this->url);
154
	}
155
156
	public function getSlogan(?string $lang = null) {
157
		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
158
	}
159
160
	public function getImprintUrl() {
161
		return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
162
	}
163
164
	public function getPrivacyUrl() {
165
		return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
166
	}
167
168
	public function getShortFooter() {
169
		$slogan = $this->getSlogan();
170
		$baseUrl = $this->getBaseUrl();
171
		if ($baseUrl !== '') {
172
			$footer = '<a href="' . $baseUrl . '" target="_blank"' .
173
				' rel="noreferrer noopener" class="entity-name">' . $this->getEntity() . '</a>';
174
		} else {
175
			$footer = '<span class="entity-name">' .$this->getEntity() . '</span>';
176
		}
177
		$footer .= ($slogan !== '' ? ' – ' . $slogan : '');
178
179
		$links = [
180
			[
181
				'text' => $this->l->t('Legal notice'),
182
				'url' => (string)$this->getImprintUrl()
183
			],
184
			[
185
				'text' => $this->l->t('Privacy policy'),
186
				'url' => (string)$this->getPrivacyUrl()
187
			],
188
		];
189
190
		$navigation = $this->navigationManager->getAll(INavigationManager::TYPE_GUEST);
191
		$guestNavigation = array_map(function ($nav) {
192
			return [
193
				'text' => $nav['name'],
194
				'url' => $nav['href']
195
			];
196
		}, $navigation);
197
		$links = array_merge($links, $guestNavigation);
198
199
		$legalLinks = '';
200
		$divider = '';
201
		foreach ($links as $link) {
202
			if ($link['url'] !== ''
203
				&& filter_var($link['url'], FILTER_VALIDATE_URL)
204
			) {
205
				$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
206
					' rel="noreferrer noopener">' . $link['text'] . '</a>';
207
				$divider = ' · ';
208
			}
209
		}
210
		if ($legalLinks !== '') {
211
			$footer .= '<br/>' . $legalLinks;
212
		}
213
214
		return $footer;
215
	}
216
217
	/**
218
	 * Color that is used for the header as well as for mail headers
219
	 *
220
	 * @return string
221
	 */
222
	public function getColorPrimary() {
223
		return $this->config->getAppValue('theming', 'color', $this->color);
224
	}
225
226
	/**
227
	 * Themed logo url
228
	 *
229
	 * @param bool $useSvg Whether to point to the SVG image or a fallback
230
	 * @return string
231
	 */
232
	public function getLogo($useSvg = true): string {
233
		$logo = $this->config->getAppValue('theming', 'logoMime', '');
234
235
		// short cut to avoid setting up the filesystem just to check if the logo is there
236
		//
237
		// explanation: if an SVG is requested and the app config value for logoMime is set then the logo is there.
238
		// otherwise we need to check it and maybe also generate a PNG from the SVG (that's done in getImage() which
239
		// needs to be called then)
240
		if ($useSvg === true && $logo !== false) {
241
			$logoExists = true;
242
		} else {
243
			try {
244
				$this->imageManager->getImage('logo', $useSvg);
245
				$logoExists = true;
246
			} catch (\Exception $e) {
247
				$logoExists = false;
248
			}
249
		}
250
251
		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
252
253
		if (!$logo || !$logoExists) {
254
			if ($useSvg) {
255
				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.svg');
256
			} else {
257
				$logo = $this->urlGenerator->imagePath('core', 'logo/logo.png');
258
			}
259
			return $logo . '?v=' . $cacheBusterCounter;
260
		}
261
262
		return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo', 'useSvg' => $useSvg, 'v' => $cacheBusterCounter ]);
263
	}
264
265
	/**
266
	 * Themed background image url
267
	 *
268
	 * @return string
269
	 */
270
	public function getBackground(): string {
271
		return $this->imageManager->getImageUrl('background');
272
	}
273
274
	/**
275
	 * @return string
276
	 */
277
	public function getiTunesAppId() {
278
		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
279
	}
280
281
	/**
282
	 * @return string
283
	 */
284
	public function getiOSClientUrl() {
285
		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
286
	}
287
288
	/**
289
	 * @return string
290
	 */
291
	public function getAndroidClientUrl() {
292
		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
293
	}
294
295
296
	/**
297
	 * @return array scss variables to overwrite
298
	 */
299
	public function getScssVariables() {
300
		$cacheBuster = $this->config->getAppValue('theming', 'cachebuster', '0');
301
		$cache = $this->cacheFactory->createDistributed('theming-' . $cacheBuster . '-' . $this->urlGenerator->getBaseUrl());
302
		if ($value = $cache->get('getScssVariables')) {
303
			return $value;
304
		}
305
306
		$variables = [
307
			'theming-cachebuster' => "'" . $cacheBuster . "'",
308
			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
309
			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
310
			'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
311
			'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
312
		];
313
314
		$variables['image-logo'] = "url('".$this->imageManager->getImageUrl('logo')."')";
315
		$variables['image-logoheader'] = "url('".$this->imageManager->getImageUrl('logoheader')."')";
316
		$variables['image-favicon'] = "url('".$this->imageManager->getImageUrl('favicon')."')";
317
		$variables['image-login-background'] = "url('".$this->imageManager->getImageUrl('background')."')";
318
		$variables['image-login-plain'] = 'false';
319
320
		if ($this->config->getAppValue('theming', 'color', '') !== '') {
321
			$variables['color-primary'] = $this->getColorPrimary();
322
			$variables['color-primary-text'] = $this->getTextColorPrimary();
323
			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
324
		}
325
326
		if ($this->config->getAppValue('theming', 'backgroundMime', '') === 'backgroundColor') {
327
			$variables['image-login-plain'] = 'true';
328
		}
329
330
		$variables['has-legal-links'] = 'false';
331
		if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
332
			$variables['has-legal-links'] = 'true';
333
		}
334
335
		$cache->set('getScssVariables', $variables);
336
		return $variables;
337
	}
338
339
	/**
340
	 * Check if the image should be replaced by the theming app
341
	 * and return the new image location then
342
	 *
343
	 * @param string $app name of the app
344
	 * @param string $image filename of the image
345
	 * @return bool|string false if image should not replaced, otherwise the location of the image
346
	 */
347
	public function replaceImagePath($app, $image) {
348
		if ($app === '' || $app === 'files_sharing') {
349
			$app = 'core';
350
		}
351
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
352
353
		try {
354
			$customFavicon = $this->imageManager->getImage('favicon');
355
		} catch (NotFoundException $e) {
356
			$customFavicon = null;
357
		}
358
359
		$route = false;
360
		if ($image === 'favicon.ico' && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
361
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]);
362
		}
363
		if (($image === 'favicon-touch.png' || $image === 'favicon-fb.png') && ($customFavicon !== null || $this->imageManager->shouldReplaceIcons())) {
364
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]);
365
		}
366
		if ($image === 'manifest.json') {
367
			try {
368
				$appPath = $this->appManager->getAppPath($app);
369
				if (file_exists($appPath . '/img/manifest.json')) {
370
					return false;
371
				}
372
			} catch (AppPathNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
373
			}
374
			$route = $this->urlGenerator->linkToRoute('theming.Theming.getManifest');
375
		}
376
		if (strpos($image, 'filetypes/') === 0 && file_exists(\OC::$SERVERROOT . '/core/img/' . $image)) {
377
			$route = $this->urlGenerator->linkToRoute('theming.Icon.getThemedIcon', ['app' => $app, 'image' => $image]);
378
		}
379
380
		if ($route) {
381
			return $route . '?v=' . $cacheBusterValue;
382
		}
383
384
		return false;
385
	}
386
387
	/**
388
	 * Increases the cache buster key
389
	 */
390
	private function increaseCacheBuster() {
391
		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
392
		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey + 1);
393
		$this->cacheFactory->createDistributed('theming-')->clear();
394
		$this->cacheFactory->createDistributed('imagePath')->clear();
395
	}
396
397
	/**
398
	 * Update setting in the database
399
	 *
400
	 * @param string $setting
401
	 * @param string $value
402
	 */
403
	public function set($setting, $value) {
404
		$this->config->setAppValue('theming', $setting, $value);
405
		$this->increaseCacheBuster();
406
	}
407
408
	/**
409
	 * Revert settings to the default value
410
	 *
411
	 * @param string $setting setting which should be reverted
412
	 * @return string default value
413
	 */
414
	public function undo($setting) {
415
		$this->config->deleteAppValue('theming', $setting);
416
		$this->increaseCacheBuster();
417
418
		$returnValue = '';
419
		switch ($setting) {
420
			case 'name':
421
				$returnValue = $this->getEntity();
422
				break;
423
			case 'url':
424
				$returnValue = $this->getBaseUrl();
425
				break;
426
			case 'slogan':
427
				$returnValue = $this->getSlogan();
428
				break;
429
			case 'color':
430
				$returnValue = $this->getColorPrimary();
431
				break;
432
			case 'logo':
433
			case 'logoheader':
434
			case 'background':
435
			case 'favicon':
436
				$this->imageManager->delete($setting);
437
				break;
438
		}
439
440
		return $returnValue;
441
	}
442
443
	/**
444
	 * Color of text in the header and primary buttons
445
	 *
446
	 * @return string
447
	 */
448
	public function getTextColorPrimary() {
449
		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
450
	}
451
}
452