Completed
Push — master ( 60734c...d4a0af )
by Morris
20:02
created

ThemingDefaults::replaceImagePath()   C

Complexity

Conditions 12
Paths 28

Size

Total Lines 29
Code Lines 20

Duplication

Lines 6
Ratio 20.69 %

Importance

Changes 0
Metric Value
cc 12
eloc 20
nc 28
nop 2
dl 6
loc 29
rs 5.1612
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Jan-Christoph Borchardt <[email protected]>
9
 * @author Joachim Bauch <[email protected]>
10
 * @author Joas Schilling <[email protected]>
11
 * @author Julius Haertl <[email protected]>
12
 * @author Julius Härtl <[email protected]>
13
 * @author Lukas Reschke <[email protected]>
14
 * @author Morris Jobke <[email protected]>
15
 * @author Roeland Jago Douma <[email protected]>
16
 *
17
 * @license GNU AGPL version 3 or any later version
18
 *
19
 * This program is free software: you can redistribute it and/or modify
20
 * it under the terms of the GNU Affero General Public License as
21
 * published by the Free Software Foundation, either version 3 of the
22
 * License, or (at your option) any later version.
23
 *
24
 * This program is distributed in the hope that it will be useful,
25
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 * GNU Affero General Public License for more details.
28
 *
29
 * You should have received a copy of the GNU Affero General Public License
30
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
31
 *
32
 */
33
34
namespace OCA\Theming;
35
36
37
use OCP\App\AppPathNotFoundException;
38
use OCP\App\IAppManager;
39
use OCP\Files\NotFoundException;
40
use OCP\ICacheFactory;
41
use OCP\IConfig;
42
use OCP\IL10N;
43
use OCP\IURLGenerator;
44
45
class ThemingDefaults extends \OC_Defaults {
46
47
	/** @var IConfig */
48
	private $config;
49
	/** @var IL10N */
50
	private $l;
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
51
	/** @var ImageManager */
52
	private $imageManager;
53
	/** @var IURLGenerator */
54
	private $urlGenerator;
55
	/** @var ICacheFactory */
56
	private $cacheFactory;
57
	/** @var Util */
58
	private $util;
59
	/** @var IAppManager */
60
	private $appManager;
61
	/** @var string */
62
	private $name;
63
	/** @var string */
64
	private $title;
65
	/** @var string */
66
	private $entity;
67
	/** @var string */
68
	private $url;
69
	/** @var string */
70
	private $slogan;
71
	/** @var string */
72
	private $color;
73
74
	/** @var string */
75
	private $iTunesAppId;
76
	/** @var string */
77
	private $iOSClientUrl;
78
	/** @var string */
79
	private $AndroidClientUrl;
80
81
	/**
82
	 * ThemingDefaults constructor.
83
	 *
84
	 * @param IConfig $config
85
	 * @param IL10N $l
86
	 * @param ImageManager $imageManager
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
								IURLGenerator $urlGenerator,
95
								ICacheFactory $cacheFactory,
96
								Util $util,
97
								ImageManager $imageManager,
98
								IAppManager $appManager
99
	) {
100
		parent::__construct();
101
		$this->config = $config;
102
		$this->l = $l;
103
		$this->imageManager = $imageManager;
104
		$this->urlGenerator = $urlGenerator;
105
		$this->cacheFactory = $cacheFactory;
106
		$this->util = $util;
107
		$this->appManager = $appManager;
108
109
		$this->name = parent::getName();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getName() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getName().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
110
		$this->title = parent::getTitle();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getTitle() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getTitle().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
111
		$this->entity = parent::getEntity();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getEntity() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getEntity().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
112
		$this->url = parent::getBaseUrl();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getBaseUrl() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getBaseUrl().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
113
		$this->slogan = parent::getSlogan();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getSlogan() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getSlogan().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
114
		$this->color = parent::getColorPrimary();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getColorPrimary() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getColorPrimary().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
115
		$this->iTunesAppId = parent::getiTunesAppId();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getiTunesAppId() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getiTunesAppId().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
116
		$this->iOSClientUrl = parent::getiOSClientUrl();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getiOSClientUrl() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getiOSClientUrl().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
117
		$this->AndroidClientUrl = parent::getAndroidClientUrl();
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (getAndroidClientUrl() instead of __construct()). Are you sure this is correct? If so, you might want to change this to $this->getAndroidClientUrl().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
118
	}
119
120
	public function getName() {
121
		return strip_tags($this->config->getAppValue('theming', 'name', $this->name));
122
	}
123
124
	public function getHTMLName() {
125
		return $this->config->getAppValue('theming', 'name', $this->name);
126
	}
127
128
	public function getTitle() {
129
		return strip_tags($this->config->getAppValue('theming', 'name', $this->title));
130
	}
131
132
	public function getEntity() {
133
		return strip_tags($this->config->getAppValue('theming', 'name', $this->entity));
134
	}
135
136
	public function getBaseUrl() {
137
		return $this->config->getAppValue('theming', 'url', $this->url);
138
	}
139
140
	public function getSlogan() {
141
		return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan));
0 ignored issues
show
Bug Compatibility introduced by
The expression \OCP\Util::sanitizeHTML(...ogan', $this->slogan)); of type array|string adds the type array to the return on line 141 which is incompatible with the return type of the parent method OC_Defaults::getSlogan of type string.
Loading history...
142
	}
143
144
	public function getImprintUrl() {
145
		return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
146
	}
147
148
	public function getPrivacyUrl() {
149
		return (string)$this->config->getAppValue('theming', 'privacyUrl', '');
150
	}
151
152
	public function getShortFooter() {
153
		$slogan = $this->getSlogan();
154
		$footer = '<a href="'. $this->getBaseUrl() . '" target="_blank"' .
155
			' rel="noreferrer noopener">' .$this->getEntity() . '</a>'.
156
			($slogan !== '' ? ' – ' . $slogan : '');
157
158
		$links = [
159
			[
160
				'text' => $this->l->t('Legal notice'),
161
				'url' => (string)$this->getImprintUrl()
162
			],
163
			[
164
				'text' => $this->l->t('Privacy policy'),
165
				'url' => (string)$this->getPrivacyUrl()
166
			],
167
		];
168
169
		$legalLinks = ''; $divider = '';
170
		foreach($links as $link) {
171
			if($link['url'] !== ''
172
				&& filter_var($link['url'], FILTER_VALIDATE_URL, [
173
					'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED
174
				])
175
			) {
176
				$legalLinks .= $divider . '<a href="' . $link['url'] . '" class="legal" target="_blank"' .
177
					' rel="noreferrer noopener">' . $link['text'] . '</a>';
178
				$divider = ' · ';
179
			}
180
		}
181
		if($legalLinks !== '' ) {
182
			$footer .= '<br/>' . $legalLinks;
183
		}
184
185
		return $footer;
186
	}
187
188
	/**
189
	 * Color that is used for the header as well as for mail headers
190
	 *
191
	 * @return string
192
	 */
193
	public function getColorPrimary() {
194
		return $this->config->getAppValue('theming', 'color', $this->color);
195
	}
196
197
	/**
198
	 * Themed logo url
199
	 *
200
	 * @param bool $useSvg Whether to point to the SVG image or a fallback
201
	 * @return string
202
	 */
203
	public function getLogo($useSvg = true): string {
204
		$logo = $this->config->getAppValue('theming', 'logoMime', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
205
206
		$logoExists = true;
207
		try {
208
			$this->imageManager->getImage('logo');
209
		} catch (\Exception $e) {
210
			$logoExists = false;
211
		}
212
213
		$cacheBusterCounter = $this->config->getAppValue('theming', 'cachebuster', '0');
214
215
		if(!$logo || !$logoExists) {
216
			if($useSvg) {
217
				$logo = $this->urlGenerator->imagePath('core', 'logo.svg');
218
			} else {
219
				$logo = $this->urlGenerator->imagePath('core', 'logo.png');
220
			}
221
			return $logo . '?v=' . $cacheBusterCounter;
222
		}
223
224
		return $this->urlGenerator->linkToRoute('theming.Theming.getImage', [ 'key' => 'logo' ]) . '?v=' . $cacheBusterCounter;
225
	}
226
227
	/**
228
	 * Themed background image url
229
	 *
230
	 * @return string
231
	 */
232
	public function getBackground(): string {
233
		return $this->imageManager->getImageUrl('background');
234
	}
235
236
	/**
237
	 * @return string
238
	 */
239
	public function getiTunesAppId() {
240
		return $this->config->getAppValue('theming', 'iTunesAppId', $this->iTunesAppId);
241
	}
242
243
	/**
244
	 * @return string
245
	 */
246
	public function getiOSClientUrl() {
247
		return $this->config->getAppValue('theming', 'iOSClientUrl', $this->iOSClientUrl);
248
	}
249
250
	/**
251
	 * @return string
252
	 */
253
	public function getAndroidClientUrl() {
254
		return $this->config->getAppValue('theming', 'AndroidClientUrl', $this->AndroidClientUrl);
255
	}
256
257
258
	/**
259
	 * @return array scss variables to overwrite
260
	 */
261
	public function getScssVariables() {
262
		$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
263
		if ($value = $cache->get('getScssVariables')) {
264
			return $value;
265
		}
266
267
		$variables = [
268
			'theming-cachebuster' => "'" . $this->config->getAppValue('theming', 'cachebuster', '0') . "'",
269
			'theming-logo-mime' => "'" . $this->config->getAppValue('theming', 'logoMime') . "'",
270
			'theming-background-mime' => "'" . $this->config->getAppValue('theming', 'backgroundMime') . "'",
271
			'theming-logoheader-mime' => "'" . $this->config->getAppValue('theming', 'logoheaderMime') . "'",
272
			'theming-favicon-mime' => "'" . $this->config->getAppValue('theming', 'faviconMime') . "'"
273
		];
274
275
		$variables['image-logo'] = "'".$this->imageManager->getImageUrl('logo')."'";
276
		$variables['image-logoheader'] = "'".$this->imageManager->getImageUrl('logoheader')."'";
277
		$variables['image-favicon'] = "'".$this->imageManager->getImageUrl('favicon')."'";
278
		$variables['image-login-background'] = "'".$this->imageManager->getImageUrl('background')."'";
279
		$variables['image-login-plain'] = 'false';
280
281
		if ($this->config->getAppValue('theming', 'color', null) !== null) {
282
			$variables['color-primary'] = $this->getColorPrimary();
283
			$variables['color-primary-text'] = $this->getTextColorPrimary();
284
			$variables['color-primary-element'] = $this->util->elementColor($this->getColorPrimary());
285
		}
286
287
		if ($this->config->getAppValue('theming', 'backgroundMime', null) === 'backgroundColor') {
288
			$variables['image-login-plain'] = 'true';
289
		}
290
291
		$variables['has-legal-links'] = 'false';
292
		if($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
293
			$variables['has-legal-links'] = 'true';
294
		}
295
296
		$cache->set('getScssVariables', $variables);
297
		return $variables;
298
	}
299
300
	/**
301
	 * Check if the image should be replaced by the theming app
302
	 * and return the new image location then
303
	 *
304
	 * @param string $app name of the app
305
	 * @param string $image filename of the image
306
	 * @return bool|string false if image should not replaced, otherwise the location of the image
307
	 */
308
	public function replaceImagePath($app, $image) {
309
		if($app==='') {
310
			$app = 'core';
311
		}
312
		$cacheBusterValue = $this->config->getAppValue('theming', 'cachebuster', '0');
313
314
		try {
315
			$customFavicon = $this->imageManager->getImage('favicon');
316
		} catch (NotFoundException $e) {
317
			$customFavicon = null;
318
		}
319
320 View Code Duplication
		if ($image === 'favicon.ico' && ($customFavicon !== null || $this->shouldReplaceIcons())) {
321
			return $this->urlGenerator->linkToRoute('theming.Icon.getFavicon', ['app' => $app]) . '?v=' . $cacheBusterValue;
322
		}
323 View Code Duplication
		if ($image === 'favicon-touch.png' && ($customFavicon !== null || $this->shouldReplaceIcons())) {
324
			return $this->urlGenerator->linkToRoute('theming.Icon.getTouchIcon', ['app' => $app]) . '?v=' . $cacheBusterValue;
325
		}
326
		if ($image === 'manifest.json') {
327
			try {
328
				$appPath = $this->appManager->getAppPath($app);
329
				if (file_exists($appPath . '/img/manifest.json')) {
330
					return false;
331
				}
332
			} catch (AppPathNotFoundException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
333
			return $this->urlGenerator->linkToRoute('theming.Theming.getManifest') . '?v=' . $cacheBusterValue;
334
		}
335
		return false;
336
	}
337
338
	/**
339
	 * Check if Imagemagick is enabled and if SVG is supported
340
	 * otherwise we can't render custom icons
341
	 *
342
	 * @return bool
343
	 */
344
	public function shouldReplaceIcons() {
345
		$cache = $this->cacheFactory->createDistributed('theming-' . $this->urlGenerator->getBaseUrl());
346
		if($value = $cache->get('shouldReplaceIcons')) {
347
			return (bool)$value;
348
		}
349
		$value = false;
350
		if(extension_loaded('imagick')) {
351
			$checkImagick = new \Imagick();
352
			if (count($checkImagick->queryFormats('SVG')) >= 1) {
353
				$value = true;
354
			}
355
			$checkImagick->clear();
356
		}
357
		$cache->set('shouldReplaceIcons', $value);
358
		return $value;
359
	}
360
361
	/**
362
	 * Increases the cache buster key
363
	 */
364
	private function increaseCacheBuster() {
365
		$cacheBusterKey = $this->config->getAppValue('theming', 'cachebuster', '0');
366
		$this->config->setAppValue('theming', 'cachebuster', (int)$cacheBusterKey+1);
367
		$this->cacheFactory->createDistributed('theming-')->clear();
368
		$this->cacheFactory->createDistributed('imagePath')->clear();
369
370
	}
371
372
	/**
373
	 * Update setting in the database
374
	 *
375
	 * @param string $setting
376
	 * @param string $value
377
	 */
378
	public function set($setting, $value) {
379
		$this->config->setAppValue('theming', $setting, $value);
380
		$this->increaseCacheBuster();
381
	}
382
383
	/**
384
	 * Revert settings to the default value
385
	 *
386
	 * @param string $setting setting which should be reverted
387
	 * @return string default value
388
	 */
389
	public function undo($setting) {
390
		$this->config->deleteAppValue('theming', $setting);
391
		$this->increaseCacheBuster();
392
393
		switch ($setting) {
394
			case 'name':
395
				$returnValue = $this->getEntity();
396
				break;
397
			case 'url':
398
				$returnValue = $this->getBaseUrl();
399
				break;
400
			case 'slogan':
401
				$returnValue = $this->getSlogan();
402
				break;
403
			case 'color':
404
				$returnValue = $this->getColorPrimary();
405
				break;
406
			default:
407
				$returnValue = '';
408
				break;
409
		}
410
411
		return $returnValue;
412
	}
413
414
	/**
415
	 * Color of text in the header and primary buttons
416
	 *
417
	 * @return string
418
	 */
419
	public function getTextColorPrimary() {
420
		return $this->util->invertTextColor($this->getColorPrimary()) ? '#000000' : '#ffffff';
421
	}
422
}
423