Completed
Pull Request — master (#9352)
by Julius
16:54
created
lib/private/Template/SCSSCacher.php 2 patches
Indentation   +329 added lines, -329 removed lines patch added patch discarded remove patch
@@ -46,333 +46,333 @@
 block discarded – undo
46 46
 
47 47
 class SCSSCacher {
48 48
 
49
-	/** @var ILogger */
50
-	protected $logger;
51
-
52
-	/** @var IAppData */
53
-	protected $appData;
54
-
55
-	/** @var IURLGenerator */
56
-	protected $urlGenerator;
57
-
58
-	/** @var IConfig */
59
-	protected $config;
60
-
61
-	/** @var \OC_Defaults */
62
-	private $defaults;
63
-
64
-	/** @var string */
65
-	protected $serverRoot;
66
-
67
-	/** @var ICache */
68
-	protected $depsCache;
69
-
70
-	/** @var null|string */
71
-	private $injectedVariables;
72
-
73
-	/** @var ICacheFactory */
74
-	private $cacheFactory;
75
-
76
-	/**
77
-	 * @param ILogger $logger
78
-	 * @param Factory $appDataFactory
79
-	 * @param IURLGenerator $urlGenerator
80
-	 * @param IConfig $config
81
-	 * @param \OC_Defaults $defaults
82
-	 * @param string $serverRoot
83
-	 * @param ICacheFactory $cacheFactory
84
-	 */
85
-	public function __construct(ILogger $logger,
86
-								Factory $appDataFactory,
87
-								IURLGenerator $urlGenerator,
88
-								IConfig $config,
89
-								\OC_Defaults $defaults,
90
-								$serverRoot,
91
-								ICacheFactory $cacheFactory) {
92
-		$this->logger = $logger;
93
-		$this->appData = $appDataFactory->get('css');
94
-		$this->urlGenerator = $urlGenerator;
95
-		$this->config = $config;
96
-		$this->defaults = $defaults;
97
-		$this->serverRoot = $serverRoot;
98
-		$this->cacheFactory = $cacheFactory;
99
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl()));
100
-	}
101
-
102
-	/**
103
-	 * Process the caching process if needed
104
-	 *
105
-	 * @param string $root Root path to the nextcloud installation
106
-	 * @param string $file
107
-	 * @param string $app The app name
108
-	 * @return boolean
109
-	 * @throws NotPermittedException
110
-	 */
111
-	public function process(string $root, string $file, string $app): bool {
112
-		$path = explode('/', $root . '/' . $file);
113
-
114
-		$fileNameSCSS = array_pop($path);
115
-		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
116
-
117
-		$path = implode('/', $path);
118
-		$webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
119
-
120
-		try {
121
-			$folder = $this->appData->getFolder($app);
122
-		} catch(NotFoundException $e) {
123
-			// creating css appdata folder
124
-			$folder = $this->appData->newFolder($app);
125
-		}
126
-
127
-
128
-		if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
129
-			return true;
130
-		}
131
-		return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
132
-	}
133
-
134
-	/**
135
-	 * @param $appName
136
-	 * @param $fileName
137
-	 * @return ISimpleFile
138
-	 */
139
-	public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
140
-		$folder = $this->appData->getFolder($appName);
141
-		$cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
142
-		return $folder->getFile($cachedFileName);
143
-	}
144
-
145
-	/**
146
-	 * Check if the file is cached or not
147
-	 * @param string $fileNameCSS
148
-	 * @param ISimpleFolder $folder
149
-	 * @return boolean
150
-	 */
151
-	private function isCached(string $fileNameCSS, ISimpleFolder $folder) {
152
-		try {
153
-			$cachedFile = $folder->getFile($fileNameCSS);
154
-			if ($cachedFile->getSize() > 0) {
155
-				$depFileName = $fileNameCSS . '.deps';
156
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
157
-				if ($deps === null) {
158
-					$depFile = $folder->getFile($depFileName);
159
-					$deps = $depFile->getContent();
160
-					//Set to memcache for next run
161
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
162
-				}
163
-				$deps = json_decode($deps, true);
164
-
165
-				foreach ((array)$deps as $file=>$mtime) {
166
-					if (!file_exists($file) || filemtime($file) > $mtime) {
167
-						return false;
168
-					}
169
-				}
170
-				return true;
171
-			}
172
-			return false;
173
-		} catch(NotFoundException $e) {
174
-			return false;
175
-		}
176
-	}
177
-
178
-	/**
179
-	 * Check if the variables file has changed
180
-	 * @return bool
181
-	 */
182
-	private function variablesChanged(): bool {
183
-		$injectedVariables = $this->getInjectedVariables();
184
-		if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
185
-			$this->resetCache();
186
-			$this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
187
-			return true;
188
-		}
189
-		return false;
190
-	}
191
-
192
-	/**
193
-	 * Cache the file with AppData
194
-	 *
195
-	 * @param string $path
196
-	 * @param string $fileNameCSS
197
-	 * @param string $fileNameSCSS
198
-	 * @param ISimpleFolder $folder
199
-	 * @param string $webDir
200
-	 * @return boolean
201
-	 * @throws NotPermittedException
202
-	 */
203
-	private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
204
-		$scss = new Compiler();
205
-		$scss->setImportPaths([
206
-			$path,
207
-			$this->serverRoot . '/core/css/',
208
-		]);
209
-		// Continue after throw
210
-		$scss->setIgnoreErrors(true);
211
-		if($this->config->getSystemValue('debug')) {
212
-			// Debug mode
213
-			$scss->setFormatter(Expanded::class);
214
-			$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
215
-		} else {
216
-			// Compression
217
-			$scss->setFormatter(Crunched::class);
218
-		}
219
-
220
-		try {
221
-			$cachedfile = $folder->getFile($fileNameCSS);
222
-		} catch(NotFoundException $e) {
223
-			$cachedfile = $folder->newFile($fileNameCSS);
224
-		}
225
-
226
-		$depFileName = $fileNameCSS . '.deps';
227
-		try {
228
-			$depFile = $folder->getFile($depFileName);
229
-		} catch (NotFoundException $e) {
230
-			$depFile = $folder->newFile($depFileName);
231
-		}
232
-
233
-		// Compile
234
-		try {
235
-			$compiledScss = $scss->compile(
236
-				'@import "variables.scss";' .
237
-				$this->getInjectedVariables() .
238
-				'@import "'.$fileNameSCSS.'";');
239
-		} catch(ParserException $e) {
240
-			$this->logger->error($e, ['app' => 'core']);
241
-			return false;
242
-		}
243
-
244
-		// Gzip file
245
-		try {
246
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
247
-		} catch (NotFoundException $e) {
248
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
249
-		}
250
-
251
-		try {
252
-			$data = $this->rebaseUrls($compiledScss, $webDir);
253
-			$cachedfile->putContent($data);
254
-			$deps = json_encode($scss->getParsedFiles());
255
-			$depFile->putContent($deps);
256
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
257
-			$gzipFile->putContent(gzencode($data, 9));
258
-			$this->logger->debug('SCSSCacher: '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
259
-			return true;
260
-		} catch(NotPermittedException $e) {
261
-			$this->logger->error('SCSSCacher: unable to cache: ' . $fileNameSCSS);
262
-			return false;
263
-		}
264
-	}
265
-
266
-	/**
267
-	 * Reset scss cache by deleting all generated css files
268
-	 * We need to regenerate all files when variables change
269
-	 */
270
-	public function resetCache() {
271
-		$this->injectedVariables = null;
272
-		$this->cacheFactory->createDistributed('SCSS-')->clear();
273
-		$appDirectory = $this->appData->getDirectoryListing();
274
-		foreach ($appDirectory as $folder) {
275
-			foreach ($folder->getDirectoryListing() as $file) {
276
-				try {
277
-					$file->delete();
278
-				} catch(NotPermittedException $e) {
279
-					$this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: ' . $file->getName()]);
280
-				}
281
-			}
282
-		}
283
-	}
284
-
285
-	/**
286
-	 * @return string SCSS code for variables from OC_Defaults
287
-	 */
288
-	private function getInjectedVariables(): string {
289
-		if ($this->injectedVariables !== null) {
290
-			return $this->injectedVariables;
291
-		}
292
-		$variables = '';
293
-		foreach ($this->defaults->getScssVariables() as $key => $value) {
294
-			$variables .= '$' . $key . ': ' . $value . ';';
295
-		}
296
-
297
-		// check for valid variables / otherwise fall back to defaults
298
-		try {
299
-			$scss = new Compiler();
300
-			$scss->compile($variables);
301
-			$this->injectedVariables = $variables;
302
-		} catch (ParserException $e) {
303
-			$this->logger->error($e, ['app' => 'core']);
304
-		}
305
-
306
-		return $variables;
307
-	}
308
-
309
-	/**
310
-	 * Add the correct uri prefix to make uri valid again
311
-	 * @param string $css
312
-	 * @param string $webDir
313
-	 * @return string
314
-	 */
315
-	private function rebaseUrls(string $css, string $webDir): string {
316
-		$re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
317
-		$subst = 'url(\''.$webDir.'/$1\')';
318
-		return preg_replace($re, $subst, $css);
319
-	}
320
-
321
-	/**
322
-	 * Return the cached css file uri
323
-	 * @param string $appName the app name
324
-	 * @param string $fileName
325
-	 * @return string
326
-	 */
327
-	public function getCachedSCSS(string $appName, string $fileName): string {
328
-		$tmpfileLoc = explode('/', $fileName);
329
-		$fileName = array_pop($tmpfileLoc);
330
-		$fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
331
-
332
-		return substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['fileName' => $fileName, 'appName' => $appName]), strlen(\OC::$WEBROOT) + 1);
333
-	}
334
-
335
-	/**
336
-	 * Prepend hashed base url to the css file
337
-	 * @param string $cssFile
338
-	 * @return string
339
-	 */
340
-	private function prependBaseurlPrefix(string $cssFile): string {
341
-		$frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
342
-		return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 4) . '-' . $cssFile;
343
-	}
344
-
345
-	/**
346
-	 * Prepend hashed app version hash
347
-	 * @param string $cssFile
348
-	 * @param string $appId
349
-	 * @return string
350
-	 */
351
-	private function prependVersionPrefix(string $cssFile, string $appId): string {
352
-		$appVersion = \OC_App::getAppVersion($appId);
353
-		if ($appVersion !== '0') {
354
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
355
-		}
356
-		$coreVersion = \OC_Util::getVersionString();
357
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
358
-	}
359
-
360
-	/**
361
-	 * Get WebDir root
362
-	 * @param string $path the css file path
363
-	 * @param string $appName the app name
364
-	 * @param string $serverRoot the server root path
365
-	 * @param string $webRoot the nextcloud installation root path
366
-	 * @return string the webDir
367
-	 */
368
-	private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
369
-		// Detect if path is within server root AND if path is within an app path
370
-		if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
371
-			// Get the file path within the app directory
372
-			$appDirectoryPath = explode($appName, $path)[1];
373
-			// Remove the webroot
374
-			return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
375
-		}
376
-		return $webRoot.substr($path, strlen($serverRoot));
377
-	}
49
+    /** @var ILogger */
50
+    protected $logger;
51
+
52
+    /** @var IAppData */
53
+    protected $appData;
54
+
55
+    /** @var IURLGenerator */
56
+    protected $urlGenerator;
57
+
58
+    /** @var IConfig */
59
+    protected $config;
60
+
61
+    /** @var \OC_Defaults */
62
+    private $defaults;
63
+
64
+    /** @var string */
65
+    protected $serverRoot;
66
+
67
+    /** @var ICache */
68
+    protected $depsCache;
69
+
70
+    /** @var null|string */
71
+    private $injectedVariables;
72
+
73
+    /** @var ICacheFactory */
74
+    private $cacheFactory;
75
+
76
+    /**
77
+     * @param ILogger $logger
78
+     * @param Factory $appDataFactory
79
+     * @param IURLGenerator $urlGenerator
80
+     * @param IConfig $config
81
+     * @param \OC_Defaults $defaults
82
+     * @param string $serverRoot
83
+     * @param ICacheFactory $cacheFactory
84
+     */
85
+    public function __construct(ILogger $logger,
86
+                                Factory $appDataFactory,
87
+                                IURLGenerator $urlGenerator,
88
+                                IConfig $config,
89
+                                \OC_Defaults $defaults,
90
+                                $serverRoot,
91
+                                ICacheFactory $cacheFactory) {
92
+        $this->logger = $logger;
93
+        $this->appData = $appDataFactory->get('css');
94
+        $this->urlGenerator = $urlGenerator;
95
+        $this->config = $config;
96
+        $this->defaults = $defaults;
97
+        $this->serverRoot = $serverRoot;
98
+        $this->cacheFactory = $cacheFactory;
99
+        $this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl()));
100
+    }
101
+
102
+    /**
103
+     * Process the caching process if needed
104
+     *
105
+     * @param string $root Root path to the nextcloud installation
106
+     * @param string $file
107
+     * @param string $app The app name
108
+     * @return boolean
109
+     * @throws NotPermittedException
110
+     */
111
+    public function process(string $root, string $file, string $app): bool {
112
+        $path = explode('/', $root . '/' . $file);
113
+
114
+        $fileNameSCSS = array_pop($path);
115
+        $fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
116
+
117
+        $path = implode('/', $path);
118
+        $webDir = $this->getWebDir($path, $app, $this->serverRoot, \OC::$WEBROOT);
119
+
120
+        try {
121
+            $folder = $this->appData->getFolder($app);
122
+        } catch(NotFoundException $e) {
123
+            // creating css appdata folder
124
+            $folder = $this->appData->newFolder($app);
125
+        }
126
+
127
+
128
+        if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
129
+            return true;
130
+        }
131
+        return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
132
+    }
133
+
134
+    /**
135
+     * @param $appName
136
+     * @param $fileName
137
+     * @return ISimpleFile
138
+     */
139
+    public function getCachedCSS(string $appName, string $fileName): ISimpleFile {
140
+        $folder = $this->appData->getFolder($appName);
141
+        $cachedFileName = $this->prependVersionPrefix($this->prependBaseurlPrefix($fileName), $appName);
142
+        return $folder->getFile($cachedFileName);
143
+    }
144
+
145
+    /**
146
+     * Check if the file is cached or not
147
+     * @param string $fileNameCSS
148
+     * @param ISimpleFolder $folder
149
+     * @return boolean
150
+     */
151
+    private function isCached(string $fileNameCSS, ISimpleFolder $folder) {
152
+        try {
153
+            $cachedFile = $folder->getFile($fileNameCSS);
154
+            if ($cachedFile->getSize() > 0) {
155
+                $depFileName = $fileNameCSS . '.deps';
156
+                $deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
157
+                if ($deps === null) {
158
+                    $depFile = $folder->getFile($depFileName);
159
+                    $deps = $depFile->getContent();
160
+                    //Set to memcache for next run
161
+                    $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
162
+                }
163
+                $deps = json_decode($deps, true);
164
+
165
+                foreach ((array)$deps as $file=>$mtime) {
166
+                    if (!file_exists($file) || filemtime($file) > $mtime) {
167
+                        return false;
168
+                    }
169
+                }
170
+                return true;
171
+            }
172
+            return false;
173
+        } catch(NotFoundException $e) {
174
+            return false;
175
+        }
176
+    }
177
+
178
+    /**
179
+     * Check if the variables file has changed
180
+     * @return bool
181
+     */
182
+    private function variablesChanged(): bool {
183
+        $injectedVariables = $this->getInjectedVariables();
184
+        if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
185
+            $this->resetCache();
186
+            $this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
187
+            return true;
188
+        }
189
+        return false;
190
+    }
191
+
192
+    /**
193
+     * Cache the file with AppData
194
+     *
195
+     * @param string $path
196
+     * @param string $fileNameCSS
197
+     * @param string $fileNameSCSS
198
+     * @param ISimpleFolder $folder
199
+     * @param string $webDir
200
+     * @return boolean
201
+     * @throws NotPermittedException
202
+     */
203
+    private function cache(string $path, string $fileNameCSS, string $fileNameSCSS, ISimpleFolder $folder, string $webDir) {
204
+        $scss = new Compiler();
205
+        $scss->setImportPaths([
206
+            $path,
207
+            $this->serverRoot . '/core/css/',
208
+        ]);
209
+        // Continue after throw
210
+        $scss->setIgnoreErrors(true);
211
+        if($this->config->getSystemValue('debug')) {
212
+            // Debug mode
213
+            $scss->setFormatter(Expanded::class);
214
+            $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
215
+        } else {
216
+            // Compression
217
+            $scss->setFormatter(Crunched::class);
218
+        }
219
+
220
+        try {
221
+            $cachedfile = $folder->getFile($fileNameCSS);
222
+        } catch(NotFoundException $e) {
223
+            $cachedfile = $folder->newFile($fileNameCSS);
224
+        }
225
+
226
+        $depFileName = $fileNameCSS . '.deps';
227
+        try {
228
+            $depFile = $folder->getFile($depFileName);
229
+        } catch (NotFoundException $e) {
230
+            $depFile = $folder->newFile($depFileName);
231
+        }
232
+
233
+        // Compile
234
+        try {
235
+            $compiledScss = $scss->compile(
236
+                '@import "variables.scss";' .
237
+                $this->getInjectedVariables() .
238
+                '@import "'.$fileNameSCSS.'";');
239
+        } catch(ParserException $e) {
240
+            $this->logger->error($e, ['app' => 'core']);
241
+            return false;
242
+        }
243
+
244
+        // Gzip file
245
+        try {
246
+            $gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
247
+        } catch (NotFoundException $e) {
248
+            $gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
249
+        }
250
+
251
+        try {
252
+            $data = $this->rebaseUrls($compiledScss, $webDir);
253
+            $cachedfile->putContent($data);
254
+            $deps = json_encode($scss->getParsedFiles());
255
+            $depFile->putContent($deps);
256
+            $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
257
+            $gzipFile->putContent(gzencode($data, 9));
258
+            $this->logger->debug('SCSSCacher: '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
259
+            return true;
260
+        } catch(NotPermittedException $e) {
261
+            $this->logger->error('SCSSCacher: unable to cache: ' . $fileNameSCSS);
262
+            return false;
263
+        }
264
+    }
265
+
266
+    /**
267
+     * Reset scss cache by deleting all generated css files
268
+     * We need to regenerate all files when variables change
269
+     */
270
+    public function resetCache() {
271
+        $this->injectedVariables = null;
272
+        $this->cacheFactory->createDistributed('SCSS-')->clear();
273
+        $appDirectory = $this->appData->getDirectoryListing();
274
+        foreach ($appDirectory as $folder) {
275
+            foreach ($folder->getDirectoryListing() as $file) {
276
+                try {
277
+                    $file->delete();
278
+                } catch(NotPermittedException $e) {
279
+                    $this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: ' . $file->getName()]);
280
+                }
281
+            }
282
+        }
283
+    }
284
+
285
+    /**
286
+     * @return string SCSS code for variables from OC_Defaults
287
+     */
288
+    private function getInjectedVariables(): string {
289
+        if ($this->injectedVariables !== null) {
290
+            return $this->injectedVariables;
291
+        }
292
+        $variables = '';
293
+        foreach ($this->defaults->getScssVariables() as $key => $value) {
294
+            $variables .= '$' . $key . ': ' . $value . ';';
295
+        }
296
+
297
+        // check for valid variables / otherwise fall back to defaults
298
+        try {
299
+            $scss = new Compiler();
300
+            $scss->compile($variables);
301
+            $this->injectedVariables = $variables;
302
+        } catch (ParserException $e) {
303
+            $this->logger->error($e, ['app' => 'core']);
304
+        }
305
+
306
+        return $variables;
307
+    }
308
+
309
+    /**
310
+     * Add the correct uri prefix to make uri valid again
311
+     * @param string $css
312
+     * @param string $webDir
313
+     * @return string
314
+     */
315
+    private function rebaseUrls(string $css, string $webDir): string {
316
+        $re = '/url\([\'"]([^\/][\.\w?=\/-]*)[\'"]\)/x';
317
+        $subst = 'url(\''.$webDir.'/$1\')';
318
+        return preg_replace($re, $subst, $css);
319
+    }
320
+
321
+    /**
322
+     * Return the cached css file uri
323
+     * @param string $appName the app name
324
+     * @param string $fileName
325
+     * @return string
326
+     */
327
+    public function getCachedSCSS(string $appName, string $fileName): string {
328
+        $tmpfileLoc = explode('/', $fileName);
329
+        $fileName = array_pop($tmpfileLoc);
330
+        $fileName = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName)), $appName);
331
+
332
+        return substr($this->urlGenerator->linkToRoute('core.Css.getCss', ['fileName' => $fileName, 'appName' => $appName]), strlen(\OC::$WEBROOT) + 1);
333
+    }
334
+
335
+    /**
336
+     * Prepend hashed base url to the css file
337
+     * @param string $cssFile
338
+     * @return string
339
+     */
340
+    private function prependBaseurlPrefix(string $cssFile): string {
341
+        $frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
342
+        return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 4) . '-' . $cssFile;
343
+    }
344
+
345
+    /**
346
+     * Prepend hashed app version hash
347
+     * @param string $cssFile
348
+     * @param string $appId
349
+     * @return string
350
+     */
351
+    private function prependVersionPrefix(string $cssFile, string $appId): string {
352
+        $appVersion = \OC_App::getAppVersion($appId);
353
+        if ($appVersion !== '0') {
354
+            return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
355
+        }
356
+        $coreVersion = \OC_Util::getVersionString();
357
+        return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
358
+    }
359
+
360
+    /**
361
+     * Get WebDir root
362
+     * @param string $path the css file path
363
+     * @param string $appName the app name
364
+     * @param string $serverRoot the server root path
365
+     * @param string $webRoot the nextcloud installation root path
366
+     * @return string the webDir
367
+     */
368
+    private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
369
+        // Detect if path is within server root AND if path is within an app path
370
+        if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
371
+            // Get the file path within the app directory
372
+            $appDirectoryPath = explode($appName, $path)[1];
373
+            // Remove the webroot
374
+            return str_replace($webRoot, '', $appWebPath.$appDirectoryPath);
375
+        }
376
+        return $webRoot.substr($path, strlen($serverRoot));
377
+    }
378 378
 }
Please login to merge, or discard this patch.
Spacing   +29 added lines, -29 removed lines patch added patch discarded remove patch
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 		$this->defaults = $defaults;
97 97
 		$this->serverRoot = $serverRoot;
98 98
 		$this->cacheFactory = $cacheFactory;
99
-		$this->depsCache = $cacheFactory->createDistributed('SCSS-' . md5($this->urlGenerator->getBaseUrl()));
99
+		$this->depsCache = $cacheFactory->createDistributed('SCSS-'.md5($this->urlGenerator->getBaseUrl()));
100 100
 	}
101 101
 
102 102
 	/**
@@ -109,7 +109,7 @@  discard block
 block discarded – undo
109 109
 	 * @throws NotPermittedException
110 110
 	 */
111 111
 	public function process(string $root, string $file, string $app): bool {
112
-		$path = explode('/', $root . '/' . $file);
112
+		$path = explode('/', $root.'/'.$file);
113 113
 
114 114
 		$fileNameSCSS = array_pop($path);
115 115
 		$fileNameCSS = $this->prependVersionPrefix($this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS)), $app);
@@ -119,13 +119,13 @@  discard block
 block discarded – undo
119 119
 
120 120
 		try {
121 121
 			$folder = $this->appData->getFolder($app);
122
-		} catch(NotFoundException $e) {
122
+		} catch (NotFoundException $e) {
123 123
 			// creating css appdata folder
124 124
 			$folder = $this->appData->newFolder($app);
125 125
 		}
126 126
 
127 127
 
128
-		if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
128
+		if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
129 129
 			return true;
130 130
 		}
131 131
 		return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
@@ -152,17 +152,17 @@  discard block
 block discarded – undo
152 152
 		try {
153 153
 			$cachedFile = $folder->getFile($fileNameCSS);
154 154
 			if ($cachedFile->getSize() > 0) {
155
-				$depFileName = $fileNameCSS . '.deps';
156
-				$deps = $this->depsCache->get($folder->getName() . '-' . $depFileName);
155
+				$depFileName = $fileNameCSS.'.deps';
156
+				$deps = $this->depsCache->get($folder->getName().'-'.$depFileName);
157 157
 				if ($deps === null) {
158 158
 					$depFile = $folder->getFile($depFileName);
159 159
 					$deps = $depFile->getContent();
160 160
 					//Set to memcache for next run
161
-					$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
161
+					$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
162 162
 				}
163 163
 				$deps = json_decode($deps, true);
164 164
 
165
-				foreach ((array)$deps as $file=>$mtime) {
165
+				foreach ((array) $deps as $file=>$mtime) {
166 166
 					if (!file_exists($file) || filemtime($file) > $mtime) {
167 167
 						return false;
168 168
 					}
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 				return true;
171 171
 			}
172 172
 			return false;
173
-		} catch(NotFoundException $e) {
173
+		} catch (NotFoundException $e) {
174 174
 			return false;
175 175
 		}
176 176
 	}
@@ -181,7 +181,7 @@  discard block
 block discarded – undo
181 181
 	 */
182 182
 	private function variablesChanged(): bool {
183 183
 		$injectedVariables = $this->getInjectedVariables();
184
-		if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
184
+		if ($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
185 185
 			$this->resetCache();
186 186
 			$this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
187 187
 			return true;
@@ -204,11 +204,11 @@  discard block
 block discarded – undo
204 204
 		$scss = new Compiler();
205 205
 		$scss->setImportPaths([
206 206
 			$path,
207
-			$this->serverRoot . '/core/css/',
207
+			$this->serverRoot.'/core/css/',
208 208
 		]);
209 209
 		// Continue after throw
210 210
 		$scss->setIgnoreErrors(true);
211
-		if($this->config->getSystemValue('debug')) {
211
+		if ($this->config->getSystemValue('debug')) {
212 212
 			// Debug mode
213 213
 			$scss->setFormatter(Expanded::class);
214 214
 			$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
@@ -219,11 +219,11 @@  discard block
 block discarded – undo
219 219
 
220 220
 		try {
221 221
 			$cachedfile = $folder->getFile($fileNameCSS);
222
-		} catch(NotFoundException $e) {
222
+		} catch (NotFoundException $e) {
223 223
 			$cachedfile = $folder->newFile($fileNameCSS);
224 224
 		}
225 225
 
226
-		$depFileName = $fileNameCSS . '.deps';
226
+		$depFileName = $fileNameCSS.'.deps';
227 227
 		try {
228 228
 			$depFile = $folder->getFile($depFileName);
229 229
 		} catch (NotFoundException $e) {
@@ -233,19 +233,19 @@  discard block
 block discarded – undo
233 233
 		// Compile
234 234
 		try {
235 235
 			$compiledScss = $scss->compile(
236
-				'@import "variables.scss";' .
237
-				$this->getInjectedVariables() .
236
+				'@import "variables.scss";'.
237
+				$this->getInjectedVariables().
238 238
 				'@import "'.$fileNameSCSS.'";');
239
-		} catch(ParserException $e) {
239
+		} catch (ParserException $e) {
240 240
 			$this->logger->error($e, ['app' => 'core']);
241 241
 			return false;
242 242
 		}
243 243
 
244 244
 		// Gzip file
245 245
 		try {
246
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
246
+			$gzipFile = $folder->getFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
247 247
 		} catch (NotFoundException $e) {
248
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
248
+			$gzipFile = $folder->newFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
249 249
 		}
250 250
 
251 251
 		try {
@@ -253,12 +253,12 @@  discard block
 block discarded – undo
253 253
 			$cachedfile->putContent($data);
254 254
 			$deps = json_encode($scss->getParsedFiles());
255 255
 			$depFile->putContent($deps);
256
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
256
+			$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
257 257
 			$gzipFile->putContent(gzencode($data, 9));
258 258
 			$this->logger->debug('SCSSCacher: '.$webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
259 259
 			return true;
260
-		} catch(NotPermittedException $e) {
261
-			$this->logger->error('SCSSCacher: unable to cache: ' . $fileNameSCSS);
260
+		} catch (NotPermittedException $e) {
261
+			$this->logger->error('SCSSCacher: unable to cache: '.$fileNameSCSS);
262 262
 			return false;
263 263
 		}
264 264
 	}
@@ -275,8 +275,8 @@  discard block
 block discarded – undo
275 275
 			foreach ($folder->getDirectoryListing() as $file) {
276 276
 				try {
277 277
 					$file->delete();
278
-				} catch(NotPermittedException $e) {
279
-					$this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: ' . $file->getName()]);
278
+				} catch (NotPermittedException $e) {
279
+					$this->logger->logException($e, ['message' => 'SCSSCacher: unable to delete file: '.$file->getName()]);
280 280
 				}
281 281
 			}
282 282
 		}
@@ -291,7 +291,7 @@  discard block
 block discarded – undo
291 291
 		}
292 292
 		$variables = '';
293 293
 		foreach ($this->defaults->getScssVariables() as $key => $value) {
294
-			$variables .= '$' . $key . ': ' . $value . ';';
294
+			$variables .= '$'.$key.': '.$value.';';
295 295
 		}
296 296
 
297 297
 		// check for valid variables / otherwise fall back to defaults
@@ -339,7 +339,7 @@  discard block
 block discarded – undo
339 339
 	 */
340 340
 	private function prependBaseurlPrefix(string $cssFile): string {
341 341
 		$frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
342
-		return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 4) . '-' . $cssFile;
342
+		return substr(md5($this->urlGenerator->getBaseUrl().$frontendController), 0, 4).'-'.$cssFile;
343 343
 	}
344 344
 
345 345
 	/**
@@ -351,10 +351,10 @@  discard block
 block discarded – undo
351 351
 	private function prependVersionPrefix(string $cssFile, string $appId): string {
352 352
 		$appVersion = \OC_App::getAppVersion($appId);
353 353
 		if ($appVersion !== '0') {
354
-			return substr(md5($appVersion), 0, 4) . '-' . $cssFile;
354
+			return substr(md5($appVersion), 0, 4).'-'.$cssFile;
355 355
 		}
356 356
 		$coreVersion = \OC_Util::getVersionString();
357
-		return substr(md5($coreVersion), 0, 4) . '-' . $cssFile;
357
+		return substr(md5($coreVersion), 0, 4).'-'.$cssFile;
358 358
 	}
359 359
 
360 360
 	/**
@@ -367,7 +367,7 @@  discard block
 block discarded – undo
367 367
 	 */
368 368
 	private function getWebDir(string $path, string $appName, string $serverRoot, string $webRoot): string {
369 369
 		// Detect if path is within server root AND if path is within an app path
370
-		if ( strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
370
+		if (strpos($path, $serverRoot) === false && $appWebPath = \OC_App::getAppWebPath($appName)) {
371 371
 			// Get the file path within the app directory
372 372
 			$appDirectoryPath = explode($appName, $path)[1];
373 373
 			// Remove the webroot
Please login to merge, or discard this patch.