PluginProbe
Autoptimize / 2.3.0
Autoptimize v2.3.0
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
autoptimize / classes / autoptimizeBase.php

autoptimizeBase.php in Autoptimize 2.3.0, at classes/autoptimizeBase.php

419 lines 15.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4 abstract class autoptimizeBase {
5 protected $content = '';
6 protected $tagWarning = false;
7
8 public function __construct($content) {
9 $this->content = $content;
10 }
11
12 //Reads the page and collects tags
13 abstract public function read($justhead);
14
15 //Joins and optimizes collected things
16 abstract public function minify();
17
18 //Caches the things
19 abstract public function cache();
20
21 //Returns the content
22 abstract public function getcontent();
23
24 //Converts an URL to a full path
25 protected function getpath($url) {
26 $url=apply_filters( 'autoptimize_filter_cssjs_alter_url', $url);
27
28 if (strpos($url,'%')!==false) {
29 $url=urldecode($url);
30 }
31
32 $siteHost=parse_url(AUTOPTIMIZE_WP_SITE_URL,PHP_URL_HOST);
33 $contentHost=parse_url(AUTOPTIMIZE_WP_ROOT_URL,PHP_URL_HOST);
34
35 // normalize
36 if (strpos($url,'//')===0) {
37 if (is_ssl()) {
38 $url = "https:".$url;
39 } else {
40 $url = "http:".$url;
41 }
42 } else if ((strpos($url,'//')===false) && (strpos($url,$siteHost)===false)) {
43 if (AUTOPTIMIZE_WP_SITE_URL === $siteHost) {
44 $url = AUTOPTIMIZE_WP_SITE_URL.$url;
45 } else {
46 $subdir_levels=substr_count(preg_replace("/https?:\/\//","",AUTOPTIMIZE_WP_SITE_URL),"/");
47 $url = AUTOPTIMIZE_WP_SITE_URL.str_repeat("/..",$subdir_levels).$url;
48 }
49 }
50
51 if ($siteHost !== $contentHost) {
52 $url=str_replace(AUTOPTIMIZE_WP_CONTENT_URL,AUTOPTIMIZE_WP_SITE_URL.AUTOPTIMIZE_WP_CONTENT_NAME,$url);
53 }
54
55 // first check; hostname wp site should be hostname of url
56 $thisHost=@parse_url($url,PHP_URL_HOST);
57 if ($thisHost !== $siteHost) {
58 /*
59 * first try to get all domains from WPML (if available)
60 * then explicitely declare $this->cdn_url as OK as well
61 * then apply own filter autoptimize_filter_cssjs_multidomain takes an array of hostnames
62 * each item in that array will be considered part of the same WP multisite installation
63 */
64 $multidomains = array();
65
66 $multidomainsWPML = apply_filters('wpml_setting', array(), 'language_domains');
67 if (!empty($multidomainsWPML)) {
68 $multidomains = array_map(array($this,"ao_getDomain"),$multidomainsWPML);
69 }
70
71 if (!empty($this->cdn_url)) {
72 $multidomains[]=parse_url($this->cdn_url,PHP_URL_HOST);
73 }
74
75 $multidomains = apply_filters('autoptimize_filter_cssjs_multidomain', $multidomains);
76
77 if (!empty($multidomains)) {
78 if (in_array($thisHost,$multidomains)) {
79 $url=str_replace($thisHost, parse_url(AUTOPTIMIZE_WP_SITE_URL,PHP_URL_HOST), $url);
80 } else {
81 return false;
82 }
83 } else {
84 return false;
85 }
86 }
87
88 // try to remove "wp root url" from url while not minding http<>https
89 $tmp_ao_root = preg_replace('/https?:/','',AUTOPTIMIZE_WP_ROOT_URL);
90 if ($siteHost !== $contentHost) {
91 // as we replaced the content-domain with the site-domain, we should match against that
92 $tmp_ao_root = preg_replace('/https?:/','',AUTOPTIMIZE_WP_SITE_URL);
93 }
94 $tmp_url = preg_replace('/https?:/','',$url);
95 $path = str_replace($tmp_ao_root,'',$tmp_url);
96
97 // if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate
98 if (preg_match('#^:?//#',$path)) {
99 /** External script/css (adsense, etc) */
100 return false;
101 }
102
103 // prepend with WP_ROOT_DIR to have full path to file
104 $path = str_replace('//','/',WP_ROOT_DIR.$path);
105
106 // final check: does file exist and is it readable
107 if (file_exists($path) && is_file($path) && is_readable($path)) {
108 return $path;
109 } else {
110 return false;
111 }
112 }
113
114 // needed for WPML-filter
115 protected function ao_getDomain($in) {
116 // make sure the url starts with something vaguely resembling a protocol
117 if ((strpos($in,"http")!==0) && (strpos($in,"//")!==0)) {
118 $in="http://".$in;
119 }
120
121 // do the actual parse_url
122 $out = parse_url($in,PHP_URL_HOST);
123
124 // fallback if parse_url does not understand the url is in fact a url
125 if (empty($out)) $out=$in;
126
127 return $out;
128 }
129
130
131 // logger
132 protected function ao_logger($logmsg,$appendHTML=true) {
133 if ($appendHTML) {
134 $logmsg="<!--noptimize--><!-- ".$logmsg." --><!--/noptimize-->";
135 $this->content.=$logmsg;
136 } else {
137 error_log("Autoptimize: ".$logmsg);
138 }
139 }
140
141 // hide everything between noptimize-comment tags
142 protected function hide_noptimize($noptimize_in) {
143 if ( preg_match( '/<!--\s?noptimize\s?-->/', $noptimize_in ) ) {
144 $noptimize_out = preg_replace_callback(
145 '#<!--\s?noptimize\s?-->.*?<!--\s?/\s?noptimize\s?-->#is',
146 create_function(
147 '$matches',
148 'return "%%NOPTIMIZE".AUTOPTIMIZE_HASH."%%".base64_encode($matches[0])."%%NOPTIMIZE%%";'
149 ),
150 $noptimize_in
151 );
152 } else {
153 $noptimize_out = $noptimize_in;
154 }
155 return $noptimize_out;
156 }
157
158 // unhide noptimize-tags
159 protected function restore_noptimize($noptimize_in) {
160 if ( strpos( $noptimize_in, '%%NOPTIMIZE%%' ) !== false ) {
161 $noptimize_out = preg_replace_callback(
162 '#%%NOPTIMIZE'.AUTOPTIMIZE_HASH.'%%(.*?)%%NOPTIMIZE%%#is',
163 create_function(
164 '$matches',
165 'return base64_decode($matches[1]);'
166 ),
167 $noptimize_in
168 );
169 } else {
170 $noptimize_out = $noptimize_in;
171 }
172 return $noptimize_out;
173 }
174
175 protected function hide_iehacks($iehacks_in) {
176 if ( strpos( $iehacks_in, '<!--[if' ) !== false ) {
177 $iehacks_out = preg_replace_callback(
178 '#<!--\[if.*?\[endif\]-->#is',
179 create_function(
180 '$matches',
181 'return "%%IEHACK".AUTOPTIMIZE_HASH."%%".base64_encode($matches[0])."%%IEHACK%%";'
182 ),
183 $iehacks_in
184 );
185 } else {
186 $iehacks_out = $iehacks_in;
187 }
188 return $iehacks_out;
189 }
190
191 protected function restore_iehacks($iehacks_in) {
192 if ( strpos( $iehacks_in, '%%IEHACK%%' ) !== false ) {
193 $iehacks_out = preg_replace_callback(
194 '#%%IEHACK'.AUTOPTIMIZE_HASH.'%%(.*?)%%IEHACK%%#is',
195 create_function(
196 '$matches',
197 'return base64_decode($matches[1]);'
198 ),
199 $iehacks_in
200 );
201 } else {
202 $iehacks_out=$iehacks_in;
203 }
204 return $iehacks_out;
205 }
206
207 protected function hide_comments($comments_in) {
208 if ( strpos( $comments_in, '<!--' ) !== false ) {
209 $comments_out = preg_replace_callback(
210 '#<!--.*?-->#is',
211 create_function(
212 '$matches',
213 'return "%%COMMENTS".AUTOPTIMIZE_HASH."%%".base64_encode($matches[0])."%%COMMENTS%%";'
214 ),
215 $comments_in
216 );
217 } else {
218 $comments_out = $comments_in;
219 }
220 return $comments_out;
221 }
222
223 protected function restore_comments($comments_in) {
224 if ( strpos( $comments_in, '%%COMMENTS%%' ) !== false ) {
225 $comments_out = preg_replace_callback(
226 '#%%COMMENTS'.AUTOPTIMIZE_HASH.'%%(.*?)%%COMMENTS%%#is',
227 create_function(
228 '$matches',
229 'return base64_decode($matches[1]);'
230 ),
231 $comments_in
232 );
233 } else {
234 $comments_out=$comments_in;
235 }
236 return $comments_out;
237 }
238
239 protected function url_replace_cdn( $url ) {
240 // API filter to change base CDN URL
241 $cdn_url = apply_filters( 'autoptimize_filter_base_cdnurl', $this->cdn_url );
242
243 if ( !empty($cdn_url) ) {
244 // prepend domain-less absolute URL's
245 if ( ( substr( $url, 0, 1 ) === '/' ) && ( substr( $url, 1, 1 ) !== '/' ) ) {
246 $url = rtrim( $cdn_url, '/' ) . $url;
247 } else {
248 // get wordpress base URL
249 $WPSiteBreakdown = parse_url( AUTOPTIMIZE_WP_SITE_URL );
250 $WPBaseUrl = $WPSiteBreakdown['scheme'] . '://' . $WPSiteBreakdown['host'];
251 if ( ! empty( $WPSiteBreakdown['port'] ) ) {
252 $WPBaseUrl .= ":" . $WPSiteBreakdown['port'];
253 }
254 // replace full url's with scheme
255 $tmp_url = str_replace( $WPBaseUrl, rtrim( $cdn_url, '/' ), $url );
256 if ( $tmp_url === $url ) {
257 // last attempt; replace scheme-less URL's
258 $url = str_replace( preg_replace( '/https?:/', '', $WPBaseUrl ), rtrim( $cdn_url, '/' ), $url );
259 } else {
260 $url = $tmp_url;
261 }
262 }
263 }
264
265 // allow API filter to alter URL after CDN replacement
266 $url = apply_filters( 'autoptimize_filter_base_replace_cdn', $url );
267 return $url;
268 }
269
270 protected function inject_in_html($payload,$replaceTag) {
271 if (strpos($this->content,$replaceTag[0])!== false) {
272 if ($replaceTag[1]==="after") {
273 $replaceBlock=$replaceTag[0].$payload;
274 } else if ($replaceTag[1]==="replace"){
275 $replaceBlock=$payload;
276 } else {
277 $replaceBlock=$payload.$replaceTag[0];
278 }
279 $this->content = substr_replace($this->content,$replaceBlock,strpos($this->content,$replaceTag[0]),strlen($replaceTag[0]));
280 } else {
281 $this->content .= $payload;
282 if (!$this->tagWarning) {
283 $this->content .= "<!--noptimize--><!-- Autoptimize found a problem with the HTML in your Theme, tag \"".str_replace(array("<",">"),"",$replaceTag[0])."\" missing --><!--/noptimize-->";
284 $this->tagWarning=true;
285 }
286 }
287 }
288
289 protected function isremovable($tag, $removables) {
290 foreach ($removables as $match) {
291 if (strpos($tag,$match)!==false) {
292 return true;
293 }
294 }
295 return false;
296 }
297
298 // inject already minified code in optimized JS/CSS
299 protected function inject_minified($in) {
300 if ( strpos( $in, '%%INJECTLATER%%' ) !== false ) {
301 $out = preg_replace_callback(
302 '#\/\*\!%%INJECTLATER'.AUTOPTIMIZE_HASH.'%%(.*?)%%INJECTLATER%%\*\/#is',
303 create_function(
304 '$matches',
305 '$filepath=base64_decode(strtok($matches[1],"|"));
306 $filecontent=file_get_contents($filepath);
307
308 // remove BOM
309 $filecontent = preg_replace("#\x{EF}\x{BB}\x{BF}#","",$filecontent);
310
311 // remove comments and blank lines
312 if (substr($filepath,-3,3)===".js") {
313 $filecontent=preg_replace("#^\s*\/\/.*$#Um","",$filecontent);
314 }
315
316 $filecontent=preg_replace("#^\s*\/\*[^!].*\*\/\s?#Um","",$filecontent);
317 $filecontent=preg_replace("#(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+#", "\n", $filecontent);
318
319 // differentiate between JS, CSS and other files
320 if (substr($filepath,-3,3)===".js") {
321 if ((substr($filecontent,-1,1)!==";")&&(substr($filecontent,-1,1)!=="}")) {
322 $filecontent.=";";
323 }
324
325 if (get_option("autoptimize_js_trycatch")==="on") {
326 $filecontent="try{".$filecontent."}catch(e){}";
327 }
328 } else if ((substr($filepath,-4,4)===".css")) {
329 $filecontent=autoptimizeStyles::fixurls($filepath,$filecontent);
330 } else {
331 $filecontent="";
332 }
333
334 // return
335 return "\n".$filecontent;'
336 ),
337 $in
338 );
339 } else {
340 $out = $in;
341 }
342 return $out;
343 }
344
345 protected function minify_single($pathIn) {
346 // determine JS or CSS and set var (also mimetype), return false if neither
347 if ( $this->str_ends_in($pathIn,".js") === true ) {
348 $codeType="js";
349 $codeMime="text/javascript";
350 } else if ( $this->str_ends_in($pathIn,".css") === true ) {
351 $codeType="css";
352 $codeMime="text/css";
353 } else {
354 return false;
355 }
356
357 // if min.js or min.css return false
358 if (( $this->str_ends_in($pathIn,"-min.".$codeType) === true ) || ( $this->str_ends_in($pathIn,".min.".$codeType) === true ) || ( $this->str_ends_in($pathIn,"js/jquery/jquery.js") === true ) ) {
359 return false;
360 }
361
362 // read file, return false if empty
363 $_toMinify = file_get_contents($pathIn);
364 if ( empty($_toMinify) ) return false;
365
366 // check cache
367 $_md5hash = "single_".md5($_toMinify);
368 $_cache = new autoptimizeCache($_md5hash,$codeType);
369 if ($_cache->check() ) {
370 $_CachedMinifiedUrl = AUTOPTIMIZE_CACHE_URL.$_cache->getname();
371 } else {
372 // if not in cache first minify
373 $_Minified = $_toMinify;
374 if ($codeType === "js") {
375 if (class_exists('JSMin') && apply_filters( 'autoptimize_js_do_minify' , true)) {
376 if (@is_callable(array("JSMin","minify"))) {
377 $tmp_code = trim(JSMin::minify($_toMinify));
378 }
379 }
380 } else if ($codeType === "css") {
381 if (class_exists('Minify_CSS_Compressor')) {
382 $tmp_code = trim(Minify_CSS_Compressor::process($_toMinify));
383 } else if(class_exists('CSSmin')) {
384 $cssmin = new CSSmin();
385 if (method_exists($cssmin,"run")) {
386 $tmp_code = trim($cssmin->run($_toMinify));
387 } elseif (@is_callable(array($cssmin,"minify"))) {
388 $tmp_code = trim(CssMin::minify($_toMinify));
389 }
390 }
391 }
392 if (!empty($tmp_code)) {
393 $_Minified = $tmp_code;
394 unset($tmp_code);
395 }
396 // and then cache
397 $_cache->cache($_Minified,$codeMime);
398 $_CachedMinifiedUrl = AUTOPTIMIZE_CACHE_URL.$_cache->getname();
399 }
400 unset($_cache);
401
402 // if CDN, then CDN
403 $_CachedMinifiedUrl = $this->url_replace_cdn($_CachedMinifiedUrl);
404
405 return $_CachedMinifiedUrl;
406 }
407
408 protected function str_ends_in($haystack,$needle) {
409 $needleLength = strlen($needle);
410 $haystackLength = strlen($haystack);
411 $lastPos=strrpos($haystack,$needle);
412 if ($lastPos === $haystackLength - $needleLength) {
413 return true;
414 } else {
415 return false;
416 }
417 }
418 }
419