PluginProbe
Autoptimize / 1.9.3
Autoptimize v1.9.3
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 / autoptimizeScripts.php

autoptimizeScripts.php in Autoptimize 1.9.3, at classes/autoptimizeScripts.php

318 lines 9.6 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 class autoptimizeScripts extends autoptimizeBase {
5 private $scripts = array();
6 private $dontmove = array('document.write','html5.js','show_ads.js','google_ad','blogcatalog.com/w','tweetmeme.com/i','mybloglog.com/','histats.com/js','ads.smowtion.com/ad.js','statcounter.com/counter/counter.js','widgets.amung.us','ws.amazon.com/widgets','media.fastclick.net','/ads/','comment-form-quicktags/quicktags.php','edToolbar','intensedebate.com','scripts.chitika.net/','_gaq.push','jotform.com/','admin-bar.min.js','GoogleAnalyticsObject','plupload.full.min.js','syntaxhighlighter','adsbygoogle','application/ld+json','text/html','text/template','gist.github.com','wp-slimstat.min.js','_stq','nonce','post_id');
7 private $domove = array('gaJsHost','load_cmc','jd.gallery.transitions.js','swfobject.embedSWF(','tiny_mce.js','tinyMCEPreInit.go');
8 private $domovelast = array('addthis.com','/afsonline/show_afs_search.js','disqus.js','networkedblogs.com/getnetworkwidget','infolinks.com/js/','jd.gallery.js.php','jd.gallery.transitions.js','swfobject.embedSWF(','linkwithin.com/widget.js','tiny_mce.js','tinyMCEPreInit.go');
9 private $trycatch = false;
10 private $alreadyminified = false;
11 private $forcehead = false;
12 private $jscode = '';
13 private $url = '';
14 private $move = array('first' => array(), 'last' => array());
15 private $restofcontent = '';
16 private $md5hash = '';
17
18 // Reads the page and collects script tags
19 public function read($options) {
20 $noptimizeJS = apply_filters( 'autoptimize_filter_js_noptimize', false, $this->content );
21 if ($noptimizeJS)
22 return false;
23
24 // Remove everything that's not the header
25 if($options['justhead'] == true) {
26 $content = explode('</head>',$this->content,2);
27 $this->content = $content[0].'</head>';
28 $this->restofcontent = $content[1];
29 }
30
31 $excludeJS = $options['js_exclude'];
32 $excludeJS = apply_filters( 'autoptimize_filter_js_exclude', $excludeJS );
33
34 if ($excludeJS!=="") {
35 $exclJSArr = array_filter(array_map('trim',explode(",",$excludeJS)));
36 $this->dontmove = array_merge($exclJSArr,$this->dontmove);
37 }
38
39 $this->domovelast = apply_filters( 'autoptimize_filter_js_movelast', $this->domovelast );
40
41 //Should we add try-catch?
42 if($options['trycatch'] == true)
43 $this->trycatch = true;
44
45 // force js in head?
46 if($options['forcehead'] == true)
47 $this->forcehead = true;
48
49 // get cdn url
50 $this->cdn_url = $options['cdn_url'];
51
52 // noptimize me
53 $this->content = $this->hide_noptimize($this->content);
54
55 // Save IE hacks
56 $this->content = $this->hide_iehacks($this->content);
57
58 // comments
59 $this->content = $this->hide_comments($this->content);
60
61 //Get script files
62 if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches)) {
63 foreach($matches[0] as $tag) {
64 if(preg_match('#src=("|\')(.*)("|\')#Usmi',$tag,$source)) {
65 //External script
66 $url = current(explode('?',$source[2],2));
67 $path = $this->getpath($url);
68 if($path !== false && preg_match('#\.js$#',$path)) {
69 //Inline
70 if($this->ismergeable($tag)) {
71 //We can merge it
72 $this->scripts[] = $path;
73 } else {
74 //No merge, but maybe we can move it
75 if($this->ismovable($tag)) {
76 //Yeah, move it
77 if($this->movetolast($tag)) {
78 $this->move['last'][] = $tag;
79 } else {
80 $this->move['first'][] = $tag;
81 }
82 } else {
83 //We shouldn't touch this
84 $tag = '';
85 }
86 }
87 } else {
88 //External script (example: google analytics)
89 //OR Script is dynamic (.php etc)
90 if($this->ismovable($tag)) {
91 if($this->movetolast($tag)) {
92 $this->move['last'][] = $tag;
93 } else {
94 $this->move['first'][] = $tag;
95 }
96 } else {
97 //We shouldn't touch this
98 $tag = '';
99 }
100 }
101 } else {
102 // Inline script
103 // unhide comments, as javascript may be wrapped in comment-tags for old times' sake
104 $tag = $this->restore_comments($tag);
105 if($this->ismergeable($tag) && ( apply_filters('autoptimize_js_include_inline',true) )) {
106 preg_match('#<script.*>(.*)</script>#Usmi',$tag,$code);
107 $code = preg_replace('#.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*#sm','$1',$code[1]);
108 $code = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/','',$code);
109 $this->scripts[] = 'INLINE;'.$code;
110 } else {
111 //Can we move this?
112 if($this->ismovable($tag)) {
113 if($this->movetolast($tag)) {
114 $this->move['last'][] = $tag;
115 } else {
116 $this->move['first'][] = $tag;
117 }
118 } else {
119 //We shouldn't touch this
120 $tag = '';
121 }
122 }
123 // re-hide comments to be able to do the removal based on tag from $this->content
124 $tag = $this->hide_comments($tag);
125 }
126
127 //Remove the original script tag
128 $this->content = str_replace($tag,'',$this->content);
129 }
130
131 return true;
132 }
133
134 // No script files, great ;-)
135 return false;
136 }
137
138 //Joins and optimizes JS
139 public function minify() {
140 foreach($this->scripts as $script) {
141 if(preg_match('#^INLINE;#',$script)) {
142 //Inline script
143 $script = preg_replace('#^INLINE;#','',$script);
144 $script = rtrim( $script, ";\n\t\r" ) . ';';
145 //Add try-catch?
146 if($this->trycatch) {
147 $script = 'try{'.$script.'}catch(e){}';
148 }
149 $tmpscript = apply_filters( 'autoptimize_js_individual_script', $script, "" );
150 if ($tmpscript!==$script && !empty($tmpscript)) {
151 $script=$tmpscript;
152 $this->alreadyminified=true;
153 }
154 $this->jscode .= "\n" . $script;
155 } else {
156 //External script
157 if($script !== false && file_exists($script) && is_readable($script)) {
158 $scriptsrc = file_get_contents($script);
159 $scriptsrc = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$scriptsrc);
160 $scriptsrc = rtrim($scriptsrc,";\n\t\r").';';
161 //Add try-catch?
162 if($this->trycatch) {
163 $scriptsrc = 'try{'.$scriptsrc.'}catch(e){}';
164 }
165 $tmpscriptsrc = apply_filters( 'autoptimize_js_individual_script', $scriptsrc, $script );
166 if ($tmpscriptsrc!==$scriptsrc && !empty($tmpscriptsrc)) {
167 $scriptsrc=$tmpscriptsrc;
168 $this->alreadyminified=true;
169 }
170 $this->jscode .= "\n".$scriptsrc;
171 }/*else{
172 //Couldn't read JS. Maybe getpath isn't working?
173 }*/
174 }
175 }
176
177 //Check for already-minified code
178 $this->md5hash = md5($this->jscode);
179 $ccheck = new autoptimizeCache($this->md5hash,'js');
180 if($ccheck->check()) {
181 $this->jscode = $ccheck->retrieve();
182 return true;
183 }
184 unset($ccheck);
185
186 //$this->jscode has all the uncompressed code now.
187 if ($this->alreadyminified!==true) {
188 if (class_exists('JSMin') && apply_filters( 'autoptimize_js_do_minify' , true)) {
189 if (@is_callable(array(new JSMin,"minify"))) {
190 $tmp_jscode = trim(JSMin::minify($this->jscode));
191 $tmp_jscode = apply_filters( 'autoptimize_js_after_minify', $tmp_jscode );
192 if (!empty($tmp_jscode)) {
193 $this->jscode = $tmp_jscode;
194 unset($tmp_jscode);
195 }
196 return true;
197 } else {
198 return false;
199 }
200 } else {
201 return false;
202 }
203 }
204 return true;
205 }
206
207 //Caches the JS in uncompressed, deflated and gzipped form.
208 public function cache()
209 {
210 $cache = new autoptimizeCache($this->md5hash,'js');
211 if(!$cache->check()) {
212 //Cache our code
213 $cache->cache($this->jscode,'text/javascript');
214 }
215 $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
216 $this->url = $this->url_replace_cdn($this->url);
217 }
218
219 // Returns the content
220 public function getcontent() {
221 // Restore the full content
222 if(!empty($this->restofcontent)) {
223 $this->content .= $this->restofcontent;
224 $this->restofcontent = '';
225 }
226
227 // Add the scripts taking forcehead/ deferred (default) into account
228 if($this->forcehead == true) {
229 $replaceTag=array("</title>","after");
230 $defer="";
231 } else {
232 $replaceTag=array("</body>","before");
233 $defer="defer ";
234 }
235
236 $defer = apply_filters( 'autoptimize_filter_js_defer', $defer );
237 $replaceTag = apply_filters( 'autoptimize_filter_js_replacetag', $replaceTag );
238
239 $bodyreplacement = implode('',$this->move['first']);
240 $bodyreplacement .= '<script type="text/javascript" '.$defer.'src="'.$this->url.'"></script>';
241 $bodyreplacement .= implode('',$this->move['last']);
242
243 $this->inject_in_html($bodyreplacement,$replaceTag);
244
245 // restore comments
246 $this->content = $this->restore_comments($this->content);
247
248 // Restore IE hacks
249 $this->content = $this->restore_iehacks($this->content);
250
251 // Restore noptimize
252 $this->content = $this->restore_noptimize($this->content);
253
254 // Return the modified HTML
255 return $this->content;
256 }
257
258 //Checks agains the whitelist
259 private function ismergeable($tag) {
260 foreach($this->domove as $match) {
261 if(strpos($tag,$match)!==false) {
262 //Matched something
263 return false;
264 }
265 }
266
267 if ($this->movetolast($tag)) {
268 return false;
269 }
270
271 foreach($this->dontmove as $match) {
272 if(strpos($tag,$match)!==false) {
273 //Matched something
274 return false;
275 }
276 }
277
278 //If we're here it's safe to merge
279 return true;
280 }
281
282 //Checks agains the blacklist
283 private function ismovable($tag) {
284 foreach($this->domove as $match) {
285 if(strpos($tag,$match)!==false) {
286 //Matched something
287 return true;
288 }
289 }
290
291 if ($this->movetolast($tag)) {
292 return true;
293 }
294
295 foreach($this->dontmove as $match) {
296 if(strpos($tag,$match)!==false) {
297 //Matched something
298 return false;
299 }
300 }
301
302 //If we're here it's safe to move
303 return true;
304 }
305
306 private function movetolast($tag) {
307 foreach($this->domovelast as $match) {
308 if(strpos($tag,$match)!==false) {
309 //Matched, return true
310 return true;
311 }
312 }
313
314 //Should be in 'first'
315 return false;
316 }
317 }
318