Completed
Pull Request — master (#7631)
by John
66:15 queued 32:02
created
lib/private/Template/CSSResourceLocator.php 2 patches
Indentation   +114 added lines, -114 removed lines patch added patch discarded remove patch
@@ -34,118 +34,118 @@
 block discarded – undo
34 34
 
35 35
 class CSSResourceLocator extends ResourceLocator {
36 36
 
37
-	/** @var SCSSCacher */
38
-	protected $scssCacher;
39
-
40
-	/**
41
-	 * @param ILogger $logger
42
-	 * @param string $theme
43
-	 * @param array $core_map
44
-	 * @param array $party_map
45
-	 * @param SCSSCacher $scssCacher
46
-	 */
47
-	public function __construct(ILogger $logger, $theme, $core_map, $party_map, $scssCacher) {
48
-		$this->scssCacher = $scssCacher;
49
-
50
-		parent::__construct($logger, $theme, $core_map, $party_map);
51
-	}
52
-
53
-	/**
54
-	 * @param string $style
55
-	 */
56
-	public function doFind($style) {
57
-		$app = substr($style, 0, strpos($style, '/'));
58
-		if (strpos($style, '3rdparty') === 0
59
-			&& $this->appendIfExist($this->thirdpartyroot, $style.'.css')
60
-			|| $this->cacheAndAppendScssIfExist($this->serverroot, $style.'.scss', $app)
61
-			|| $this->cacheAndAppendScssIfExist($this->serverroot, 'core/'.$style.'.scss')
62
-			|| $this->appendIfExist($this->serverroot, $style.'.css')
63
-			|| $this->appendIfExist($this->serverroot, 'core/'.$style.'.css')
64
-		) {
65
-			return;
66
-		}
67
-		$style = substr($style, strpos($style, '/')+1);
68
-		$app_path = \OC_App::getAppPath($app);
69
-		$app_url = \OC_App::getAppWebPath($app);
70
-
71
-		if ($app_path === false && $app_url === false) {
72
-			$this->logger->error('Could not find resource {resource} to load', [
73
-				'resource' => $app . '/' . $style . '.css',
74
-				'app' => 'cssresourceloader',
75
-			]);
76
-			return;
77
-		}
78
-
79
-		// Account for the possibility of having symlinks in app path. Doing
80
-		// this here instead of above as an empty argument to realpath gets
81
-		// turned into cwd.
82
-		$app_path = realpath($app_path);
83
-
84
-		if(!$this->cacheAndAppendScssIfExist($app_path, $style.'.scss', $app)) {
85
-			$this->append($app_path, $style.'.css', $app_url);
86
-		}
87
-	}
88
-
89
-	/**
90
-	 * @param string $style
91
-	 */
92
-	public function doFindTheme($style) {
93
-		$theme_dir = 'themes/'.$this->theme.'/';
94
-		$this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$style.'.css')
95
-			|| $this->appendIfExist($this->serverroot, $theme_dir.$style.'.css')
96
-			|| $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$style.'.css');
97
-	}
98
-
99
-	/**
100
-	 * cache and append the scss $file if exist at $root
101
-	 *
102
-	 * @param string $root path to check
103
-	 * @param string $file the filename
104
-	 * @return bool True if the resource was found and cached, false otherwise
105
-	 */
106
-	protected function cacheAndAppendScssIfExist($root, $file, $app = 'core') {
107
-		if (is_file($root.'/'.$file)) {
108
-			if($this->scssCacher !== null) {
109
-				if($this->scssCacher->process($root, $file, $app)) {
110
-
111
-					$this->append($root, $this->scssCacher->getCachedSCSS($app, $file), \OC::$WEBROOT, true, true);
112
-					return true;
113
-				} else {
114
-					$this->logger->warning('Failed to compile and/or save '.$root.'/'.$file, ['app' => 'core']);
115
-					return false;
116
-				}
117
-			} else {
118
-				$this->logger->debug('Scss is disabled for '.$root.'/'.$file.', ignoring', ['app' => 'core']);
119
-				return true;
120
-			}
121
-		}
122
-		return false;
123
-	}
124
-
125
-	public function append($root, $file, $webRoot = null, $throw = true, $scss = false) {
126
-		if (!$scss) {
127
-			parent::append($root, $file, $webRoot, $throw);
128
-		} else {
129
-			if (!$webRoot) {
130
-				$webRoot = $this->findWebRoot($root);
131
-
132
-				if ($webRoot === null) {
133
-					$webRoot = '';
134
-					$this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [
135
-						'app' => 'lib',
136
-						'root' => $root,
137
-						'file' => $file,
138
-						'webRoot' => $webRoot,
139
-						'throw' => $throw ? 'true' : 'false'
140
-					]);
141
-
142
-					if ($throw && $root === '/') {
143
-						throw new ResourceNotFoundException($file, $webRoot);
144
-					}
145
-				}
146
-			}
147
-
148
-			$this->resources[] = array($webRoot? : \OC::$WEBROOT, $webRoot, $file);
149
-		}
150
-	}
37
+    /** @var SCSSCacher */
38
+    protected $scssCacher;
39
+
40
+    /**
41
+     * @param ILogger $logger
42
+     * @param string $theme
43
+     * @param array $core_map
44
+     * @param array $party_map
45
+     * @param SCSSCacher $scssCacher
46
+     */
47
+    public function __construct(ILogger $logger, $theme, $core_map, $party_map, $scssCacher) {
48
+        $this->scssCacher = $scssCacher;
49
+
50
+        parent::__construct($logger, $theme, $core_map, $party_map);
51
+    }
52
+
53
+    /**
54
+     * @param string $style
55
+     */
56
+    public function doFind($style) {
57
+        $app = substr($style, 0, strpos($style, '/'));
58
+        if (strpos($style, '3rdparty') === 0
59
+            && $this->appendIfExist($this->thirdpartyroot, $style.'.css')
60
+            || $this->cacheAndAppendScssIfExist($this->serverroot, $style.'.scss', $app)
61
+            || $this->cacheAndAppendScssIfExist($this->serverroot, 'core/'.$style.'.scss')
62
+            || $this->appendIfExist($this->serverroot, $style.'.css')
63
+            || $this->appendIfExist($this->serverroot, 'core/'.$style.'.css')
64
+        ) {
65
+            return;
66
+        }
67
+        $style = substr($style, strpos($style, '/')+1);
68
+        $app_path = \OC_App::getAppPath($app);
69
+        $app_url = \OC_App::getAppWebPath($app);
70
+
71
+        if ($app_path === false && $app_url === false) {
72
+            $this->logger->error('Could not find resource {resource} to load', [
73
+                'resource' => $app . '/' . $style . '.css',
74
+                'app' => 'cssresourceloader',
75
+            ]);
76
+            return;
77
+        }
78
+
79
+        // Account for the possibility of having symlinks in app path. Doing
80
+        // this here instead of above as an empty argument to realpath gets
81
+        // turned into cwd.
82
+        $app_path = realpath($app_path);
83
+
84
+        if(!$this->cacheAndAppendScssIfExist($app_path, $style.'.scss', $app)) {
85
+            $this->append($app_path, $style.'.css', $app_url);
86
+        }
87
+    }
88
+
89
+    /**
90
+     * @param string $style
91
+     */
92
+    public function doFindTheme($style) {
93
+        $theme_dir = 'themes/'.$this->theme.'/';
94
+        $this->appendIfExist($this->serverroot, $theme_dir.'apps/'.$style.'.css')
95
+            || $this->appendIfExist($this->serverroot, $theme_dir.$style.'.css')
96
+            || $this->appendIfExist($this->serverroot, $theme_dir.'core/'.$style.'.css');
97
+    }
98
+
99
+    /**
100
+     * cache and append the scss $file if exist at $root
101
+     *
102
+     * @param string $root path to check
103
+     * @param string $file the filename
104
+     * @return bool True if the resource was found and cached, false otherwise
105
+     */
106
+    protected function cacheAndAppendScssIfExist($root, $file, $app = 'core') {
107
+        if (is_file($root.'/'.$file)) {
108
+            if($this->scssCacher !== null) {
109
+                if($this->scssCacher->process($root, $file, $app)) {
110
+
111
+                    $this->append($root, $this->scssCacher->getCachedSCSS($app, $file), \OC::$WEBROOT, true, true);
112
+                    return true;
113
+                } else {
114
+                    $this->logger->warning('Failed to compile and/or save '.$root.'/'.$file, ['app' => 'core']);
115
+                    return false;
116
+                }
117
+            } else {
118
+                $this->logger->debug('Scss is disabled for '.$root.'/'.$file.', ignoring', ['app' => 'core']);
119
+                return true;
120
+            }
121
+        }
122
+        return false;
123
+    }
124
+
125
+    public function append($root, $file, $webRoot = null, $throw = true, $scss = false) {
126
+        if (!$scss) {
127
+            parent::append($root, $file, $webRoot, $throw);
128
+        } else {
129
+            if (!$webRoot) {
130
+                $webRoot = $this->findWebRoot($root);
131
+
132
+                if ($webRoot === null) {
133
+                    $webRoot = '';
134
+                    $this->logger->error('ResourceLocator can not find a web root (root: {root}, file: {file}, webRoot: {webRoot}, throw: {throw})', [
135
+                        'app' => 'lib',
136
+                        'root' => $root,
137
+                        'file' => $file,
138
+                        'webRoot' => $webRoot,
139
+                        'throw' => $throw ? 'true' : 'false'
140
+                    ]);
141
+
142
+                    if ($throw && $root === '/') {
143
+                        throw new ResourceNotFoundException($file, $webRoot);
144
+                    }
145
+                }
146
+            }
147
+
148
+            $this->resources[] = array($webRoot? : \OC::$WEBROOT, $webRoot, $file);
149
+        }
150
+    }
151 151
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -64,13 +64,13 @@  discard block
 block discarded – undo
64 64
 		) {
65 65
 			return;
66 66
 		}
67
-		$style = substr($style, strpos($style, '/')+1);
67
+		$style = substr($style, strpos($style, '/') + 1);
68 68
 		$app_path = \OC_App::getAppPath($app);
69 69
 		$app_url = \OC_App::getAppWebPath($app);
70 70
 
71 71
 		if ($app_path === false && $app_url === false) {
72 72
 			$this->logger->error('Could not find resource {resource} to load', [
73
-				'resource' => $app . '/' . $style . '.css',
73
+				'resource' => $app.'/'.$style.'.css',
74 74
 				'app' => 'cssresourceloader',
75 75
 			]);
76 76
 			return;
@@ -81,7 +81,7 @@  discard block
 block discarded – undo
81 81
 		// turned into cwd.
82 82
 		$app_path = realpath($app_path);
83 83
 
84
-		if(!$this->cacheAndAppendScssIfExist($app_path, $style.'.scss', $app)) {
84
+		if (!$this->cacheAndAppendScssIfExist($app_path, $style.'.scss', $app)) {
85 85
 			$this->append($app_path, $style.'.css', $app_url);
86 86
 		}
87 87
 	}
@@ -105,8 +105,8 @@  discard block
 block discarded – undo
105 105
 	 */
106 106
 	protected function cacheAndAppendScssIfExist($root, $file, $app = 'core') {
107 107
 		if (is_file($root.'/'.$file)) {
108
-			if($this->scssCacher !== null) {
109
-				if($this->scssCacher->process($root, $file, $app)) {
108
+			if ($this->scssCacher !== null) {
109
+				if ($this->scssCacher->process($root, $file, $app)) {
110 110
 
111 111
 					$this->append($root, $this->scssCacher->getCachedSCSS($app, $file), \OC::$WEBROOT, true, true);
112 112
 					return true;
@@ -145,7 +145,7 @@  discard block
 block discarded – undo
145 145
 				}
146 146
 			}
147 147
 
148
-			$this->resources[] = array($webRoot? : \OC::$WEBROOT, $webRoot, $file);
148
+			$this->resources[] = array($webRoot ?: \OC::$WEBROOT, $webRoot, $file);
149 149
 		}
150 150
 	}
151 151
 }
Please login to merge, or discard this patch.
lib/private/Template/SCSSCacher.php 2 patches
Indentation   +278 added lines, -278 removed lines patch added patch discarded remove patch
@@ -45,282 +45,282 @@
 block discarded – undo
45 45
 
46 46
 class SCSSCacher {
47 47
 
48
-	/** @var ILogger */
49
-	protected $logger;
50
-
51
-	/** @var IAppData */
52
-	protected $appData;
53
-
54
-	/** @var IURLGenerator */
55
-	protected $urlGenerator;
56
-
57
-	/** @var IConfig */
58
-	protected $config;
59
-
60
-	/** @var string */
61
-	protected $serverRoot;
62
-
63
-	/** @var ICache */
64
-	protected $depsCache;
65
-
66
-	/**
67
-	 * @param ILogger $logger
68
-	 * @param Factory $appDataFactory
69
-	 * @param IURLGenerator $urlGenerator
70
-	 * @param IConfig $config
71
-	 * @param \OC_Defaults $defaults
72
-	 * @param string $serverRoot
73
-	 * @param ICache $depsCache
74
-	 */
75
-	public function __construct(ILogger $logger,
76
-								Factory $appDataFactory,
77
-								IURLGenerator $urlGenerator,
78
-								IConfig $config,
79
-								\OC_Defaults $defaults,
80
-								$serverRoot,
81
-								ICache $depsCache) {
82
-		$this->logger = $logger;
83
-		$this->appData = $appDataFactory->get('css');
84
-		$this->urlGenerator = $urlGenerator;
85
-		$this->config = $config;
86
-		$this->defaults = $defaults;
87
-		$this->serverRoot = $serverRoot;
88
-		$this->depsCache = $depsCache;
89
-	}
90
-
91
-	/**
92
-	 * Process the caching process if needed
93
-	 * @param string $root Root path to the nextcloud installation
94
-	 * @param string $file
95
-	 * @param string $app The app name
96
-	 * @return boolean
97
-	 */
98
-	public function process($root, $file, $app) {
99
-		$path = explode('/', $root . '/' . $file);
100
-
101
-		$fileNameSCSS = array_pop($path);
102
-		$fileNameCSS = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS));
103
-
104
-		$path = implode('/', $path);
105
-		$webDir = null;
106
-
107
-		// Detect if path is within an app path
108
-		$app_paths = $this->config->getSystemValue('apps_paths');
109
-		if (!empty($app_paths)) {
110
-			foreach ($app_paths as $app_path) {
111
-				if (strpos($path, $app_path["path"]) === 0) {
112
-					$webDir = $app_path["url"].str_replace($app_path["path"], '', $path);
113
-					break;
114
-				}
115
-			}
116
-		}
117
-		if (is_null($webDir)) {
118
-			$webDir = substr($path, strlen($this->serverRoot));
119
-		}
120
-
121
-		try {
122
-			$folder = $this->appData->getFolder($app);
123
-		} catch(NotFoundException $e) {
124
-			// creating css appdata folder
125
-			$folder = $this->appData->newFolder($app);
126
-		}
127
-
128
-
129
-		if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
130
-			return true;
131
-		}
132
-		return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
133
-	}
134
-
135
-	/**
136
-	 * @param $appName
137
-	 * @param $fileName
138
-	 * @return ISimpleFile
139
-	 */
140
-	public function getCachedCSS($appName, $fileName) {
141
-		$folder = $this->appData->getFolder($appName);
142
-		return $folder->getFile($this->prependBaseurlPrefix($fileName));
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($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 ($deps as $file=>$mtime) {
166
-					if (!file_exists($file) || filemtime($file) > $mtime) {
167
-						return false;
168
-					}
169
-				}
170
-			}
171
-			return true;
172
-		} catch(NotFoundException $e) {
173
-			return false;
174
-		}
175
-	}
176
-
177
-	/**
178
-	 * Check if the variables file has changed
179
-	 * @return bool
180
-	 */
181
-	private function variablesChanged() {
182
-		$injectedVariables = $this->getInjectedVariables();
183
-		if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
184
-			$this->resetCache();
185
-			$this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
186
-			return true;
187
-		}
188
-		return false;
189
-	}
190
-
191
-	/**
192
-	 * Cache the file with AppData
193
-	 * @param string $path
194
-	 * @param string $fileNameCSS
195
-	 * @param string $fileNameSCSS
196
-	 * @param ISimpleFolder $folder
197
-	 * @param string $webDir
198
-	 * @return boolean
199
-	 */
200
-	private function cache($path, $fileNameCSS, $fileNameSCSS, ISimpleFolder $folder, $webDir) {
201
-		$scss = new Compiler();
202
-		$scss->setImportPaths([
203
-			$path,
204
-			\OC::$SERVERROOT . '/core/css/',
205
-		]);
206
-		// Continue after throw
207
-		$scss->setIgnoreErrors(true);
208
-		if($this->config->getSystemValue('debug')) {
209
-			// Debug mode
210
-			$scss->setFormatter(Expanded::class);
211
-			$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
212
-		} else {
213
-			// Compression
214
-			$scss->setFormatter(Crunched::class);
215
-		}
216
-
217
-		try {
218
-			$cachedfile = $folder->getFile($fileNameCSS);
219
-		} catch(NotFoundException $e) {
220
-			$cachedfile = $folder->newFile($fileNameCSS);
221
-		}
222
-
223
-		$depFileName = $fileNameCSS . '.deps';
224
-		try {
225
-			$depFile = $folder->getFile($depFileName);
226
-		} catch (NotFoundException $e) {
227
-			$depFile = $folder->newFile($depFileName);
228
-		}
229
-
230
-		// Compile
231
-		try {
232
-			$compiledScss = $scss->compile(
233
-				'@import "variables.scss";' .
234
-				$this->getInjectedVariables() .
235
-				'@import "'.$fileNameSCSS.'";');
236
-		} catch(ParserException $e) {
237
-			$this->logger->error($e, ['app' => 'core']);
238
-			return false;
239
-		}
240
-
241
-		// Gzip file
242
-		try {
243
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
244
-		} catch (NotFoundException $e) {
245
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
246
-		}
247
-
248
-		try {
249
-			$data = $this->rebaseUrls($compiledScss, $webDir);
250
-			$cachedfile->putContent($data);
251
-			$deps = json_encode($scss->getParsedFiles());
252
-			$depFile->putContent($deps);
253
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
254
-			$gzipFile->putContent(gzencode($data, 9));
255
-			$this->logger->debug($webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
256
-			return true;
257
-		} catch(NotPermittedException $e) {
258
-			return false;
259
-		}
260
-	}
261
-
262
-	/**
263
-	 * Reset scss cache by deleting all generated css files
264
-	 * We need to regenerate all files when variables change
265
-	 */
266
-	private function resetCache() {
267
-		$appDirectory = $this->appData->getDirectoryListing();
268
-		if(empty($appDirectory)){
269
-			return;
270
-		}
271
-		foreach ($appDirectory as $folder) {
272
-			foreach ($folder->getDirectoryListing() as $file) {
273
-				if (substr($file->getName(), -3) === "css" || substr($file->getName(), -4) === "deps") {
274
-					$file->delete();
275
-				}
276
-			}
277
-		}
278
-	}
279
-
280
-	/**
281
-	 * @return string SCSS code for variables from OC_Defaults
282
-	 */
283
-	private function getInjectedVariables() {
284
-		$variables = '';
285
-		foreach ($this->defaults->getScssVariables() as $key => $value) {
286
-			$variables .= '$' . $key . ': ' . $value . ';';
287
-		}
288
-		return $variables;
289
-	}
290
-
291
-	/**
292
-	 * Add the correct uri prefix to make uri valid again
293
-	 * @param string $css
294
-	 * @param string $webDir
295
-	 * @return string
296
-	 */
297
-	private function rebaseUrls($css, $webDir) {
298
-		$re = '/url\([\'"]([\.\w?=\/-]*)[\'"]\)/x';
299
-		$subst = 'url(\''.$webDir.'/$1\')';
300
-		return preg_replace($re, $subst, $css);
301
-	}
302
-
303
-	/**
304
-	 * Return the cached css file uri
305
-	 * @param string $appName the app name
306
-	 * @param string $fileName
307
-	 * @return string
308
-	 */
309
-	public function getCachedSCSS($appName, $fileName) {
310
-		$tmpfileLoc = explode('/', $fileName);
311
-		$fileName = array_pop($tmpfileLoc);
312
-		$fileName = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName));
313
-
314
-		return substr($this->urlGenerator->linkToRoute('core.Css.getCss', array('fileName' => $fileName, 'appName' => $appName)), strlen(\OC::$WEBROOT) + 1);
315
-	}
316
-
317
-	/**
318
-	 * Prepend hashed base url to the css file
319
-	 * @param $cssFile
320
-	 * @return string
321
-	 */
322
-	private function prependBaseurlPrefix($cssFile) {
323
-		$frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
324
-		return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 8) . '-' . $cssFile;
325
-	}
48
+    /** @var ILogger */
49
+    protected $logger;
50
+
51
+    /** @var IAppData */
52
+    protected $appData;
53
+
54
+    /** @var IURLGenerator */
55
+    protected $urlGenerator;
56
+
57
+    /** @var IConfig */
58
+    protected $config;
59
+
60
+    /** @var string */
61
+    protected $serverRoot;
62
+
63
+    /** @var ICache */
64
+    protected $depsCache;
65
+
66
+    /**
67
+     * @param ILogger $logger
68
+     * @param Factory $appDataFactory
69
+     * @param IURLGenerator $urlGenerator
70
+     * @param IConfig $config
71
+     * @param \OC_Defaults $defaults
72
+     * @param string $serverRoot
73
+     * @param ICache $depsCache
74
+     */
75
+    public function __construct(ILogger $logger,
76
+                                Factory $appDataFactory,
77
+                                IURLGenerator $urlGenerator,
78
+                                IConfig $config,
79
+                                \OC_Defaults $defaults,
80
+                                $serverRoot,
81
+                                ICache $depsCache) {
82
+        $this->logger = $logger;
83
+        $this->appData = $appDataFactory->get('css');
84
+        $this->urlGenerator = $urlGenerator;
85
+        $this->config = $config;
86
+        $this->defaults = $defaults;
87
+        $this->serverRoot = $serverRoot;
88
+        $this->depsCache = $depsCache;
89
+    }
90
+
91
+    /**
92
+     * Process the caching process if needed
93
+     * @param string $root Root path to the nextcloud installation
94
+     * @param string $file
95
+     * @param string $app The app name
96
+     * @return boolean
97
+     */
98
+    public function process($root, $file, $app) {
99
+        $path = explode('/', $root . '/' . $file);
100
+
101
+        $fileNameSCSS = array_pop($path);
102
+        $fileNameCSS = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS));
103
+
104
+        $path = implode('/', $path);
105
+        $webDir = null;
106
+
107
+        // Detect if path is within an app path
108
+        $app_paths = $this->config->getSystemValue('apps_paths');
109
+        if (!empty($app_paths)) {
110
+            foreach ($app_paths as $app_path) {
111
+                if (strpos($path, $app_path["path"]) === 0) {
112
+                    $webDir = $app_path["url"].str_replace($app_path["path"], '', $path);
113
+                    break;
114
+                }
115
+            }
116
+        }
117
+        if (is_null($webDir)) {
118
+            $webDir = substr($path, strlen($this->serverRoot));
119
+        }
120
+
121
+        try {
122
+            $folder = $this->appData->getFolder($app);
123
+        } catch(NotFoundException $e) {
124
+            // creating css appdata folder
125
+            $folder = $this->appData->newFolder($app);
126
+        }
127
+
128
+
129
+        if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
130
+            return true;
131
+        }
132
+        return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
133
+    }
134
+
135
+    /**
136
+     * @param $appName
137
+     * @param $fileName
138
+     * @return ISimpleFile
139
+     */
140
+    public function getCachedCSS($appName, $fileName) {
141
+        $folder = $this->appData->getFolder($appName);
142
+        return $folder->getFile($this->prependBaseurlPrefix($fileName));
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($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 ($deps as $file=>$mtime) {
166
+                    if (!file_exists($file) || filemtime($file) > $mtime) {
167
+                        return false;
168
+                    }
169
+                }
170
+            }
171
+            return true;
172
+        } catch(NotFoundException $e) {
173
+            return false;
174
+        }
175
+    }
176
+
177
+    /**
178
+     * Check if the variables file has changed
179
+     * @return bool
180
+     */
181
+    private function variablesChanged() {
182
+        $injectedVariables = $this->getInjectedVariables();
183
+        if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
184
+            $this->resetCache();
185
+            $this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
186
+            return true;
187
+        }
188
+        return false;
189
+    }
190
+
191
+    /**
192
+     * Cache the file with AppData
193
+     * @param string $path
194
+     * @param string $fileNameCSS
195
+     * @param string $fileNameSCSS
196
+     * @param ISimpleFolder $folder
197
+     * @param string $webDir
198
+     * @return boolean
199
+     */
200
+    private function cache($path, $fileNameCSS, $fileNameSCSS, ISimpleFolder $folder, $webDir) {
201
+        $scss = new Compiler();
202
+        $scss->setImportPaths([
203
+            $path,
204
+            \OC::$SERVERROOT . '/core/css/',
205
+        ]);
206
+        // Continue after throw
207
+        $scss->setIgnoreErrors(true);
208
+        if($this->config->getSystemValue('debug')) {
209
+            // Debug mode
210
+            $scss->setFormatter(Expanded::class);
211
+            $scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
212
+        } else {
213
+            // Compression
214
+            $scss->setFormatter(Crunched::class);
215
+        }
216
+
217
+        try {
218
+            $cachedfile = $folder->getFile($fileNameCSS);
219
+        } catch(NotFoundException $e) {
220
+            $cachedfile = $folder->newFile($fileNameCSS);
221
+        }
222
+
223
+        $depFileName = $fileNameCSS . '.deps';
224
+        try {
225
+            $depFile = $folder->getFile($depFileName);
226
+        } catch (NotFoundException $e) {
227
+            $depFile = $folder->newFile($depFileName);
228
+        }
229
+
230
+        // Compile
231
+        try {
232
+            $compiledScss = $scss->compile(
233
+                '@import "variables.scss";' .
234
+                $this->getInjectedVariables() .
235
+                '@import "'.$fileNameSCSS.'";');
236
+        } catch(ParserException $e) {
237
+            $this->logger->error($e, ['app' => 'core']);
238
+            return false;
239
+        }
240
+
241
+        // Gzip file
242
+        try {
243
+            $gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
244
+        } catch (NotFoundException $e) {
245
+            $gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
246
+        }
247
+
248
+        try {
249
+            $data = $this->rebaseUrls($compiledScss, $webDir);
250
+            $cachedfile->putContent($data);
251
+            $deps = json_encode($scss->getParsedFiles());
252
+            $depFile->putContent($deps);
253
+            $this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
254
+            $gzipFile->putContent(gzencode($data, 9));
255
+            $this->logger->debug($webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
256
+            return true;
257
+        } catch(NotPermittedException $e) {
258
+            return false;
259
+        }
260
+    }
261
+
262
+    /**
263
+     * Reset scss cache by deleting all generated css files
264
+     * We need to regenerate all files when variables change
265
+     */
266
+    private function resetCache() {
267
+        $appDirectory = $this->appData->getDirectoryListing();
268
+        if(empty($appDirectory)){
269
+            return;
270
+        }
271
+        foreach ($appDirectory as $folder) {
272
+            foreach ($folder->getDirectoryListing() as $file) {
273
+                if (substr($file->getName(), -3) === "css" || substr($file->getName(), -4) === "deps") {
274
+                    $file->delete();
275
+                }
276
+            }
277
+        }
278
+    }
279
+
280
+    /**
281
+     * @return string SCSS code for variables from OC_Defaults
282
+     */
283
+    private function getInjectedVariables() {
284
+        $variables = '';
285
+        foreach ($this->defaults->getScssVariables() as $key => $value) {
286
+            $variables .= '$' . $key . ': ' . $value . ';';
287
+        }
288
+        return $variables;
289
+    }
290
+
291
+    /**
292
+     * Add the correct uri prefix to make uri valid again
293
+     * @param string $css
294
+     * @param string $webDir
295
+     * @return string
296
+     */
297
+    private function rebaseUrls($css, $webDir) {
298
+        $re = '/url\([\'"]([\.\w?=\/-]*)[\'"]\)/x';
299
+        $subst = 'url(\''.$webDir.'/$1\')';
300
+        return preg_replace($re, $subst, $css);
301
+    }
302
+
303
+    /**
304
+     * Return the cached css file uri
305
+     * @param string $appName the app name
306
+     * @param string $fileName
307
+     * @return string
308
+     */
309
+    public function getCachedSCSS($appName, $fileName) {
310
+        $tmpfileLoc = explode('/', $fileName);
311
+        $fileName = array_pop($tmpfileLoc);
312
+        $fileName = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileName));
313
+
314
+        return substr($this->urlGenerator->linkToRoute('core.Css.getCss', array('fileName' => $fileName, 'appName' => $appName)), strlen(\OC::$WEBROOT) + 1);
315
+    }
316
+
317
+    /**
318
+     * Prepend hashed base url to the css file
319
+     * @param $cssFile
320
+     * @return string
321
+     */
322
+    private function prependBaseurlPrefix($cssFile) {
323
+        $frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
324
+        return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 8) . '-' . $cssFile;
325
+    }
326 326
 }
Please login to merge, or discard this patch.
Spacing   +22 added lines, -22 removed lines patch added patch discarded remove patch
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 	 * @return boolean
97 97
 	 */
98 98
 	public function process($root, $file, $app) {
99
-		$path = explode('/', $root . '/' . $file);
99
+		$path = explode('/', $root.'/'.$file);
100 100
 
101 101
 		$fileNameSCSS = array_pop($path);
102 102
 		$fileNameCSS = $this->prependBaseurlPrefix(str_replace('.scss', '.css', $fileNameSCSS));
@@ -120,13 +120,13 @@  discard block
 block discarded – undo
120 120
 
121 121
 		try {
122 122
 			$folder = $this->appData->getFolder($app);
123
-		} catch(NotFoundException $e) {
123
+		} catch (NotFoundException $e) {
124 124
 			// creating css appdata folder
125 125
 			$folder = $this->appData->newFolder($app);
126 126
 		}
127 127
 
128 128
 
129
-		if(!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
129
+		if (!$this->variablesChanged() && $this->isCached($fileNameCSS, $folder)) {
130 130
 			return true;
131 131
 		}
132 132
 		return $this->cache($path, $fileNameCSS, $fileNameSCSS, $folder, $webDir);
@@ -152,13 +152,13 @@  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
 
@@ -169,7 +169,7 @@  discard block
 block discarded – undo
169 169
 				}
170 170
 			}
171 171
 			return true;
172
-		} catch(NotFoundException $e) {
172
+		} catch (NotFoundException $e) {
173 173
 			return false;
174 174
 		}
175 175
 	}
@@ -180,7 +180,7 @@  discard block
 block discarded – undo
180 180
 	 */
181 181
 	private function variablesChanged() {
182 182
 		$injectedVariables = $this->getInjectedVariables();
183
-		if($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
183
+		if ($this->config->getAppValue('core', 'scss.variables') !== md5($injectedVariables)) {
184 184
 			$this->resetCache();
185 185
 			$this->config->setAppValue('core', 'scss.variables', md5($injectedVariables));
186 186
 			return true;
@@ -201,11 +201,11 @@  discard block
 block discarded – undo
201 201
 		$scss = new Compiler();
202 202
 		$scss->setImportPaths([
203 203
 			$path,
204
-			\OC::$SERVERROOT . '/core/css/',
204
+			\OC::$SERVERROOT.'/core/css/',
205 205
 		]);
206 206
 		// Continue after throw
207 207
 		$scss->setIgnoreErrors(true);
208
-		if($this->config->getSystemValue('debug')) {
208
+		if ($this->config->getSystemValue('debug')) {
209 209
 			// Debug mode
210 210
 			$scss->setFormatter(Expanded::class);
211 211
 			$scss->setLineNumberStyle(Compiler::LINE_COMMENTS);
@@ -216,11 +216,11 @@  discard block
 block discarded – undo
216 216
 
217 217
 		try {
218 218
 			$cachedfile = $folder->getFile($fileNameCSS);
219
-		} catch(NotFoundException $e) {
219
+		} catch (NotFoundException $e) {
220 220
 			$cachedfile = $folder->newFile($fileNameCSS);
221 221
 		}
222 222
 
223
-		$depFileName = $fileNameCSS . '.deps';
223
+		$depFileName = $fileNameCSS.'.deps';
224 224
 		try {
225 225
 			$depFile = $folder->getFile($depFileName);
226 226
 		} catch (NotFoundException $e) {
@@ -230,19 +230,19 @@  discard block
 block discarded – undo
230 230
 		// Compile
231 231
 		try {
232 232
 			$compiledScss = $scss->compile(
233
-				'@import "variables.scss";' .
234
-				$this->getInjectedVariables() .
233
+				'@import "variables.scss";'.
234
+				$this->getInjectedVariables().
235 235
 				'@import "'.$fileNameSCSS.'";');
236
-		} catch(ParserException $e) {
236
+		} catch (ParserException $e) {
237 237
 			$this->logger->error($e, ['app' => 'core']);
238 238
 			return false;
239 239
 		}
240 240
 
241 241
 		// Gzip file
242 242
 		try {
243
-			$gzipFile = $folder->getFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
243
+			$gzipFile = $folder->getFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
244 244
 		} catch (NotFoundException $e) {
245
-			$gzipFile = $folder->newFile($fileNameCSS . '.gzip'); # Safari doesn't like .gz
245
+			$gzipFile = $folder->newFile($fileNameCSS.'.gzip'); # Safari doesn't like .gz
246 246
 		}
247 247
 
248 248
 		try {
@@ -250,11 +250,11 @@  discard block
 block discarded – undo
250 250
 			$cachedfile->putContent($data);
251 251
 			$deps = json_encode($scss->getParsedFiles());
252 252
 			$depFile->putContent($deps);
253
-			$this->depsCache->set($folder->getName() . '-' . $depFileName, $deps);
253
+			$this->depsCache->set($folder->getName().'-'.$depFileName, $deps);
254 254
 			$gzipFile->putContent(gzencode($data, 9));
255 255
 			$this->logger->debug($webDir.'/'.$fileNameSCSS.' compiled and successfully cached', ['app' => 'core']);
256 256
 			return true;
257
-		} catch(NotPermittedException $e) {
257
+		} catch (NotPermittedException $e) {
258 258
 			return false;
259 259
 		}
260 260
 	}
@@ -265,7 +265,7 @@  discard block
 block discarded – undo
265 265
 	 */
266 266
 	private function resetCache() {
267 267
 		$appDirectory = $this->appData->getDirectoryListing();
268
-		if(empty($appDirectory)){
268
+		if (empty($appDirectory)) {
269 269
 			return;
270 270
 		}
271 271
 		foreach ($appDirectory as $folder) {
@@ -283,7 +283,7 @@  discard block
 block discarded – undo
283 283
 	private function getInjectedVariables() {
284 284
 		$variables = '';
285 285
 		foreach ($this->defaults->getScssVariables() as $key => $value) {
286
-			$variables .= '$' . $key . ': ' . $value . ';';
286
+			$variables .= '$'.$key.': '.$value.';';
287 287
 		}
288 288
 		return $variables;
289 289
 	}
@@ -321,6 +321,6 @@  discard block
 block discarded – undo
321 321
 	 */
322 322
 	private function prependBaseurlPrefix($cssFile) {
323 323
 		$frontendController = ($this->config->getSystemValue('htaccess.IgnoreFrontController', false) === true || getenv('front_controller_active') === 'true');
324
-		return substr(md5($this->urlGenerator->getBaseUrl() . $frontendController), 0, 8) . '-' . $cssFile;
324
+		return substr(md5($this->urlGenerator->getBaseUrl().$frontendController), 0, 8).'-'.$cssFile;
325 325
 	}
326 326
 }
Please login to merge, or discard this patch.