PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / vendor / mrclay / minify / lib / Minify / CSS / UriRewriter.php

UriRewriter.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.7.0, at vendor/mrclay/minify/lib/Minify/CSS/UriRewriter.php

359 lines 10.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Minify_CSS_UriRewriter
4 * @package Minify
5 */
6
7 /**
8 * Rewrite file-relative URIs as root-relative in CSS files
9 *
10 * @package Minify
11 * @author Stephen Clay <[email protected]>
12 */
13 class Minify_CSS_UriRewriter
14 {
15
16 /**
17 * rewrite() and rewriteRelative() append debugging information here
18 *
19 * @var string
20 */
21 public static $debugText = '';
22
23 /**
24 * In CSS content, rewrite file relative URIs as root relative
25 *
26 * @param string $css
27 *
28 * @param string $currentDir The directory of the current CSS file.
29 *
30 * @param string $docRoot The document root of the web site in which
31 * the CSS file resides (default = $_SERVER['DOCUMENT_ROOT']).
32 *
33 * @param array $symlinks (default = array()) If the CSS file is stored in
34 * a symlink-ed directory, provide an array of link paths to
35 * target paths, where the link paths are within the document root. Because
36 * paths need to be normalized for this to work, use "//" to substitute
37 * the doc root in the link paths (the array keys). E.g.:
38 * <code>
39 * array('//symlink' => '/real/target/path') // unix
40 * array('//static' => 'D:\\staticStorage') // Windows
41 * </code>
42 *
43 * @return string
44 */
45 public static function rewrite($css, $currentDir, $docRoot = null, $symlinks = array())
46 {
47 self::$_docRoot = self::_realpath(
48 $docRoot ? $docRoot : $_SERVER['DOCUMENT_ROOT']
49 );
50 self::$_currentDir = self::_realpath($currentDir);
51 self::$_symlinks = array();
52
53 // normalize symlinks in order to map to link
54 foreach ($symlinks as $link => $target) {
55 $link = ($link === '//') ? self::$_docRoot : str_replace('//', self::$_docRoot . '/', $link);
56 $link = strtr($link, '/', DIRECTORY_SEPARATOR);
57
58 self::$_symlinks[$link] = self::_realpath($target);
59 }
60
61 self::$debugText .= "docRoot : " . self::$_docRoot . "\n"
62 . "currentDir : " . self::$_currentDir . "\n";
63 if (self::$_symlinks) {
64 self::$debugText .= "symlinks : " . var_export(self::$_symlinks, 1) . "\n";
65 }
66 self::$debugText .= "\n";
67
68 $css = self::_trimUrls($css);
69
70 $css = self::_owlifySvgPaths($css);
71
72 // rewrite
73 $pattern = '/@import\\s+([\'"])(.*?)[\'"]/';
74 $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
75
76 $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/';
77 $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
78
79 $css = self::_unOwlify($css);
80
81 return $css;
82 }
83
84 /**
85 * In CSS content, prepend a path to relative URIs
86 *
87 * @param string $css
88 *
89 * @param string $path The path to prepend.
90 *
91 * @return string
92 */
93 public static function prepend($css, $path)
94 {
95 self::$_prependPath = $path;
96
97 $css = self::_trimUrls($css);
98
99 $css = self::_owlifySvgPaths($css);
100
101 // append
102 $pattern = '/@import\\s+([\'"])(.*?)[\'"]/';
103 $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
104
105 $pattern = '/url\\(\\s*([\'"](.*?)[\'"]|[^\\)\\s]+)\\s*\\)/';
106 $css = preg_replace_callback($pattern, array(self::$className, '_processUriCB'), $css);
107
108 $css = self::_unOwlify($css);
109
110 self::$_prependPath = null;
111
112 return $css;
113 }
114
115 /**
116 * Get a root relative URI from a file relative URI
117 *
118 * <code>
119 * Minify_CSS_UriRewriter::rewriteRelative(
120 * '../img/hello.gif'
121 * , '/home/user/www/css' // path of CSS file
122 * , '/home/user/www' // doc root
123 * );
124 * // returns '/img/hello.gif'
125 *
126 * // example where static files are stored in a symlinked directory
127 * Minify_CSS_UriRewriter::rewriteRelative(
128 * 'hello.gif'
129 * , '/var/staticFiles/theme'
130 * , '/home/user/www'
131 * , array('/home/user/www/static' => '/var/staticFiles')
132 * );
133 * // returns '/static/theme/hello.gif'
134 * </code>
135 *
136 * @param string $uri file relative URI
137 *
138 * @param string $realCurrentDir realpath of the current file's directory.
139 *
140 * @param string $realDocRoot realpath of the site document root.
141 *
142 * @param array $symlinks (default = array()) If the file is stored in
143 * a symlink-ed directory, provide an array of link paths to
144 * real target paths, where the link paths "appear" to be within the document
145 * root. E.g.:
146 * <code>
147 * array('/home/foo/www/not/real/path' => '/real/target/path') // unix
148 * array('C:\\htdocs\\not\\real' => 'D:\\real\\target\\path') // Windows
149 * </code>
150 *
151 * @return string
152 */
153 public static function rewriteRelative($uri, $realCurrentDir, $realDocRoot, $symlinks = array())
154 {
155 // prepend path with current dir separator (OS-independent)
156 $path = strtr($realCurrentDir, '/', DIRECTORY_SEPARATOR);
157 $path .= DIRECTORY_SEPARATOR . strtr($uri, '/', DIRECTORY_SEPARATOR);
158
159 self::$debugText .= "file-relative URI : {$uri}\n"
160 . "path prepended : {$path}\n";
161
162 // "unresolve" a symlink back to doc root
163 foreach ($symlinks as $link => $target) {
164 if (0 === strpos($path, $target)) {
165 // replace $target with $link
166 $path = $link . substr($path, strlen($target));
167
168 self::$debugText .= "symlink unresolved : {$path}\n";
169
170 break;
171 }
172 }
173 // strip doc root
174 $path = substr($path, strlen($realDocRoot));
175
176 self::$debugText .= "docroot stripped : {$path}\n";
177
178 // fix to root-relative URI
179 $uri = strtr($path, '/\\', '//');
180 $uri = self::removeDots($uri);
181
182 self::$debugText .= "traversals removed : {$uri}\n\n";
183
184 return $uri;
185 }
186
187 /**
188 * Remove instances of "./" and "../" where possible from a root-relative URI
189 *
190 * @param string $uri
191 *
192 * @return string
193 */
194 public static function removeDots($uri)
195 {
196 $uri = str_replace('/./', '/', $uri);
197 // inspired by patch from Oleg Cherniy
198 do {
199 $uri = preg_replace('@/[^/]+/\\.\\./@', '/', $uri, 1, $changed);
200 } while ($changed);
201
202 return $uri;
203 }
204
205 /**
206 * Defines which class to call as part of callbacks, change this
207 * if you extend Minify_CSS_UriRewriter
208 *
209 * @var string
210 */
211 protected static $className = 'Minify_CSS_UriRewriter';
212
213 /**
214 * Get realpath with any trailing slash removed. If realpath() fails,
215 * just remove the trailing slash.
216 *
217 * @param string $path
218 *
219 * @return mixed path with no trailing slash
220 */
221 protected static function _realpath($path)
222 {
223 $realPath = realpath($path);
224 if ($realPath !== false) {
225 $path = $realPath;
226 }
227
228 return rtrim($path, '/\\');
229 }
230
231 /**
232 * Directory of this stylesheet
233 *
234 * @var string
235 */
236 private static $_currentDir = '';
237
238 /**
239 * DOC_ROOT
240 *
241 * @var string
242 */
243 private static $_docRoot = '';
244
245 /**
246 * directory replacements to map symlink targets back to their
247 * source (within the document root) E.g. '/var/www/symlink' => '/var/realpath'
248 *
249 * @var array
250 */
251 private static $_symlinks = array();
252
253 /**
254 * Path to prepend
255 *
256 * @var string
257 */
258 private static $_prependPath = null;
259
260 /**
261 * @param string $css
262 *
263 * @return string
264 */
265 private static function _trimUrls($css)
266 {
267 $pattern = '/
268 url\\( # url(
269 \\s*
270 ([^\\)]+?) # 1 = URI (assuming does not contain ")")
271 \\s*
272 \\) # )
273 /x';
274
275 return preg_replace($pattern, 'url($1)', $css);
276 }
277
278 /**
279 * @param array $m
280 *
281 * @return string
282 */
283 private static function _processUriCB($m)
284 {
285 // $m matched either '/@import\\s+([\'"])(.*?)[\'"]/' or '/url\\(\\s*([^\\)\\s]+)\\s*\\)/'
286 $isImport = ($m[0][0] === '@');
287 // determine URI and the quote character (if any)
288 if ($isImport) {
289 $quoteChar = $m[1];
290 $uri = $m[2];
291 } else {
292 // $m[1] is either quoted or not
293 $quoteChar = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : '';
294
295 $uri = ($quoteChar === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2);
296 }
297
298 if ($uri === '') {
299 return $m[0];
300 }
301
302 // if not root/scheme relative and not starts with scheme
303 if (!preg_match('~^(/|[a-z]+\:)~', $uri)) {
304 // URI is file-relative: rewrite depending on options
305 if (self::$_prependPath === null) {
306 $uri = self::rewriteRelative($uri, self::$_currentDir, self::$_docRoot, self::$_symlinks);
307 } else {
308 $uri = self::$_prependPath . $uri;
309 if ($uri[0] === '/') {
310 $root = '';
311 $rootRelative = $uri;
312 $uri = $root . self::removeDots($rootRelative);
313 } elseif (preg_match('@^((https?\:)?//([^/]+))/@', $uri, $m) && (false !== strpos($m[3], '.'))) {
314 $root = $m[1];
315 $rootRelative = substr($uri, strlen($root));
316 $uri = $root . self::removeDots($rootRelative);
317 }
318 }
319 }
320
321 if ($isImport) {
322 return "@import {$quoteChar}{$uri}{$quoteChar}";
323 } else {
324 return "url({$quoteChar}{$uri}{$quoteChar})";
325 }
326 }
327
328 /**
329 * Mungs some inline SVG URL declarations so they won't be touched
330 *
331 * @link https://github.com/mrclay/minify/issues/517
332 * @see _unOwlify
333 *
334 * @param string $css
335 * @return string
336 */
337 private static function _owlifySvgPaths($css)
338 {
339 $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)url(\(\s*#\w+\s*\))~';
340
341 return preg_replace($pattern, '$1owl$2', $css);
342 }
343
344 /**
345 * Undo work of _owlify
346 *
347 * @see _owlifySvgPaths
348 *
349 * @param string $css
350 * @return string
351 */
352 private static function _unOwlify($css)
353 {
354 $pattern = '~\b((?:clip-path|mask|-webkit-mask)\s*\:\s*)owl~';
355
356 return preg_replace($pattern, '$1url', $css);
357 }
358 }
359