Passed
Push — master ( 1d0db5...d25e53 )
by John
17:58 queued 04:54
created
lib/private/Template/SCSSCacher.php 2 patches
Indentation   +485 added lines, -485 removed lines patch added patch discarded remove patch
@@ -52,492 +52,492 @@
 block discarded – undo
52 52
 
53 53
 class SCSSCacher {
54 54
 
55
-	/** @var ILogger */
56
-	protected $logger;
57
-
58
-	/** @var IAppData */
59
-	protected $appData;
60
-
61
-	/** @var IURLGenerator */
62
-	protected $urlGenerator;
63
-
64
-	/** @var IConfig */
65
-	protected $config;
66
-
67
-	/** @var \OC_Defaults */
68
-	private $defaults;
69
-
70
-	/** @var string */
71
-	protected $serverRoot;
72
-
73
-	/** @var ICache */
74
-	protected $depsCache;
75
-
76
-	/** @var null|string */
77
-	private $injectedVariables;
78
-
79
-	/** @var ICacheFactory */
80
-	private $cacheFactory;
81
-
82
-	/** @var IconsCacher */
83
-	private $iconsCacher;
84
-
85
-	/** @var ICache */
86
-	private $isCachedCache;
87
-
88
-	/** @var ITimeFactory */
89
-	private $timeFactory;
90
-
91
-	/** @var IMemcache */
92
-	private $lockingCache;
93
-	/** @var AppConfig */
94
-	private $appConfig;
95
-
96
-	/**
97
-	 * @param ILogger $logger
98
-	 * @param Factory $appDataFactory
99
-	 * @param IURLGenerator $urlGenerator
100
-	 * @param IConfig $config
101
-	 * @param \OC_Defaults $defaults
102
-	 * @param string $serverRoot
103
-	 * @param ICacheFactory $cacheFactory
104
-	 * @param IconsCacher $iconsCacher
105
-	 * @param ITimeFactory $timeFactory
106
-	 */
107
-	public function __construct(ILogger $logger,
108
-								Factory $appDataFactory,
109
-								IURLGenerator $urlGenerator,
110
-								IConfig $config,
111
-								\OC_Defaults $defaults,
112
-								$serverRoot,
113
-								ICacheFactory $cacheFactory,
114
-								IconsCacher $iconsCacher,
115
-								ITimeFactory $timeFactory,
116
-								AppConfig $appConfig) {
117
-		$this->logger = $logger;
118
-		$this->appData = $appDataFactory->get('css');
119
-		$this->urlGenerator = $urlGenerator;
120
-		$this->config = $config;
121
-		$this->defaults = $defaults;
122
-		$this->serverRoot = $serverRoot;
123
-		$this->cacheFactory = $cacheFactory;
124
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
125
-		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
126
-		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
127
-		if (!($lockingCache instanceof IMemcache)) {
128
-			$lockingCache = new NullCache();
129
-		}
130
-		$this->lockingCache = $lockingCache;
131
-		$this->iconsCacher = $iconsCacher;
132
-		$this->timeFactory = $timeFactory;
133
-		$this->appConfig = $appConfig;
134
-	}
135
-
136
-	/**
137
-	 * Process the caching process if needed
138
-	 *
139
-	 * @param string $root Root path to the nextcloud installation
140
-	 * @param string $file
141
-	 * @param string $app The app name
142
-	 * @return boolean
143
-	 * @throws NotPermittedException
144
-	 */
145
-	public function process(string $root, string $file, string $app): bool {
146
-		$path = explode('/', $root . '/' . $file);
147
-
148
-		$fileNameSCSS = array_pop($path);
149
-		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
150
-
151
-		$path = implode('/', $path);
152
-		$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
153
-
154
-		$this->logger->debug('SCSSCacher::process ordinary check follows', ['app' => 'scss_cacher']);
155
-		if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
156
-			// Inject icons vars css if any
157
-			return $this->injectCssVariablesIfAny();
158
-		}
159
-
160
-		try {
161
-			$folder = $this->appData->getFolder($app);
162
-		} catch (NotFoundException $e) {
163
-			// creating css appdata folder
164
-			$folder = $this->appData->newFolder($app);
165
-		}
166
-
167
-		$lockKey = $webDir . '/' . $fileNameSCSS;
168
-
169
-		if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
170
-			$this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
171
-			$retry = 0;
172
-			sleep(1);
173
-			while ($retry < 10) {
174
-				$this->appConfig->clearCachedConfig();
175
-				$this->logger->debug('SCSSCacher::process check in while loop follows', ['app' => 'scss_cacher']);
176
-				if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
177
-					// Inject icons vars css if any
178
-					$this->logger->debug("SCSSCacher::process cached file for app '$app' and file '$fileNameCSS' is now available after $retry s. Moving on...", ['app' => 'scss_cacher']);
179
-					return $this->injectCssVariablesIfAny();
180
-				}
181
-				sleep(1);
182
-				$retry++;
183
-			}
184
-			$this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
185
-			return false;
186
-		}
187
-
188
-		$this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
189
-		try {
190
-			$cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
191
-		} catch (\Exception $e) {
192
-			$this->lockingCache->remove($lockKey);
193
-			throw $e;
194
-		}
195
-
196
-		// Cleaning lock
197
-		$this->lockingCache->remove($lockKey);
198
-		$this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
199
-
200
-		// Inject icons vars css if any
201
-		if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
202
-			$this->iconsCacher->injectCss();
203
-		}
204
-
205
-		return $cached;
206
-	}
207
-
208
-	/**
209
-	 * @param $appName
210
-	 * @param $fileName
211
-	 * @return ISimpleFile
212
-	 */
213
-	public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
214
-		$folder = $this->appData->getFolder($appName);
215
-		$cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
216
-
217
-		return $folder->getFile($cachedFileName);
218
-	}
219
-
220
-	/**
221
-	 * Check if the file is cached or not
222
-	 * @param string $fileNameCSS
223
-	 * @param string $app
224
-	 * @return boolean
225
-	 */
226
-	private function isCached(string $fileNameCSS, string $app) {
227
-		$key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
228
-
229
-		// If the file mtime is more recent than our cached one,
230
-		// let's consider the file is properly cached
231
-		if ($cacheValue = $this->isCachedCache->get($key)) {
232
-			if ($cacheValue > $this->timeFactory->getTime()) {
233
-				return true;
234
-			}
235
-		}
236
-		$this->logger->debug("SCSSCacher::isCached $fileNameCSS isCachedCache is expired or unset", ['app' => 'scss_cacher']);
237
-
238
-		// Creating file cache if none for further checks
239
-		try {
240
-			$folder = $this->appData->getFolder($app);
241
-		} catch (NotFoundException $e) {
242
-			$this->logger->debug("SCSSCacher::isCached app data folder for $app could not be fetched", ['app' => 'scss_cacher']);
243
-			return false;
244
-		}
245
-
246
-		// Checking if file size is coherent
247
-		// and if one of the css dependency changed
248
-		try {
249
-			$cachedFile = $folder->getFile($fileNameCSS);
250
-			if ($cachedFile->getSize() > 0) {
251
-				$depFileName = $fileNameCSS . '.deps';
252
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
253
-				if ($deps === null) {
254
-					$depFile = $folder->getFile($depFileName);
255
-					$deps = $depFile->getContent();
256
-					// Set to memcache for next run
257
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
258
-				}
259
-				$deps = json_decode($deps, true);
260
-
261
-				foreach ((array) $deps as $file => $mtime) {
262
-					if (!file_exists($file) || filemtime($file) > $mtime) {
263
-						$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached due to deps file $file", ['app' => 'scss_cacher']);
264
-						return false;
265
-					}
266
-				}
267
-
268
-				$this->logger->debug("SCSSCacher::isCached $fileNameCSS dependencies successfully cached for 5 minutes", ['app' => 'scss_cacher']);
269
-				// It would probably make sense to adjust this timeout to something higher and see if that has some effect then
270
-				$this->isCachedCache->set($key, $this->timeFactory->getTime() + 5 * 60);
271
-				return true;
272
-			}
273
-			$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
274
-			return false;
275
-		} catch (NotFoundException $e) {
276
-			$this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
277
-			return false;
278
-		}
279
-	}
280
-
281
-	/**
282
-	 * Check if the variables file has changed
283
-	 * @return bool
284
-	 */
285
-	private function variablesChanged(): bool {
286
-		$cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
287
-		$injectedVariables = $this->getInjectedVariables($cachedVariables);
288
-		if ($cachedVariables !== md5($injectedVariables)) {
289
-			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
290
-			$this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
291
-			$this->resetCache();
292
-			return true;
293
-		}
294
-		return false;
295
-	}
296
-
297
-	/**
298
-	 * Cache the file with AppData
299
-	 *
300
-	 * @param string $path
301
-	 * @param string $fileNameCSS
302
-	 * @param string $fileNameSCSS
303
-	 * @param ISimpleFolder $folder
304
-	 * @param string $webDir
305
-	 * @return boolean
306
-	 * @throws NotPermittedException
307
-	 */
308
-	private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
309
-		$scss = new Compiler();
310
-		$scss->setImportPaths([
311
-			$path,
312
-			$this->serverRoot . '/core/css/'
313
-		]);
314
-
315
-		// Continue after throw
316
-		$scss->setIgnoreErrors(true);
317
-		if ($this->config->getSystemValue('debug')) {
318
-			// Debug mode
319
-			$scss->setFormatter(Expanded::class);
320
-			$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
321
-		} else {
322
-			// Compression
323
-			$scss->setFormatter(Crunched::class);
324
-		}
325
-
326
-		try {
327
-			$cachedfile = $folder->getFile($fileNameCSS);
328
-		} catch (NotFoundException $e) {
329
-			$cachedfile = $folder->newFile($fileNameCSS);
330
-		}
331
-
332
-		$depFileName = $fileNameCSS . '.deps';
333
-		try {
334
-			$depFile = $folder->getFile($depFileName);
335
-		} catch (NotFoundException $e) {
336
-			$depFile = $folder->newFile($depFileName);
337
-		}
338
-
339
-		// Compile
340
-		try {
341
-			$compiledScss = $scss->compile(
342
-				'$webroot: \'' . $this->getRoutePrefix() . '\';' .
343
-				$this->getInjectedVariables() .
344
-				'@import "variables.scss";' .
345
-				'@import "functions.scss";' .
346
-				'@import "' . $fileNameSCSS . '";');
347
-		} catch (ParserException $e) {
348
-			$this->logger->logException($e, ['app' => 'scss_cacher']);
349
-
350
-			return false;
351
-		}
352
-
353
-		// Parse Icons and create related css variables
354
-		$compiledScss = $this->iconsCacher->setIconsCss($compiledScss);
355
-
356
-		// Gzip file
357
-		try {
358
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
359
-		} catch (NotFoundException $e) {
360
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
361
-		}
362
-
363
-		try {
364
-			$data = $this->rebaseUrls($compiledScss, $webDir);
365
-			$cachedfile->putContent($data);
366
-			$deps = json_encode($scss->getParsedFiles());
367
-			$depFile->putContent($deps);
368
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
369
-			$gzipFile->putContent(gzencode($data, 9));
370
-			$this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
371
-
372
-			return true;
373
-		} catch (NotPermittedException $e) {
374
-			$this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
375
-
376
-			return false;
377
-		}
378
-	}
379
-
380
-	/**
381
-	 * Reset scss cache by deleting all generated css files
382
-	 * We need to regenerate all files when variables change
383
-	 */
384
-	public function resetCache() {
385
-		$this->logger->debug('SCSSCacher::resetCache', ['app' => 'scss_cacher']);
386
-		if (!$this->lockingCache->add('resetCache', 'locked!', 120)) {
387
-			$this->logger->debug('SCSSCacher::resetCache Locked', ['app' => 'scss_cacher']);
388
-			return;
389
-		}
390
-		$this->logger->debug('SCSSCacher::resetCache Lock acquired', ['app' => 'scss_cacher']);
391
-		$this->injectedVariables = null;
392
-
393
-		// do not clear locks
394
-		$this->cacheFactory->createDistributed('SCSS-deps-')->clear();
395
-		$this->cacheFactory->createDistributed('SCSS-cached-')->clear();
396
-
397
-		$appDirectory = $this->appData->getDirectoryListing();
398
-		foreach ($appDirectory as $folder) {
399
-			foreach ($folder->getDirectoryListing() as $file) {
400
-				try {
401
-					$file->delete();
402
-				} catch (NotPermittedException $e) {
403
-					$this->logger->logException($e, ['message' => 'SCSSCacher::resetCache unable to delete file: ' . $file->getName(), 'app' => 'scss_cacher']);
404
-				}
405
-			}
406
-		}
407
-		$this->logger->debug('SCSSCacher::resetCache css cache cleared!', ['app' => 'scss_cacher']);
408
-		$this->lockingCache->remove('resetCache');
409
-		$this->logger->debug('SCSSCacher::resetCache Locking removed', ['app' => 'scss_cacher']);
410
-	}
411
-
412
-	/**
413
-	 * @return string SCSS code for variables from OC_Defaults
414
-	 */
415
-	private function getInjectedVariables(string $cache = ''): string {
416
-		if ($this->injectedVariables !== null) {
417
-			return $this->injectedVariables;
418
-		}
419
-		$variables = '';
420
-		foreach ($this->defaults->getScssVariables() as $key => $value) {
421
-			$variables .= '$' . $key . ': ' . $value . ' !default;';
422
-		}
423
-
424
-		/*
55
+    /** @var ILogger */
56
+    protected $logger;
57
+
58
+    /** @var IAppData */
59
+    protected $appData;
60
+
61
+    /** @var IURLGenerator */
62
+    protected $urlGenerator;
63
+
64
+    /** @var IConfig */
65
+    protected $config;
66
+
67
+    /** @var \OC_Defaults */
68
+    private $defaults;
69
+
70
+    /** @var string */
71
+    protected $serverRoot;
72
+
73
+    /** @var ICache */
74
+    protected $depsCache;
75
+
76
+    /** @var null|string */
77
+    private $injectedVariables;
78
+
79
+    /** @var ICacheFactory */
80
+    private $cacheFactory;
81
+
82
+    /** @var IconsCacher */
83
+    private $iconsCacher;
84
+
85
+    /** @var ICache */
86
+    private $isCachedCache;
87
+
88
+    /** @var ITimeFactory */
89
+    private $timeFactory;
90
+
91
+    /** @var IMemcache */
92
+    private $lockingCache;
93
+    /** @var AppConfig */
94
+    private $appConfig;
95
+
96
+    /**
97
+     * @param ILogger $logger
98
+     * @param Factory $appDataFactory
99
+     * @param IURLGenerator $urlGenerator
100
+     * @param IConfig $config
101
+     * @param \OC_Defaults $defaults
102
+     * @param string $serverRoot
103
+     * @param ICacheFactory $cacheFactory
104
+     * @param IconsCacher $iconsCacher
105
+     * @param ITimeFactory $timeFactory
106
+     */
107
+    public function __construct(ILogger $logger,
108
+                                Factory $appDataFactory,
109
+                                IURLGenerator $urlGenerator,
110
+                                IConfig $config,
111
+                                \OC_Defaults $defaults,
112
+                                $serverRoot,
113
+                                ICacheFactory $cacheFactory,
114
+                                IconsCacher $iconsCacher,
115
+                                ITimeFactory $timeFactory,
116
+                                AppConfig $appConfig) {
117
+        $this->logger = $logger;
118
+        $this->appData = $appDataFactory->get('css');
119
+        $this->urlGenerator = $urlGenerator;
120
+        $this->config = $config;
121
+        $this->defaults = $defaults;
122
+        $this->serverRoot = $serverRoot;
123
+        $this->cacheFactory = $cacheFactory;
124
+        $this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
125
+        $this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
126
+        $lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
127
+        if (!($lockingCache instanceof IMemcache)) {
128
+            $lockingCache = new NullCache();
129
+        }
130
+        $this->lockingCache = $lockingCache;
131
+        $this->iconsCacher = $iconsCacher;
132
+        $this->timeFactory = $timeFactory;
133
+        $this->appConfig = $appConfig;
134
+    }
135
+
136
+    /**
137
+     * Process the caching process if needed
138
+     *
139
+     * @param string $root Root path to the nextcloud installation
140
+     * @param string $file
141
+     * @param string $app The app name
142
+     * @return boolean
143
+     * @throws NotPermittedException
144
+     */
145
+    public function process(string $root, string $file, string $app): bool {
146
+        $path = explode('/', $root . '/' . $file);
147
+
148
+        $fileNameSCSS = array_pop($path);
149
+        $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
150
+
151
+        $path = implode('/', $path);
152
+        $webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
153
+
154
+        $this->logger->debug('SCSSCacher::process ordinary check follows', ['app' => 'scss_cacher']);
155
+        if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
156
+            // Inject icons vars css if any
157
+            return $this->injectCssVariablesIfAny();
158
+        }
159
+
160
+        try {
161
+            $folder = $this->appData->getFolder($app);
162
+        } catch (NotFoundException $e) {
163
+            // creating css appdata folder
164
+            $folder = $this->appData->newFolder($app);
165
+        }
166
+
167
+        $lockKey = $webDir . '/' . $fileNameSCSS;
168
+
169
+        if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
170
+            $this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
171
+            $retry = 0;
172
+            sleep(1);
173
+            while ($retry < 10) {
174
+                $this->appConfig->clearCachedConfig();
175
+                $this->logger->debug('SCSSCacher::process check in while loop follows', ['app' => 'scss_cacher']);
176
+                if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $app)) {
177
+                    // Inject icons vars css if any
178
+                    $this->logger->debug("SCSSCacher::process cached file for app '$app' and file '$fileNameCSS' is now available after $retry s. Moving on...", ['app' => 'scss_cacher']);
179
+                    return $this->injectCssVariablesIfAny();
180
+                }
181
+                sleep(1);
182
+                $retry++;
183
+            }
184
+            $this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
185
+            return false;
186
+        }
187
+
188
+        $this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
189
+        try {
190
+            $cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
191
+        } catch (\Exception $e) {
192
+            $this->lockingCache->remove($lockKey);
193
+            throw $e;
194
+        }
195
+
196
+        // Cleaning lock
197
+        $this->lockingCache->remove($lockKey);
198
+        $this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
199
+
200
+        // Inject icons vars css if any
201
+        if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
202
+            $this->iconsCacher->injectCss();
203
+        }
204
+
205
+        return $cached;
206
+    }
207
+
208
+    /**
209
+     * @param $appName
210
+     * @param $fileName
211
+     * @return ISimpleFile
212
+     */
213
+    public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
214
+        $folder = $this->appData->getFolder($appName);
215
+        $cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
216
+
217
+        return $folder->getFile($cachedFileName);
218
+    }
219
+
220
+    /**
221
+     * Check if the file is cached or not
222
+     * @param string $fileNameCSS
223
+     * @param string $app
224
+     * @return boolean
225
+     */
226
+    private function isCached(string $fileNameCSS, string $app) {
227
+        $key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
228
+
229
+        // If the file mtime is more recent than our cached one,
230
+        // let's consider the file is properly cached
231
+        if ($cacheValue = $this->isCachedCache->get($key)) {
232
+            if ($cacheValue > $this->timeFactory->getTime()) {
233
+                return true;
234
+            }
235
+        }
236
+        $this->logger->debug("SCSSCacher::isCached $fileNameCSS isCachedCache is expired or unset", ['app' => 'scss_cacher']);
237
+
238
+        // Creating file cache if none for further checks
239
+        try {
240
+            $folder = $this->appData->getFolder($app);
241
+        } catch (NotFoundException $e) {
242
+            $this->logger->debug("SCSSCacher::isCached app data folder for $app could not be fetched", ['app' => 'scss_cacher']);
243
+            return false;
244
+        }
245
+
246
+        // Checking if file size is coherent
247
+        // and if one of the css dependency changed
248
+        try {
249
+            $cachedFile = $folder->getFile($fileNameCSS);
250
+            if ($cachedFile->getSize() > 0) {
251
+                $depFileName = $fileNameCSS . '.deps';
252
+                $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
253
+                if ($deps === null) {
254
+                    $depFile = $folder->getFile($depFileName);
255
+                    $deps = $depFile->getContent();
256
+                    // Set to memcache for next run
257
+                    $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
258
+                }
259
+                $deps = json_decode($deps, true);
260
+
261
+                foreach ((array) $deps as $file => $mtime) {
262
+                    if (!file_exists($file) || filemtime($file) > $mtime) {
263
+                        $this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached due to deps file $file", ['app' => 'scss_cacher']);
264
+                        return false;
265
+                    }
266
+                }
267
+
268
+                $this->logger->debug("SCSSCacher::isCached $fileNameCSS dependencies successfully cached for 5 minutes", ['app' => 'scss_cacher']);
269
+                // It would probably make sense to adjust this timeout to something higher and see if that has some effect then
270
+                $this->isCachedCache->set($key, $this->timeFactory->getTime() + 5 * 60);
271
+                return true;
272
+            }
273
+            $this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
274
+            return false;
275
+        } catch (NotFoundException $e) {
276
+            $this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
277
+            return false;
278
+        }
279
+    }
280
+
281
+    /**
282
+     * Check if the variables file has changed
283
+     * @return bool
284
+     */
285
+    private function variablesChanged(): bool {
286
+        $cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
287
+        $injectedVariables = $this->getInjectedVariables($cachedVariables);
288
+        if ($cachedVariables !== md5($injectedVariables)) {
289
+            $this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
290
+            $this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
291
+            $this->resetCache();
292
+            return true;
293
+        }
294
+        return false;
295
+    }
296
+
297
+    /**
298
+     * Cache the file with AppData
299
+     *
300
+     * @param string $path
301
+     * @param string $fileNameCSS
302
+     * @param string $fileNameSCSS
303
+     * @param ISimpleFolder $folder
304
+     * @param string $webDir
305
+     * @return boolean
306
+     * @throws NotPermittedException
307
+     */
308
+    private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
309
+        $scss = new Compiler();
310
+        $scss->setImportPaths([
311
+            $path,
312
+            $this->serverRoot . '/core/css/'
313
+        ]);
314
+
315
+        // Continue after throw
316
+        $scss->setIgnoreErrors(true);
317
+        if ($this->config->getSystemValue('debug')) {
318
+            // Debug mode
319
+            $scss->setFormatter(Expanded::class);
320
+            $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
321
+        } else {
322
+            // Compression
323
+            $scss->setFormatter(Crunched::class);
324
+        }
325
+
326
+        try {
327
+            $cachedfile = $folder->getFile($fileNameCSS);
328
+        } catch (NotFoundException $e) {
329
+            $cachedfile = $folder->newFile($fileNameCSS);
330
+        }
331
+
332
+        $depFileName = $fileNameCSS . '.deps';
333
+        try {
334
+            $depFile = $folder->getFile($depFileName);
335
+        } catch (NotFoundException $e) {
336
+            $depFile = $folder->newFile($depFileName);
337
+        }
338
+
339
+        // Compile
340
+        try {
341
+            $compiledScss = $scss->compile(
342
+                '$webroot: \'' . $this->getRoutePrefix() . '\';' .
343
+                $this->getInjectedVariables() .
344
+                '@import "variables.scss";' .
345
+                '@import "functions.scss";' .
346
+                '@import "' . $fileNameSCSS . '";');
347
+        } catch (ParserException $e) {
348
+            $this->logger->logException($e, ['app' => 'scss_cacher']);
349
+
350
+            return false;
351
+        }
352
+
353
+        // Parse Icons and create related css variables
354
+        $compiledScss = $this->iconsCacher->setIconsCss($compiledScss);
355
+
356
+        // Gzip file
357
+        try {
358
+            $gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
359
+        } catch (NotFoundException $e) {
360
+            $gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
361
+        }
362
+
363
+        try {
364
+            $data = $this->rebaseUrls($compiledScss, $webDir);
365
+            $cachedfile->putContent($data);
366
+            $deps = json_encode($scss->getParsedFiles());
367
+            $depFile->putContent($deps);
368
+            $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
369
+            $gzipFile->putContent(gzencode($data, 9));
370
+            $this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
371
+
372
+            return true;
373
+        } catch (NotPermittedException $e) {
374
+            $this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
375
+
376
+            return false;
377
+        }
378
+    }
379
+
380
+    /**
381
+     * Reset scss cache by deleting all generated css files
382
+     * We need to regenerate all files when variables change
383
+     */
384
+    public function resetCache() {
385
+        $this->logger->debug('SCSSCacher::resetCache', ['app' => 'scss_cacher']);
386
+        if (!$this->lockingCache->add('resetCache', 'locked!', 120)) {
387
+            $this->logger->debug('SCSSCacher::resetCache Locked', ['app' => 'scss_cacher']);
388
+            return;
389
+        }
390
+        $this->logger->debug('SCSSCacher::resetCache Lock acquired', ['app' => 'scss_cacher']);
391
+        $this->injectedVariables = null;
392
+
393
+        // do not clear locks
394
+        $this->cacheFactory->createDistributed('SCSS-deps-')->clear();
395
+        $this->cacheFactory->createDistributed('SCSS-cached-')->clear();
396
+
397
+        $appDirectory = $this->appData->getDirectoryListing();
398
+        foreach ($appDirectory as $folder) {
399
+            foreach ($folder->getDirectoryListing() as $file) {
400
+                try {
401
+                    $file->delete();
402
+                } catch (NotPermittedException $e) {
403
+                    $this->logger->logException($e, ['message' => 'SCSSCacher::resetCache unable to delete file: ' . $file->getName(), 'app' => 'scss_cacher']);
404
+                }
405
+            }
406
+        }
407
+        $this->logger->debug('SCSSCacher::resetCache css cache cleared!', ['app' => 'scss_cacher']);
408
+        $this->lockingCache->remove('resetCache');
409
+        $this->logger->debug('SCSSCacher::resetCache Locking removed', ['app' => 'scss_cacher']);
410
+    }
411
+
412
+    /**
413
+     * @return string SCSS code for variables from OC_Defaults
414
+     */
415
+    private function getInjectedVariables(string $cache = ''): string {
416
+        if ($this->injectedVariables !== null) {
417
+            return $this->injectedVariables;
418
+        }
419
+        $variables = '';
420
+        foreach ($this->defaults->getScssVariables() as $key => $value) {
421
+            $variables .= '$' . $key . ': ' . $value . ' !default;';
422
+        }
423
+
424
+        /*
425 425
 		 * If we are trying to return the same variables as that are cached
426 426
 		 * Then there is no need to do the compile step
427 427
 		 */
428
-		if ($cache === md5($variables)) {
429
-			$this->injectedVariables = $variables;
430
-			return $variables;
431
-		}
432
-
433
-		// check for valid variables / otherwise fall back to defaults
434
-		try {
435
-			$scss = new Compiler();
436
-			$scss->compile($variables);
437
-			$this->injectedVariables = $variables;
438
-		} catch (ParserException $e) {
439
-			$this->logger->logException($e, ['app' => 'scss_cacher']);
440
-		}
441
-
442
-		return $variables;
443
-	}
444
-
445
-	/**
446
-	 * Add the correct uri prefix to make uri valid again
447
-	 * @param string $css
448
-	 * @param string $webDir
449
-	 * @return string
450
-	 */
451
-	private function rebaseUrls(string $css, string $webDir): string {
452
-		$re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
453
-		$subst = 'url(\'' . $webDir . '/$1\')';
454
-
455
-		return preg_replace($re, $subst, $css);
456
-	}
457
-
458
-	/**
459
-	 * Return the cached css file uri
460
-	 * @param string $appName the app name
461
-	 * @param string $fileName
462
-	 * @return string
463
-	 */
464
-	public function getCachedSCSS(string $appName, string $fileName): string {
465
-		$tmpfileLoc = explode('/', $fileName);
466
-		$fileName = array_pop($tmpfileLoc);
467
-		$fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
468
-
469
-		return substr($this->urlGenerator->linkToRoute('core.Css.getCss', [
470
-			'fileName' => $fileName,
471
-			'appName' => $appName,
472
-			'v' => $this->config->getAppValue('core', 'theming.variables', '0')
473
-		]), \strlen(\OC::$WEBROOT) + 1);
474
-	}
475
-
476
-	/**
477
-	 * Prepend hashed base url to the css file
478
-	 * @param string $cssFile
479
-	 * @return string
480
-	 */
481
-	private function prependBaseurlPrefix(string $cssFile): string {
482
-		return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
483
-	}
484
-
485
-	private function getRoutePrefix() {
486
-		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
487
-		$prefix = \OC::$WEBROOT . '/index.php';
488
-		if ($frontControllerActive) {
489
-			$prefix = \OC::$WEBROOT;
490
-		}
491
-		return $prefix;
492
-	}
493
-
494
-	/**
495
-	 * Prepend hashed app version hash
496
-	 * @param string $cssFile
497
-	 * @param string $appId
498
-	 * @return string
499
-	 */
500
-	private function prependVersionPrefix(string $cssFile, string $appId): string {
501
-		$appVersion = \OC_App::getAppVersion($appId);
502
-		if ($appVersion !== '0') {
503
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
504
-		}
505
-		$coreVersion = \OC_Util::getVersionString();
506
-
507
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
508
-	}
509
-
510
-	/**
511
-	 * Get WebDir root
512
-	 * @param string $path the css file path
513
-	 * @param string $appName the app name
514
-	 * @param string $serverRoot the server root path
515
-	 * @param string $webRoot the nextcloud installation root path
516
-	 * @return string the webDir
517
-	 */
518
-	private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
519
-		// Detect if path is within server root AND if path is within an app path
520
-		if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
521
-			// Get the file path within the app directory
522
-			$appDirectoryPath = explode($appName, $path)[1];
523
-			// Remove the webroot
524
-
525
-			return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
526
-		}
527
-
528
-		return $webRoot . substr($path, strlen($serverRoot));
529
-	}
530
-
531
-	/**
532
-	 * Add the icons css cache in the header if needed
533
-	 *
534
-	 * @return boolean true
535
-	 */
536
-	private function injectCssVariablesIfAny() {
537
-		// Inject icons vars css if any
538
-		if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
539
-			$this->iconsCacher->injectCss();
540
-		}
541
-		return true;
542
-	}
428
+        if ($cache === md5($variables)) {
429
+            $this->injectedVariables = $variables;
430
+            return $variables;
431
+        }
432
+
433
+        // check for valid variables / otherwise fall back to defaults
434
+        try {
435
+            $scss = new Compiler();
436
+            $scss->compile($variables);
437
+            $this->injectedVariables = $variables;
438
+        } catch (ParserException $e) {
439
+            $this->logger->logException($e, ['app' => 'scss_cacher']);
440
+        }
441
+
442
+        return $variables;
443
+    }
444
+
445
+    /**
446
+     * Add the correct uri prefix to make uri valid again
447
+     * @param string $css
448
+     * @param string $webDir
449
+     * @return string
450
+     */
451
+    private function rebaseUrls(string $css, string $webDir): string {
452
+        $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
453
+        $subst = 'url(\'' . $webDir . '/$1\')';
454
+
455
+        return preg_replace($re, $subst, $css);
456
+    }
457
+
458
+    /**
459
+     * Return the cached css file uri
460
+     * @param string $appName the app name
461
+     * @param string $fileName
462
+     * @return string
463
+     */
464
+    public function getCachedSCSS(string $appName, string $fileName): string {
465
+        $tmpfileLoc = explode('/', $fileName);
466
+        $fileName = array_pop($tmpfileLoc);
467
+        $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
468
+
469
+        return substr($this->urlGenerator->linkToRoute('core.Css.getCss', [
470
+            'fileName' => $fileName,
471
+            'appName' => $appName,
472
+            'v' => $this->config->getAppValue('core', 'theming.variables', '0')
473
+        ]), \strlen(\OC::$WEBROOT) + 1);
474
+    }
475
+
476
+    /**
477
+     * Prepend hashed base url to the css file
478
+     * @param string $cssFile
479
+     * @return string
480
+     */
481
+    private function prependBaseurlPrefix(string $cssFile): string {
482
+        return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
483
+    }
484
+
485
+    private function getRoutePrefix() {
486
+        $frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
487
+        $prefix = \OC::$WEBROOT . '/index.php';
488
+        if ($frontControllerActive) {
489
+            $prefix = \OC::$WEBROOT;
490
+        }
491
+        return $prefix;
492
+    }
493
+
494
+    /**
495
+     * Prepend hashed app version hash
496
+     * @param string $cssFile
497
+     * @param string $appId
498
+     * @return string
499
+     */
500
+    private function prependVersionPrefix(string $cssFile, string $appId): string {
501
+        $appVersion = \OC_App::getAppVersion($appId);
502
+        if ($appVersion !== '0') {
503
+            return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
504
+        }
505
+        $coreVersion = \OC_Util::getVersionString();
506
+
507
+        return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
508
+    }
509
+
510
+    /**
511
+     * Get WebDir root
512
+     * @param string $path the css file path
513
+     * @param string $appName the app name
514
+     * @param string $serverRoot the server root path
515
+     * @param string $webRoot the nextcloud installation root path
516
+     * @return string the webDir
517
+     */
518
+    private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
519
+        // Detect if path is within server root AND if path is within an app path
520
+        if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
521
+            // Get the file path within the app directory
522
+            $appDirectoryPath = explode($appName, $path)[1];
523
+            // Remove the webroot
524
+
525
+            return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
526
+        }
527
+
528
+        return $webRoot . substr($path, strlen($serverRoot));
529
+    }
530
+
531
+    /**
532
+     * Add the icons css cache in the header if needed
533
+     *
534
+     * @return boolean true
535
+     */
536
+    private function injectCssVariablesIfAny() {
537
+        // Inject icons vars css if any
538
+        if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
539
+            $this->iconsCacher->injectCss();
540
+        }
541
+        return true;
542
+    }
543 543
 }
Please login to merge, or discard this patch.
Spacing   +36 added lines, -36 removed lines patch added patch discarded remove patch
@@ -121,9 +121,9 @@  discard block
 block discarded – undo
121 121
 		$this->defaults = $defaults;
122 122
 		$this->serverRoot = $serverRoot;
123 123
 		$this->cacheFactory = $cacheFactory;
124
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-' . md5($this->urlGenerator->getBaseUrl()));
125
-		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-' . md5($this->urlGenerator->getBaseUrl()));
126
-		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-' . md5($this->urlGenerator->getBaseUrl()));
124
+		$this->depsCache = $cacheFactory->createDistributed('SCSS-deps-'.md5($this->urlGenerator->getBaseUrl()));
125
+		$this->isCachedCache = $cacheFactory->createDistributed('SCSS-cached-'.md5($this->urlGenerator->getBaseUrl()));
126
+		$lockingCache = $cacheFactory->createDistributed('SCSS-locks-'.md5($this->urlGenerator->getBaseUrl()));
127 127
 		if (!($lockingCache instanceof IMemcache)) {
128 128
 			$lockingCache = new NullCache();
129 129
 		}
@@ -143,7 +143,7 @@  discard block
 block discarded – undo
143 143
 	 * @throws NotPermittedException
144 144
 	 */
145 145
 	public function process(string $root, string $file, string $app): bool {
146
-		$path = explode('/', $root . '/' . $file);
146
+		$path = explode('/', $root.'/'.$file);
147 147
 
148 148
 		$fileNameSCSS = array_pop($path);
149 149
 		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
@@ -164,10 +164,10 @@  discard block
 block discarded – undo
164 164
 			$folder = $this->appData->newFolder($app);
165 165
 		}
166 166
 
167
-		$lockKey = $webDir . '/' . $fileNameSCSS;
167
+		$lockKey = $webDir.'/'.$fileNameSCSS;
168 168
 
169 169
 		if (!$this->lockingCache->add($lockKey, 'locked!', 120)) {
170
-			$this->logger->debug('SCSSCacher::process could not get lock for ' . $lockKey . ' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
170
+			$this->logger->debug('SCSSCacher::process could not get lock for '.$lockKey.' and will wait 10 seconds for cached file to be available', ['app' => 'scss_cacher']);
171 171
 			$retry = 0;
172 172
 			sleep(1);
173 173
 			while ($retry < 10) {
@@ -181,11 +181,11 @@  discard block
 block discarded – undo
181 181
 				sleep(1);
182 182
 				$retry++;
183 183
 			}
184
-			$this->logger->debug('SCSSCacher::process Giving up scss caching for ' . $lockKey, ['app' => 'scss_cacher']);
184
+			$this->logger->debug('SCSSCacher::process Giving up scss caching for '.$lockKey, ['app' => 'scss_cacher']);
185 185
 			return false;
186 186
 		}
187 187
 
188
-		$this->logger->debug('SCSSCacher::process Lock acquired for ' . $lockKey, ['app' => 'scss_cacher']);
188
+		$this->logger->debug('SCSSCacher::process Lock acquired for '.$lockKey, ['app' => 'scss_cacher']);
189 189
 		try {
190 190
 			$cached = $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
191 191
 		} catch (\Exception $e) {
@@ -195,7 +195,7 @@  discard block
 block discarded – undo
195 195
 
196 196
 		// Cleaning lock
197 197
 		$this->lockingCache->remove($lockKey);
198
-		$this->logger->debug('SCSSCacher::process Lock removed for ' . $lockKey, ['app' => 'scss_cacher']);
198
+		$this->logger->debug('SCSSCacher::process Lock removed for '.$lockKey, ['app' => 'scss_cacher']);
199 199
 
200 200
 		// Inject icons vars css if any
201 201
 		if ($this->iconsCacher->getCachedCSS() && $this->iconsCacher->getCachedCSS()->getSize() > 0) {
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
 	 * @return boolean
225 225
 	 */
226 226
 	private function isCached(string $fileNameCSS, string $app) {
227
-		$key = $this->config->getSystemValue('version') . '/' . $app . '/' . $fileNameCSS;
227
+		$key = $this->config->getSystemValue('version').'/'.$app.'/'.$fileNameCSS;
228 228
 
229 229
 		// If the file mtime is more recent than our cached one,
230 230
 		// let's consider the file is properly cached
@@ -248,13 +248,13 @@  discard block
 block discarded – undo
248 248
 		try {
249 249
 			$cachedFile = $folder->getFile($fileNameCSS);
250 250
 			if ($cachedFile->getSize() > 0) {
251
-				$depFileName = $fileNameCSS . '.deps';
252
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
251
+				$depFileName = $fileNameCSS.'.deps';
252
+				$deps = $this->depsCache->get($folder->getName().'-'.$depFileName);
253 253
 				if ($deps === null) {
254 254
 					$depFile = $folder->getFile($depFileName);
255 255
 					$deps = $depFile->getContent();
256 256
 					// Set to memcache for next run
257
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
257
+					$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
258 258
 				}
259 259
 				$deps = json_decode($deps, true);
260 260
 
@@ -273,7 +273,7 @@  discard block
 block discarded – undo
273 273
 			$this->logger->debug("SCSSCacher::isCached $fileNameCSS is not considered as cached cacheValue: $cacheValue", ['app' => 'scss_cacher']);
274 274
 			return false;
275 275
 		} catch (NotFoundException $e) {
276
-			$this->logger->debug("SCSSCacher::isCached NotFoundException " . $e->getMessage(), ['app' => 'scss_cacher']);
276
+			$this->logger->debug("SCSSCacher::isCached NotFoundException ".$e->getMessage(), ['app' => 'scss_cacher']);
277 277
 			return false;
278 278
 		}
279 279
 	}
@@ -286,7 +286,7 @@  discard block
 block discarded – undo
286 286
 		$cachedVariables = $this->config->getAppValue('core', 'theming.variables', '');
287 287
 		$injectedVariables = $this->getInjectedVariables($cachedVariables);
288 288
 		if ($cachedVariables !== md5($injectedVariables)) {
289
-			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: ' . json_encode($this->config->getAppValue('core', 'theming.variables')) . ' currentInjectedVariables: ' . json_encode($injectedVariables), ['app' => 'scss_cacher']);
289
+			$this->logger->debug('SCSSCacher::variablesChanged storedVariables: '.json_encode($this->config->getAppValue('core', 'theming.variables')).' currentInjectedVariables: '.json_encode($injectedVariables), ['app' => 'scss_cacher']);
290 290
 			$this->config->setAppValue('core', 'theming.variables', md5($injectedVariables));
291 291
 			$this->resetCache();
292 292
 			return true;
@@ -309,7 +309,7 @@  discard block
 block discarded – undo
309 309
 		$scss = new Compiler();
310 310
 		$scss->setImportPaths([
311 311
 			$path,
312
-			$this->serverRoot . '/core/css/'
312
+			$this->serverRoot.'/core/css/'
313 313
 		]);
314 314
 
315 315
 		// Continue after throw
@@ -329,7 +329,7 @@  discard block
 block discarded – undo
329 329
 			$cachedfile = $folder->newFile($fileNameCSS);
330 330
 		}
331 331
 
332
-		$depFileName = $fileNameCSS . '.deps';
332
+		$depFileName = $fileNameCSS.'.deps';
333 333
 		try {
334 334
 			$depFile = $folder->getFile($depFileName);
335 335
 		} catch (NotFoundException $e) {
@@ -339,11 +339,11 @@  discard block
 block discarded – undo
339 339
 		// Compile
340 340
 		try {
341 341
 			$compiledScss = $scss->compile(
342
-				'$webroot: \'' . $this->getRoutePrefix() . '\';' .
343
-				$this->getInjectedVariables() .
344
-				'@import "variables.scss";' .
345
-				'@import "functions.scss";' .
346
-				'@import "' . $fileNameSCSS . '";');
342
+				'$webroot: \''.$this->getRoutePrefix().'\';'.
343
+				$this->getInjectedVariables().
344
+				'@import "variables.scss";'.
345
+				'@import "functions.scss";'.
346
+				'@import "'.$fileNameSCSS.'";');
347 347
 		} catch (ParserException $e) {
348 348
 			$this->logger->logException($e, ['app' => 'scss_cacher']);
349 349
 
@@ -355,9 +355,9 @@  discard block
 block discarded – undo
355 355
 
356 356
 		// Gzip file
357 357
 		try {
358
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
358
+			$gzipFile = $folder->getFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
359 359
 		} catch (NotFoundException $e) {
360
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
360
+			$gzipFile = $folder->newFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
361 361
 		}
362 362
 
363 363
 		try {
@@ -365,13 +365,13 @@  discard block
 block discarded – undo
365 365
 			$cachedfile->putContent($data);
366 366
 			$deps = json_encode($scss->getParsedFiles());
367 367
 			$depFile->putContent($deps);
368
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
368
+			$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
369 369
 			$gzipFile->putContent(gzencode($data, 9));
370
-			$this->logger->debug('SCSSCacher::cache ' . $webDir . '/' . $fileNameSCSS . ' compiled and successfully cached', ['app' => 'scss_cacher']);
370
+			$this->logger->debug('SCSSCacher::cache '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'scss_cacher']);
371 371
 
372 372
 			return true;
373 373
 		} catch (NotPermittedException $e) {
374
-			$this->logger->error('SCSSCacher::cache unable to cache: ' . $fileNameSCSS, ['app' => 'scss_cacher']);
374
+			$this->logger->error('SCSSCacher::cache unable to cache: '.$fileNameSCSS, ['app' => 'scss_cacher']);
375 375
 
376 376
 			return false;
377 377
 		}
@@ -400,7 +400,7 @@  discard block
 block discarded – undo
400 400
 				try {
401 401
 					$file->delete();
402 402
 				} catch (NotPermittedException $e) {
403
-					$this->logger->logException($e, ['message' => 'SCSSCacher::resetCache unable to delete file: ' . $file->getName(), 'app' => 'scss_cacher']);
403
+					$this->logger->logException($e, ['message' => 'SCSSCacher::resetCache unable to delete file: '.$file->getName(), 'app' => 'scss_cacher']);
404 404
 				}
405 405
 			}
406 406
 		}
@@ -418,7 +418,7 @@  discard block
 block discarded – undo
418 418
 		}
419 419
 		$variables = '';
420 420
 		foreach ($this->defaults->getScssVariables() as $key => $value) {
421
-			$variables .= '$' . $key . ': ' . $value . ' !default;';
421
+			$variables .= '$'.$key.': '.$value.' !default;';
422 422
 		}
423 423
 
424 424
 		/*
@@ -450,7 +450,7 @@  discard block
 block discarded – undo
450 450
 	 */
451 451
 	private function rebaseUrls(string $css, string $webDir): string {
452 452
 		$re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
453
-		$subst = 'url(\'' . $webDir . '/$1\')';
453
+		$subst = 'url(\''.$webDir.'/$1\')';
454 454
 
455 455
 		return preg_replace($re, $subst, $css);
456 456
 	}
@@ -479,12 +479,12 @@  discard block
 block discarded – undo
479 479
 	 * @return string
480 480
 	 */
481 481
 	private function prependBaseurlPrefix(string $cssFile): string {
482
-		return substr(md5($this->urlGenerator->getBaseUrl() . $this->getRoutePrefix()), 0, 4) . '-' . $cssFile;
482
+		return substr(md5($this->urlGenerator->getBaseUrl().$this->getRoutePrefix()), 0, 4).'-'.$cssFile;
483 483
 	}
484 484
 
485 485
 	private function getRoutePrefix() {
486 486
 		$frontControllerActive = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
487
-		$prefix = \OC::$WEBROOT . '/index.php';
487
+		$prefix = \OC::$WEBROOT.'/index.php';
488 488
 		if ($frontControllerActive) {
489 489
 			$prefix = \OC::$WEBROOT;
490 490
 		}
@@ -500,11 +500,11 @@  discard block
 block discarded – undo
500 500
 	private function prependVersionPrefix(string $cssFile, string $appId): string {
501 501
 		$appVersion = \OC_App::getAppVersion($appId);
502 502
 		if ($appVersion !== '0') {
503
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
503
+			return substr(md5($appVersion), 0, 4).'-'.$cssFile;
504 504
 		}
505 505
 		$coreVersion = \OC_Util::getVersionString();
506 506
 
507
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
507
+		return substr(md5($coreVersion), 0, 4).'-'.$cssFile;
508 508
 	}
509 509
 
510 510
 	/**
@@ -522,10 +522,10 @@  discard block
 block discarded – undo
522 522
 			$appDirectoryPath = explode($appName, $path)[1];
523 523
 			// Remove the webroot
524 524
 
525
-			return str_replace($webRoot, '', $appWebPath . $appDirectoryPath);
525
+			return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
526 526
 		}
527 527
 
528
-		return $webRoot . substr($path, strlen($serverRoot));
528
+		return $webRoot.substr($path, strlen($serverRoot));
529 529
 	}
530 530
 
531 531
 	/**
Please login to merge, or discard this patch.