PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.5.4
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.5.4
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 / ImportProcessor.php

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

218 lines 7.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class Minify_ImportProcessor
4 * @package Minify
5 */
6
7 /**
8 * Linearize a CSS/JS file by including content specified by CSS import
9 * declarations. In CSS files, relative URIs are fixed.
10 *
11 * @imports will be processed regardless of where they appear in the source
12 * files; i.e. @imports commented out or in string content will still be
13 * processed!
14 *
15 * This has a unit test but should be considered "experimental".
16 *
17 * @package Minify
18 * @author Stephen Clay <[email protected]>
19 * @author Simon Schick <[email protected]>
20 */
21 class Minify_ImportProcessor
22 {
23 public static $filesIncluded = array();
24
25 public static function process($file)
26 {
27 self::$filesIncluded = array();
28 self::$_isCss = (strtolower(substr($file, -4)) === '.css');
29 $obj = new Minify_ImportProcessor(dirname($file));
30
31 return $obj->_getContent($file);
32 }
33
34 // allows callback funcs to know the current directory
35 private $_currentDir;
36
37 // allows callback funcs to know the directory of the file that inherits this one
38 private $_previewsDir;
39
40 // allows _importCB to write the fetched content back to the obj
41 private $_importedContent = '';
42
43 private static $_isCss;
44
45 /**
46 * @param String $currentDir
47 * @param String $previewsDir Is only used internally
48 */
49 private function __construct($currentDir, $previewsDir = "")
50 {
51 $this->_currentDir = $currentDir;
52 $this->_previewsDir = $previewsDir;
53 }
54
55 private function _getContent($file, $is_imported = false)
56 {
57 $file = preg_replace('~\\?.*~', '', $file);
58 $file = realpath($file);
59 if (! $file
60 || in_array($file, self::$filesIncluded)
61 || false === ($content = @file_get_contents($file))) {
62 // file missing, already included, or failed read
63 return '';
64 }
65 self::$filesIncluded[] = realpath($file);
66 $this->_currentDir = dirname($file);
67
68 // remove UTF-8 BOM if present
69 if (pack("CCC", 0xef, 0xbb, 0xbf) === substr($content, 0, 3)) {
70 $content = substr($content, 3);
71 }
72 // ensure uniform EOLs
73 $content = str_replace("\r\n", "\n", $content);
74
75 // process @imports
76 $pattern = '/
77 @import\\s+
78 (?:url\\(\\s*)? # maybe url(
79 [\'"]? # maybe quote
80 (.*?) # 1 = URI
81 [\'"]? # maybe end quote
82 (?:\\s*\\))? # maybe )
83 ([a-zA-Z,\\s]*)? # 2 = media list
84 ; # end token
85 /x';
86 $content = preg_replace_callback($pattern, array($this, '_importCB'), $content);
87
88 // You only need to rework the import-path if the script is imported
89 if (self::$_isCss && $is_imported) {
90 // rewrite remaining relative URIs
91 $pattern = '/url\\(\\s*([^\\)\\s]+)\\s*\\)/';
92 $content = preg_replace_callback($pattern, array($this, '_urlCB'), $content);
93 }
94
95 return $this->_importedContent . $content;
96 }
97
98 private function _importCB($m)
99 {
100 $url = $m[1];
101 $mediaList = preg_replace('/\\s+/', '', $m[2]);
102
103 if (strpos($url, '://') > 0) {
104 // protocol, leave in place for CSS, comment for JS
105 return self::$_isCss
106 ? $m[0]
107 : "/* Minify_ImportProcessor will not include remote content */";
108 }
109 if ('/' === $url[0]) {
110 // protocol-relative or root path
111 $url = ltrim($url, '/');
112 $file = realpath($_SERVER['DOCUMENT_ROOT']) . DIRECTORY_SEPARATOR
113 . strtr($url, '/', DIRECTORY_SEPARATOR);
114 } else {
115 // relative to current path
116 $file = $this->_currentDir . DIRECTORY_SEPARATOR
117 . strtr($url, '/', DIRECTORY_SEPARATOR);
118 }
119 $obj = new Minify_ImportProcessor(dirname($file), $this->_currentDir);
120 $content = $obj->_getContent($file, true);
121 if ('' === $content) {
122 // failed. leave in place for CSS, comment for JS
123 return self::$_isCss
124 ? $m[0]
125 : "/* Minify_ImportProcessor could not fetch '{$file}' */";
126 }
127
128 return (!self::$_isCss || preg_match('@(?:^$|\\ball\\b)@', $mediaList))
129 ? $content
130 : "@media {$mediaList} {\n{$content}\n}\n";
131 }
132
133 private function _urlCB($m)
134 {
135 // $m[1] is either quoted or not
136 $quote = ($m[1][0] === "'" || $m[1][0] === '"') ? $m[1][0] : '';
137
138 $url = ($quote === '') ? $m[1] : substr($m[1], 1, strlen($m[1]) - 2);
139
140 if ('/' !== $url[0]) {
141 if (strpos($url, '//') > 0) {
142 // probably starts with protocol, do not alter
143 } else {
144 // prepend path with current dir separator (OS-independent)
145 $path = $this->_currentDir
146 . DIRECTORY_SEPARATOR . strtr($url, '/', DIRECTORY_SEPARATOR);
147 // update the relative path by the directory of the file that imported this one
148 $url = self::getPathDiff(realpath($this->_previewsDir), $path);
149 }
150 }
151
152 return "url({$quote}{$url}{$quote})";
153 }
154
155 /**
156 * @param string $from
157 * @param string $to
158 * @param string $ps
159 * @return string
160 */
161 private function getPathDiff($from, $to, $ps = DIRECTORY_SEPARATOR)
162 {
163 $realFrom = $this->truepath($from);
164 $realTo = $this->truepath($to);
165
166 $arFrom = explode($ps, rtrim($realFrom, $ps));
167 $arTo = explode($ps, rtrim($realTo, $ps));
168 while (count($arFrom) && count($arTo) && ($arFrom[0] == $arTo[0])) {
169 array_shift($arFrom);
170 array_shift($arTo);
171 }
172
173 return str_pad("", count($arFrom) * 3, '..' . $ps) . implode($ps, $arTo);
174 }
175
176 /**
177 * This function is to replace PHP's extremely buggy realpath().
178 * @param string $path The original path, can be relative etc.
179 * @return string The resolved path, it might not exist.
180 * @see http://stackoverflow.com/questions/4049856/replace-phps-realpath
181 */
182 private function truepath($path)
183 {
184 // whether $path is unix or not
185 $unipath = ('' === $path) || ($path[0] !== '/');
186
187 // attempts to detect if path is relative in which case, add cwd
188 if (strpos($path, ':') === false && $unipath) {
189 $path = $this->_currentDir . DIRECTORY_SEPARATOR . $path;
190 }
191
192 // resolve path parts (single dot, double dot and double delimiters)
193 $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
194 $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
195 $absolutes = array();
196 foreach ($parts as $part) {
197 if ('.' === $part) {
198 continue;
199 }
200 if ('..' === $part) {
201 array_pop($absolutes);
202 } else {
203 $absolutes[] = $part;
204 }
205 }
206
207 $path = implode(DIRECTORY_SEPARATOR, $absolutes);
208 // resolve any symlinks
209 if (file_exists($path) && linkinfo($path) > 0) {
210 $path = readlink($path);
211 }
212 // put initial separator that could have been lost
213 $path = !$unipath ? '/' . $path : $path;
214
215 return $path;
216 }
217 }
218