Passed
Push — master ( e324c9...3ac048 )
by Roeland
19:27 queued 12s
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
	 * @NoAdminRequired
134
	 * @NoCSRFRequired
135
	 * @NoSameSiteCookieRequired
136
	 *
137
	 * @return DataDisplayResponse
138
	 */
139
	public function getCss(): DataDisplayResponse {
140
		$css        = '';
141
		$imports    = '';
142
		$userValues = $this->getUserValues();
143
144
		foreach ($userValues as $key => $scssFile) {
145
			if ($scssFile !== false) {
146
				if ($scssFile === 'highcontrast' && in_array('dark', $userValues)) {
147
					$scssFile .= 'dark';
148
				}
149
				$imports .= '@import "' . $scssFile . '";';
150
			}
151
		}
152
153
		if ($imports !== '') {
154
			$scss = new Compiler();
155
			$scss->setImportPaths([
156
				$this->appRoot . '/css/',
157
				$this->serverRoot . '/core/css/'
158
			]);
159
160
			// Continue after throw
161
			$scss->setIgnoreErrors(true);
162
			$scss->setFormatter(Crunched::class);
163
164
			// Import theme, variables and compile css4 variables
165
			try {
166
				$css .= $scss->compile(
167
					$imports .
168
					$this->getInjectedVariables() .
169
					'@import "variables.scss";' .
170
					'@import "css-variables.scss";'
171
				);
172
			} catch (ParserException $e) {
173
				$this->logger->error($e->getMessage(), ['app' => 'core']);
174
			}
175
		}
176
177
		// We don't want to override vars with url since path is different
178
		$css = $this->filterOutRule('/--[a-z-:]+url\([^;]+\)/mi', $css);
179
180
		// Rebase all urls
181
		$appWebRoot = substr($this->appRoot, strlen($this->serverRoot) - strlen(\OC::$WEBROOT));
182
		$css        = $this->rebaseUrls($css, $appWebRoot . '/css');
183
184
		if (in_array('dark', $userValues) && $this->iconsCacher->getCachedList() && $this->iconsCacher->getCachedList()->getSize() > 0) {
185
			$iconsCss = $this->invertSvgIconsColor($this->iconsCacher->getCachedList()->getContent());
186
			$css = $css . $iconsCss;
187
		}
188
189
		$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
190
191
		// Set cache control
192
		$ttl = 31536000;
193
		$response->addHeader('Cache-Control', 'max-age=' . $ttl . ', immutable');
194
		$expires = new \DateTime();
195
		$expires->setTimestamp($this->timeFactory->getTime());
196
		$expires->add(new \DateInterval('PT' . $ttl . 'S'));
197
		$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
198
		$response->addHeader('Pragma', 'cache');
199
200
		// store current cache hash
201
		$this->config->setUserValue($this->userSession->getUser()->getUID(), $this->appName, 'icons-css', md5($css));
202
203
		return $response;
204
	}
205
206
	/**
207
	 * Return an array with the user theme & font settings
208
	 *
209
	 * @return array
210
	 */
211
	private function getUserValues(): array {
212
		$userTheme = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'theme', false);
213
		$userFont  = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'font', false);
214
		$userHighContrast = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'highcontrast', false);
215
216
		return [$userTheme, $userHighContrast, $userFont];
217
	}
218
219
	/**
220
	 * Remove all matches from the $rule regex
221
	 *
222
	 * @param string $rule regex to match
223
	 * @param string $css string to parse
224
	 * @return string
225
	 */
226
	private function filterOutRule(string $rule, string $css): string {
227
		return preg_replace($rule, '', $css);
228
	}
229
230
	/**
231
	 * Add the correct uri prefix to make uri valid again
232
	 *
233
	 * @param string $css
234
	 * @param string $webDir
235
	 * @return string
236
	 */
237
	private function rebaseUrls(string $css, string $webDir): string {
238
		$re    = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
239
		$subst = 'url(\'' . $webDir . '/$1\')';
240
241
		return preg_replace($re, $subst, $css);
242
	}
243
244
	/**
245
	 * Remove all matches from the $rule regex
246
	 *
247
	 * @param string $css string to parse
248
	 * @return string
249
	 */
250
	private function invertSvgIconsColor(string $css) {
251
		return str_replace(
252
			['color=000&', 'color=fff&', 'color=***&'],
253
			['color=***&', 'color=000&', 'color=fff&'],
254
			str_replace(
255
				['color=000000&', 'color=ffffff&', 'color=******&'],
256
				['color=******&', 'color=000000&', 'color=ffffff&'],
257
				$css
258
			)
259
		);
260
	}
261
262
	/**
263
	 * @return string SCSS code for variables from OC_Defaults
264
	 */
265
	private function getInjectedVariables(): string {
266
		if ($this->injectedVariables !== null) {
267
			return $this->injectedVariables;
268
		}
269
		$variables = '';
270
		foreach ($this->defaults->getScssVariables() as $key => $value) {
271
			$variables .= '$' . $key . ': ' . $value . ';';
272
		}
273
274
		// check for valid variables / otherwise fall back to defaults
275
		try {
276
			$scss = new Compiler();
277
			$scss->compile($variables);
278
			$this->injectedVariables = $variables;
279
		} catch (ParserException $e) {
280
			$this->logger->logException($e, ['app' => 'core']);
281
		}
282
		return $variables;
283
	}
284
}
285