Passed
Push — master ( 859941...64f5a2 )
by Joas
12:41 queued 11s
created

AccessibilityController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 25
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 13
nc 1
nop 11
dl 0
loc 25
rs 9.8333
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
declare(strict_types=1);
4
5
/**
6
 * @copyright Copyright (c) 2018 John Molakvoæ (skjnldsv) <[email protected]>
7
 * @copyright Copyright (c) 2019 Janis Köhr <[email protected]>
8
 *
9
 * @author Alexey Pyltsyn <[email protected]>
10
 * @author Christoph Wurst <[email protected]>
11
 * @author Janis Köhr <[email protected]>
12
 * @author Joas Schilling <[email protected]>
13
 * @author John Molakvoæ (skjnldsv) <[email protected]>
14
 * @author Julius Härtl <[email protected]>
15
 * @author Roeland Jago Douma <[email protected]>
16
 * @author Thomas Citharel <[email protected]>
17
 *
18
 * @license GNU AGPL version 3 or any later version
19
 *
20
 * This program is free software: you can redistribute it and/or modify
21
 * it under the terms of the GNU Affero General Public License as
22
 * published by the Free Software Foundation, either version 3 of the
23
 * License, or (at your option) any later version.
24
 *
25
 * This program is distributed in the hope that it will be useful,
26
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
 * GNU Affero General Public License for more details.
29
 *
30
 * You should have received a copy of the GNU Affero General Public License
31
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32
 *
33
 */
34
35
namespace OCA\Accessibility\Controller;
36
37
use OC\Template\IconsCacher;
38
use OCP\App\IAppManager;
39
use OCP\AppFramework\Controller;
40
use OCP\AppFramework\Http;
41
use OCP\AppFramework\Http\DataDisplayResponse;
42
use OCP\AppFramework\Utility\ITimeFactory;
43
use OCP\IConfig;
44
use OCP\ILogger;
45
use OCP\IRequest;
46
use OCP\IURLGenerator;
47
use OCP\IUserManager;
48
use OCP\IUserSession;
49
use ScssPhp\ScssPhp\Compiler;
50
use ScssPhp\ScssPhp\Exception\ParserException;
51
use ScssPhp\ScssPhp\Formatter\Crunched;
52
53
class AccessibilityController extends Controller {
54
55
	/** @var string */
56
	protected $appName;
57
58
	/** @var string */
59
	protected $serverRoot;
60
61
	/** @var IConfig */
62
	private $config;
63
64
	/** @var IUserManager */
65
	private $userManager;
66
67
	/** @var ILogger */
68
	private $logger;
69
70
	/** @var IURLGenerator */
71
	private $urlGenerator;
72
73
	/** @var ITimeFactory */
74
	protected $timeFactory;
75
76
	/** @var IUserSession */
77
	private $userSession;
78
79
	/** @var IAppManager */
80
	private $appManager;
81
82
	/** @var IconsCacher */
83
	protected $iconsCacher;
84
85
	/** @var \OC_Defaults */
86
	private $defaults;
87
88
	/** @var null|string */
89
	private $injectedVariables;
90
91
	/**
92
	 * Account constructor.
93
	 *
94
	 * @param string $appName
95
	 * @param IRequest $request
96
	 * @param IConfig $config
97
	 * @param IUserManager $userManager
98
	 * @param ILogger $logger
99
	 * @param IURLGenerator $urlGenerator
100
	 * @param ITimeFactory $timeFactory
101
	 * @param IUserSession $userSession
102
	 * @param IAppManager $appManager
103
	 * @param \OC_Defaults $defaults
104
	 */
105
	public function __construct(string $appName,
106
								IRequest $request,
107
								IConfig $config,
108
								IUserManager $userManager,
109
								ILogger $logger,
110
								IURLGenerator $urlGenerator,
111
								ITimeFactory $timeFactory,
112
								IUserSession $userSession,
113
								IAppManager $appManager,
114
								IconsCacher $iconsCacher,
115
								\OC_Defaults $defaults) {
116
		parent::__construct($appName, $request);
117
		$this->appName      = $appName;
118
		$this->config       = $config;
119
		$this->userManager  = $userManager;
120
		$this->logger       = $logger;
121
		$this->urlGenerator = $urlGenerator;
122
		$this->timeFactory  = $timeFactory;
123
		$this->userSession  = $userSession;
124
		$this->appManager   = $appManager;
125
		$this->iconsCacher  = $iconsCacher;
126
		$this->defaults     = $defaults;
127
128
		$this->serverRoot = \OC::$SERVERROOT;
129
		$this->appRoot    = $this->appManager->getAppPath($this->appName);
0 ignored issues
show
Bug Best Practice introduced by
The property appRoot does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
130
	}
131
132
	/**
133
	 * @PublicPage
134
	 * @NoCSRFRequired
135
	 * @NoSameSiteCookieRequired
136
	 *
137
	 * @return DataDisplayResponse
138
	 */
139
	public function getCss(): DataDisplayResponse {
140
		$css        = '';
141
		$imports    = '';
142
		if ($this->userSession->isLoggedIn()) {
143
			$userValues = $this->getUserValues();
144
		} else {
145
			$userValues = ['dark'];
146
		}
147
148
		foreach ($userValues as $key => $scssFile) {
149
			if ($scssFile !== false) {
150
				if ($scssFile === 'highcontrast' && in_array('dark', $userValues)) {
151
					$scssFile .= 'dark';
152
				}
153
				$imports .= '@import "' . $scssFile . '";';
154
			}
155
		}
156
157
		if ($imports !== '') {
158
			$scss = new Compiler();
159
			$scss->setImportPaths([
160
				$this->appRoot . '/css/',
161
				$this->serverRoot . '/core/css/'
162
			]);
163
164
			// Continue after throw
165
			$scss->setIgnoreErrors(true);
166
			$scss->setFormatter(Crunched::class);
167
168
			// Import theme, variables and compile css4 variables
169
			try {
170
				$css .= $scss->compile(
171
					$imports .
172
					$this->getInjectedVariables() .
173
					'@import "variables.scss";' .
174
					'@import "css-variables.scss";'
175
				);
176
			} catch (ParserException $e) {
177
				$this->logger->error($e->getMessage(), ['app' => 'core']);
178
			}
179
		}
180
181
		// We don't want to override vars with url since path is different
182
		$css = $this->filterOutRule('/--[a-z-:]+url\([^;]+\)/mi', $css);
183
184
		// Rebase all urls
185
		$appWebRoot = substr($this->appRoot, strlen($this->serverRoot) - strlen(\OC::$WEBROOT));
186
		$css        = $this->rebaseUrls($css, $appWebRoot . '/css');
187
188
		if (in_array('dark', $userValues) && $this->iconsCacher->getCachedList() && $this->iconsCacher->getCachedList()->getSize() > 0) {
189
			$iconsCss = $this->invertSvgIconsColor($this->iconsCacher->getCachedList()->getContent());
190
			$css = $css . $iconsCss;
191
		}
192
193
		$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
194
195
		// Set cache control
196
		$ttl = 31536000;
197
		$response->addHeader('Cache-Control', 'max-age=' . $ttl . ', immutable');
198
		$expires = new \DateTime();
199
		$expires->setTimestamp($this->timeFactory->getTime());
200
		$expires->add(new \DateInterval('PT' . $ttl . 'S'));
201
		$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
202
		$response->addHeader('Pragma', 'cache');
203
204
		// store current cache hash
205
		if ($this->userSession->isLoggedIn()) {
206
			$this->config->setUserValue($this->userSession->getUser()->getUID(), $this->appName, 'icons-css', md5($css));
207
		}
208
209
		return $response;
210
	}
211
212
	/**
213
	 * Return an array with the user theme & font settings
214
	 *
215
	 * @return array
216
	 */
217
	private function getUserValues(): array {
218
		$userTheme = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'theme', false);
219
		$userFont  = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'font', false);
220
		$userHighContrast = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'highcontrast', false);
221
222
		return [$userTheme, $userHighContrast, $userFont];
223
	}
224
225
	/**
226
	 * Remove all matches from the $rule regex
227
	 *
228
	 * @param string $rule regex to match
229
	 * @param string $css string to parse
230
	 * @return string
231
	 */
232
	private function filterOutRule(string $rule, string $css): string {
233
		return preg_replace($rule, '', $css);
234
	}
235
236
	/**
237
	 * Add the correct uri prefix to make uri valid again
238
	 *
239
	 * @param string $css
240
	 * @param string $webDir
241
	 * @return string
242
	 */
243
	private function rebaseUrls(string $css, string $webDir): string {
244
		$re    = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
245
		$subst = 'url(\'' . $webDir . '/$1\')';
246
247
		return preg_replace($re, $subst, $css);
248
	}
249
250
	/**
251
	 * Remove all matches from the $rule regex
252
	 *
253
	 * @param string $css string to parse
254
	 * @return string
255
	 */
256
	private function invertSvgIconsColor(string $css) {
257
		return str_replace(
258
			['color=000&', 'color=fff&', 'color=***&'],
259
			['color=***&', 'color=000&', 'color=fff&'],
260
			str_replace(
261
				['color=000000&', 'color=ffffff&', 'color=******&'],
262
				['color=******&', 'color=000000&', 'color=ffffff&'],
263
				$css
264
			)
265
		);
266
	}
267
268
	/**
269
	 * @return string SCSS code for variables from OC_Defaults
270
	 */
271
	private function getInjectedVariables(): string {
272
		if ($this->injectedVariables !== null) {
273
			return $this->injectedVariables;
274
		}
275
		$variables = '';
276
		foreach ($this->defaults->getScssVariables() as $key => $value) {
277
			$variables .= '$' . $key . ': ' . $value . ';';
278
		}
279
280
		// check for valid variables / otherwise fall back to defaults
281
		try {
282
			$scss = new Compiler();
283
			$scss->compile($variables);
284
			$this->injectedVariables = $variables;
285
		} catch (ParserException $e) {
286
			$this->logger->logException($e, ['app' => 'core']);
287
		}
288
		return $variables;
289
	}
290
}
291