Completed
Push — master ( d35b65...6a979a )
by Morris
24:58 queued 10s
created

AccessibilityController::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 11
dl 0
loc 26
rs 9.504
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
declare (strict_types = 1);
3
/**
4
 * @copyright Copyright (c) 2018 John Molakvoæ (skjnldsv) <[email protected]>
5
 *
6
 * @license GNU AGPL version 3 or any later version
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU Affero General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
namespace OCA\Accessibility\Controller;
24
25
use Leafo\ScssPhp\Compiler;
26
use Leafo\ScssPhp\Exception\ParserException;
27
use Leafo\ScssPhp\Formatter\Crunched;
28
use OCP\AppFramework\Controller;
29
use OCP\AppFramework\Http;
30
use OCP\AppFramework\Http\DataDisplayResponse;
31
use OCP\AppFramework\Http\DataDownloadResponse;
32
use OCP\AppFramework\Utility\ITimeFactory;
33
use OCP\App\IAppManager;
34
use OCP\IConfig;
35
use OCP\ILogger;
36
use OCP\IRequest;
37
use OCP\IURLGenerator;
38
use OCP\IUserManager;
39
use OCP\IUserSession;
40
use OC\Template\IconsCacher;
41
42
class AccessibilityController extends Controller {
43
44
	/** @var string */
45
	protected $appName;
46
47
	/** @var string */
48
	protected $serverRoot;
49
50
	/** @var IConfig */
51
	private $config;
52
53
	/** @var IUserManager */
54
	private $userManager;
55
56
	/** @var ILogger */
57
	private $logger;
58
59
	/** @var IURLGenerator */
60
	private $urlGenerator;
61
62
	/** @var ITimeFactory */
63
	protected $timeFactory;
64
65
	/** @var IUserSession */
66
	private $userSession;
67
68
	/** @var IAppManager */
69
	private $appManager;
70
71
	/** @var IconsCacher */
72
	protected $iconsCacher;
73
74
	/** @var \OC_Defaults */
75
	private $defaults;
76
77
	/** @var null|string */
78
	private $injectedVariables;
79
80
	/**
81
	 * Account constructor.
82
	 *
83
	 * @param string $appName
84
	 * @param IRequest $request
85
	 * @param IConfig $config
86
	 * @param IUserManager $userManager
87
	 * @param ILogger $logger
88
	 * @param IURLGenerator $urlGenerator
89
	 * @param ITimeFactory $timeFactory
90
	 * @param IUserSession $userSession
91
	 * @param IAppManager $appManager
92
	 * @param \OC_Defaults $defaults
93
	 */
94
	public function __construct(string $appName,
95
								IRequest $request,
96
								IConfig $config,
97
								IUserManager $userManager,
98
								ILogger $logger,
99
								IURLGenerator $urlGenerator,
100
								ITimeFactory $timeFactory,
101
								IUserSession $userSession,
102
								IAppManager $appManager,
103
								IconsCacher $iconsCacher,
104
								\OC_Defaults $defaults) {
105
		parent::__construct($appName, $request);
106
		$this->appName      = $appName;
107
		$this->config       = $config;
108
		$this->userManager  = $userManager;
109
		$this->logger       = $logger;
110
		$this->urlGenerator = $urlGenerator;
111
		$this->timeFactory  = $timeFactory;
112
		$this->userSession  = $userSession;
113
		$this->appManager   = $appManager;
114
		$this->iconsCacher  = $iconsCacher;
115
		$this->defaults     = $defaults;
116
117
		$this->serverRoot = \OC::$SERVERROOT;
118
		$this->appRoot    = $this->appManager->getAppPath($this->appName);
0 ignored issues
show
Bug introduced by
The property appRoot does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
119
	}
120
121
	/**
122
	 * @NoAdminRequired
123
	 * @NoCSRFRequired
124
	 *
125
	 * @return DataDisplayResponse
126
	 */
127
	public function getCss(): DataDisplayResponse {
128
		$css        = '';
129
		$imports    = '';
130
		$userValues = $this->getUserValues();
131
132
		foreach ($userValues as $key => $scssFile) {
133
			if ($scssFile !== false) {
134
				$imports .= '@import "' . $scssFile . '";';
135
			}
136
		}
137
138
		if ($imports !== '') {
139
			$scss = new Compiler();
140
			$scss->setImportPaths([
141
				$this->appRoot . '/css/',
142
				$this->serverRoot . '/core/css/'
143
			]);
144
145
			// Continue after throw
146
			$scss->setIgnoreErrors(true);
147
			$scss->setFormatter(Crunched::class);
148
149
			// Import theme, variables and compile css4 variables
150
			try {
151
				$css .= $scss->compile(
152
					$imports .
153
					$this->getInjectedVariables() .
154
					'@import "variables.scss";' .
155
					'@import "css-variables.scss";'
156
				);
157
			} catch (ParserException $e) {
0 ignored issues
show
Bug introduced by
The class Leafo\ScssPhp\Exception\ParserException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
158
				$this->logger->error($e->getMessage(), ['app' => 'core']);
159
			}
160
		}
161
162
		// We don't want to override vars with url since path is different
163
		$css = $this->filterOutRule('/--[a-z-:]+url\([^;]+\)/mi', $css);
164
165
		// Rebase all urls
166
		$appWebRoot = substr($this->appRoot, strlen($this->serverRoot) - strlen(\OC::$WEBROOT));
167
		$css        = $this->rebaseUrls($css, $appWebRoot . '/css');
168
169
		if (in_array('themedark', $userValues) && $this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
170
			$iconsCss = $this->invertSvgIconsColor($this->iconsCacher->getCachedCSS()->getContent());
171
			$css = $css . $iconsCss;
172
		}
173
174
		$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
175
176
		// Set cache control
177
		$ttl = 31536000;
178
		$response->addHeader('Cache-Control', 'max-age=' . $ttl . ', immutable');
179
		$expires = new \DateTime();
180
		$expires->setTimestamp($this->timeFactory->getTime());
181
		$expires->add(new \DateInterval('PT' . $ttl . 'S'));
182
		$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
183
		$response->addHeader('Pragma', 'cache');
184
185
		return $response;
186
	}
187
188
	/**
189
	 * @NoCSRFRequired
190
	 * @PublicPage
191
	 *
192
	 * @return DataDownloadResponse
193
	 */
194
	public function getJavascript(): DataDownloadResponse {
195
		$responseJS = '(function() {
196
	OCA.Accessibility = {
197
		theme: ' . json_encode($this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'theme', false)) . ',
198
		
199
	};
200
})();';
201
		$response = new DataDownloadResponse($responseJS, 'javascript', 'text/javascript');
202
		$response->cacheFor(3600);
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
215
		return [$userTheme, $userFont];
216
	}
217
218
	/**
219
	 * Remove all matches from the $rule regex
220
	 *
221
	 * @param string $rule regex to match
222
	 * @param string $css string to parse
223
	 * @return string
224
	 */
225
	private function filterOutRule(string $rule, string $css): string {
226
		return preg_replace($rule, '', $css);
227
	}
228
229
	/**
230
	 * Add the correct uri prefix to make uri valid again
231
	 *
232
	 * @param string $css
233
	 * @param string $webDir
234
	 * @return string
235
	 */
236
	private function rebaseUrls(string $css, string $webDir): string {
237
		$re    = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
238
		$subst = 'url(\'' . $webDir . '/$1\')';
239
240
		return preg_replace($re, $subst, $css);
241
	}
242
243
	/**
244
	 * Remove all matches from the $rule regex
245
	 *
246
	 * @param string $css string to parse
247
	 * @return string
248
	 */
249
	private function invertSvgIconsColor(string $css) {
250
		return str_replace(['/000', '/fff', '/***'], ['/***', '/000', '/fff'], $css);
251
	}
252
253
	/**
254
	 * @return string SCSS code for variables from OC_Defaults
255
	 */
256 View Code Duplication
	private function getInjectedVariables(): string {
257
		if ($this->injectedVariables !== null) {
258
			return $this->injectedVariables;
259
		}
260
		$variables = '';
261
		foreach ($this->defaults->getScssVariables() as $key => $value) {
262
			$variables .= '$' . $key . ': ' . $value . ';';
263
		}
264
265
		// check for valid variables / otherwise fall back to defaults
266
		try {
267
			$scss = new Compiler();
268
			$scss->compile($variables);
269
			$this->injectedVariables = $variables;
270
		} catch (ParserException $e) {
0 ignored issues
show
Bug introduced by
The class Leafo\ScssPhp\Exception\ParserException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
271
			$this->logger->error($e, ['app' => 'core']);
272
		}
273
		return $variables;
274
	}
275
}
276