Passed
Push — master ( 3231b3...73e3d0 )
by John
12:14 queued 12s
created

Util::invertTextColor()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Julius Härtl <[email protected]>
4
 *
5
 * @author Christoph Wurst <[email protected]>
6
 * @author Daniel Kesselberg <[email protected]>
7
 * @author Joas Schilling <[email protected]>
8
 * @author Julien Veyssier <[email protected]>
9
 * @author Julius Haertl <[email protected]>
10
 * @author Julius Härtl <[email protected]>
11
 * @author Michael Weimann <[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
namespace OCA\Theming;
30
31
use OCP\App\AppPathNotFoundException;
32
use OCP\App\IAppManager;
33
use OCP\Files\IAppData;
34
use OCP\Files\NotFoundException;
35
use OCP\Files\SimpleFS\ISimpleFile;
36
use OCP\IConfig;
37
38
class Util {
39
40
	/** @var IConfig */
41
	private $config;
42
43
	/** @var IAppManager */
44
	private $appManager;
45
46
	/** @var IAppData */
47
	private $appData;
48
49
	/**
50
	 * Util constructor.
51
	 *
52
	 * @param IConfig $config
53
	 * @param IAppManager $appManager
54
	 * @param IAppData $appData
55
	 */
56
	public function __construct(IConfig $config, IAppManager $appManager, IAppData $appData) {
57
		$this->config = $config;
58
		$this->appManager = $appManager;
59
		$this->appData = $appData;
60
	}
61
62
	/**
63
	 * @param string $color rgb color value
64
	 * @return bool
65
	 */
66
	public function invertTextColor($color) {
67
		$l = $this->calculateLuma($color);
68
		if ($l > 0.6) {
69
			return true;
70
		} else {
71
			return false;
72
		}
73
	}
74
75
	/**
76
	 * get color for on-page elements:
77
	 * theme color by default, grey if theme color is to bright
78
	 * @param string $color
79
	 * @param bool $brightBackground
80
	 * @return string
81
	 */
82
	public function elementColor($color, bool $brightBackground = true) {
83
		$luminance = $this->calculateLuminance($color);
84
85
		if ($brightBackground && $luminance > 0.8) {
86
			// If the color is too bright in bright mode, we fall back to a darker gray
87
			return '#aaaaaa';
88
		}
89
90
		if (!$brightBackground && $luminance < 0.2) {
91
			// If the color is too dark in dark mode, we fall back to a brighter gray
92
			return '#555555';
93
		}
94
95
		return $color;
96
	}
97
98
	/**
99
	 * Convert RGB to HSL
100
	 *
101
	 * Copied from cssphp, copyright Leaf Corcoran, licensed under MIT
102
	 *
103
	 * @param integer $red
104
	 * @param integer $green
105
	 * @param integer $blue
106
	 *
107
	 * @return array
108
	 */
109
	public function toHSL($red, $green, $blue) {
110
		$min = min($red, $green, $blue);
111
		$max = max($red, $green, $blue);
112
		$l = $min + $max;
113
		$d = $max - $min;
114
115
		if ((int) $d === 0) {
116
			$h = $s = 0;
117
		} else {
118
			if ($l < 255) {
119
				$s = $d / $l;
120
			} else {
121
				$s = $d / (510 - $l);
122
			}
123
124
			if ($red == $max) {
125
				$h = 60 * ($green - $blue) / $d;
126
			} elseif ($green == $max) {
127
				$h = 60 * ($blue - $red) / $d + 120;
128
			} else {
129
				$h = 60 * ($red - $green) / $d + 240;
130
			}
131
		}
132
133
		return [fmod($h, 360), $s * 100, $l / 5.1];
134
	}
135
136
	/**
137
	 * @param string $color rgb color value
138
	 * @return float
139
	 */
140
	public function calculateLuminance($color) {
141
		[$red, $green, $blue] = $this->hexToRGB($color);
142
		$hsl = $this->toHSL($red, $green, $blue);
143
		return $hsl[2] / 100;
144
	}
145
146
	/**
147
	 * @param string $color rgb color value
148
	 * @return float
149
	 */
150
	public function calculateLuma($color) {
151
		[$red, $green, $blue] = $this->hexToRGB($color);
152
		return (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue) / 255;
153
	}
154
155
	/**
156
	 * @param string $color rgb color value
157
	 * @return int[]
158
	 * @psalm-return array{0: int, 1: int, 2: int}
159
	 */
160
	public function hexToRGB($color) {
161
		$hex = preg_replace("/[^0-9A-Fa-f]/", '', $color);
162
		if (strlen($hex) === 3) {
163
			$hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
164
		}
165
		if (strlen($hex) !== 6) {
166
			return [0, 0, 0];
167
		}
168
		return [
169
			hexdec(substr($hex, 0, 2)),
170
			hexdec(substr($hex, 2, 2)),
171
			hexdec(substr($hex, 4, 2))
172
		];
173
	}
174
175
	/**
176
	 * @param $color
177
	 * @return string base64 encoded radio button svg
178
	 */
179
	public function generateRadioButton($color) {
180
		$radioButtonIcon = '<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16">' .
181
			'<path d="M8 1a7 7 0 0 0-7 7 7 7 0 0 0 7 7 7 7 0 0 0 7-7 7 7 0 0 0-7-7zm0 1a6 6 0 0 1 6 6 6 6 0 0 1-6 6 6 6 0 0 1-6-6 6 6 0 0 1 6-6zm0 2a4 4 0 1 0 0 8 4 4 0 0 0 0-8z" fill="'.$color.'"/></svg>';
182
		return base64_encode($radioButtonIcon);
183
	}
184
185
186
	/**
187
	 * @param $app string app name
188
	 * @return string|ISimpleFile path to app icon / file of logo
189
	 */
190
	public function getAppIcon($app) {
191
		$app = str_replace(['\0', '/', '\\', '..'], '', $app);
192
		try {
193
			$appPath = $this->appManager->getAppPath($app);
194
			$icon = $appPath . '/img/' . $app . '.svg';
195
			if (file_exists($icon)) {
196
				return $icon;
197
			}
198
			$icon = $appPath . '/img/app.svg';
199
			if (file_exists($icon)) {
200
				return $icon;
201
			}
202
		} catch (AppPathNotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
203
		}
204
205
		if ($this->config->getAppValue('theming', 'logoMime', '') !== '') {
206
			$logoFile = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $logoFile is dead and can be removed.
Loading history...
207
			try {
208
				$folder = $this->appData->getFolder('images');
209
				return $folder->getFile('logo');
210
			} catch (NotFoundException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
211
			}
212
		}
213
		return \OC::$SERVERROOT . '/core/img/logo/logo.svg';
214
	}
215
216
	/**
217
	 * @param $app string app name
218
	 * @param $image string relative path to image in app folder
219
	 * @return string|false absolute path to image
220
	 */
221
	public function getAppImage($app, $image) {
222
		$app = str_replace(['\0', '/', '\\', '..'], '', $app);
223
		$image = str_replace(['\0', '\\', '..'], '', $image);
224
		if ($app === "core") {
225
			$icon = \OC::$SERVERROOT . '/core/img/' . $image;
226
			if (file_exists($icon)) {
227
				return $icon;
228
			}
229
		}
230
231
		try {
232
			$appPath = $this->appManager->getAppPath($app);
233
		} catch (AppPathNotFoundException $e) {
234
			return false;
235
		}
236
237
		$icon = $appPath . '/img/' . $image;
238
		if (file_exists($icon)) {
239
			return $icon;
240
		}
241
		$icon = $appPath . '/img/' . $image . '.svg';
242
		if (file_exists($icon)) {
243
			return $icon;
244
		}
245
		$icon = $appPath . '/img/' . $image . '.png';
246
		if (file_exists($icon)) {
247
			return $icon;
248
		}
249
		$icon = $appPath . '/img/' . $image . '.gif';
250
		if (file_exists($icon)) {
251
			return $icon;
252
		}
253
		$icon = $appPath . '/img/' . $image . '.jpg';
254
		if (file_exists($icon)) {
255
			return $icon;
256
		}
257
258
		return false;
259
	}
260
261
	/**
262
	 * replace default color with a custom one
263
	 *
264
	 * @param $svg string content of a svg file
265
	 * @param $color string color to match
266
	 * @return string
267
	 */
268
	public function colorizeSvg($svg, $color) {
269
		$svg = preg_replace('/#0082c9/i', $color, $svg);
270
		return $svg;
271
	}
272
273
	/**
274
	 * Check if a custom theme is set in the server configuration
275
	 *
276
	 * @return bool
277
	 */
278
	public function isAlreadyThemed() {
279
		$theme = $this->config->getSystemValue('theme', '');
280
		if ($theme !== '') {
281
			return true;
282
		}
283
		return false;
284
	}
285
286
	public function isBackgroundThemed() {
287
		$backgroundLogo = $this->config->getAppValue('theming', 'backgroundMime', '');
288
		return $backgroundLogo !== '' && $backgroundLogo !== 'backgroundColor';
289
	}
290
}
291