Completed
Push — master ( 8032e3...4751f1 )
by Morris
15:26
created

AccessibilityController::invertSvgIconsColor()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
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\Utility\ITimeFactory;
32
use OCP\App\IAppManager;
33
use OCP\IConfig;
34
use OCP\ILogger;
35
use OCP\IRequest;
36
use OCP\IURLGenerator;
37
use OCP\IUserManager;
38
use OCP\IUserSession;
39
use OC\Template\IconsCacher;
40
41
class AccessibilityController extends Controller {
42
43
	/** @var string */
44
	protected $appName;
45
46
	/** @var string */
47
	protected $serverRoot;
48
49
	/** @var IConfig */
50
	private $config;
51
52
	/** @var IUserManager */
53
	private $userManager;
54
55
	/** @var ILogger */
56
	private $logger;
57
58
	/** @var IURLGenerator */
59
	private $urlGenerator;
60
61
	/** @var ITimeFactory */
62
	protected $timeFactory;
63
64
	/** @var IUserSession */
65
	private $userSession;
66
67
	/** @var IAppManager */
68
	private $appManager;
69
70
	/** @var IconsCacher */
71
	protected $iconsCacher;
72
73
	/**
74
	 * Account constructor.
75
	 *
76
	 * @param string $appName
77
	 * @param IRequest $request
78
	 * @param IConfig $config
79
	 * @param IUserManager $userManager
80
	 * @param ILogger $logger
81
	 * @param IURLGenerator $urlGenerator
82
	 * @param ITimeFactory $timeFactory
83
	 * @param IUserSession $userSession
84
	 * @param IAppManager $appManager
85
	 */
86
	public function __construct(string $appName,
87
								IRequest $request,
88
								IConfig $config,
89
								IUserManager $userManager,
90
								ILogger $logger,
91
								IURLGenerator $urlGenerator,
92
								ITimeFactory $timeFactory,
93
								IUserSession $userSession,
94
								IAppManager $appManager,
95
								IconsCacher $iconsCacher) {
96
		parent::__construct($appName, $request);
97
		$this->appName      = $appName;
98
		$this->config       = $config;
99
		$this->userManager  = $userManager;
100
		$this->logger       = $logger;
101
		$this->urlGenerator = $urlGenerator;
102
		$this->timeFactory  = $timeFactory;
103
		$this->userSession  = $userSession;
104
		$this->appManager   = $appManager;
105
		$this->iconsCacher  = $iconsCacher;
106
107
		$this->serverRoot = \OC::$SERVERROOT;
108
		$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...
109
	}
110
111
	/**
112
	 * @NoAdminRequired
113
	 * @NoCSRFRequired
114
	 *
115
	 * @return DataDisplayResponse
116
	 */
117
	public function getCss(): DataDisplayResponse {
118
		$css        = '';
119
		$imports    = '';
120
		$userValues = $this->getUserValues();
121
122
		foreach ($userValues as $key => $scssFile) {
123
			if ($scssFile !== false) {
124
				$imports .= '@import "' . $scssFile . '";';
125
			}
126
		}
127
128
		if ($imports !== '') {
129
			$scss = new Compiler();
130
			$scss->setImportPaths([
131
				$this->appRoot . '/css/',
132
				$this->serverRoot . '/core/css/'
133
			]);
134
135
			// Continue after throw
136
			$scss->setIgnoreErrors(true);
137
			$scss->setFormatter(Crunched::class);
138
139
			// Import theme, variables and compile css4 variables
140
			try {
141
				$css .= $scss->compile(
142
					$imports .
143
					'@import "variables.scss";' .
144
					'@import "css-variables.scss";'
145
				);
146
			} 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...
147
				$this->logger->error($e->getMessage(), ['app' => 'core']);
148
			}
149
		}
150
151
		// We don't want to override vars with url since path is different
152
		$css = $this->filterOutRule('/--[a-z-:]+url\([^;]+\)/mi', $css);
153
154
		// Rebase all urls
155
		$appWebRoot = substr($this->appRoot, strlen($this->serverRoot) - strlen(\OC::$WEBROOT));
156
		$css        = $this->rebaseUrls($css, $appWebRoot . '/css');
157
158
		if (in_array('themedark', $userValues) && $this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
159
			$iconsCss = $this->invertSvgIconsColor($this->iconsCacher->getCachedCSS()->getContent());
160
			$css = $css . $iconsCss;
161
		}
162
163
		$response = new DataDisplayResponse($css, Http::STATUS_OK, ['Content-Type' => 'text/css']);
164
165
		// Set cache control
166
		$ttl = 31536000;
167
		$response->addHeader('Cache-Control', 'max-age=' . $ttl . ', immutable');
168
		$expires = new \DateTime();
169
		$expires->setTimestamp($this->timeFactory->getTime());
170
		$expires->add(new \DateInterval('PT' . $ttl . 'S'));
171
		$response->addHeader('Expires', $expires->format(\DateTime::RFC1123));
172
		$response->addHeader('Pragma', 'cache');
173
174
		return $response;
175
	}
176
177
	/**
178
	 * Return an array with the user theme & font settings
179
	 *
180
	 * @return array
181
	 */
182
	private function getUserValues(): array{
183
		$userTheme = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'theme', false);
184
		$userFont  = $this->config->getUserValue($this->userSession->getUser()->getUID(), $this->appName, 'font', false);
185
186
		return [$userTheme, $userFont];
187
	}
188
189
	/**
190
	 * Remove all matches from the $rule regex
191
	 *
192
	 * @param string $rule regex to match
193
	 * @param string $css string to parse
194
	 * @return string
195
	 */
196
	private function filterOutRule(string $rule, string $css): string {
197
		return preg_replace($rule, '', $css);
198
	}
199
200
	/**
201
	 * Add the correct uri prefix to make uri valid again
202
	 *
203
	 * @param string $css
204
	 * @param string $webDir
205
	 * @return string
206
	 */
207
	private function rebaseUrls(string $css, string $webDir): string {
208
		$re    = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
209
		$subst = 'url(\'' . $webDir . '/$1\')';
210
211
		return preg_replace($re, $subst, $css);
212
	}
213
214
	/**
215
	 * Remove all matches from the $rule regex
216
	 *
217
	 * @param string $css string to parse
218
	 * @return string
219
	 */
220
	private function invertSvgIconsColor(string $css) {
221
		return str_replace(['/000', '/fff', '/***'], ['/***', '/000', '/fff'], $css);
222
	}
223
}
224