PluginProbe
Autoptimize / 1.7.1
Autoptimize v1.7.1
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.7.1, at classes/autoptimizeScripts.php

299 lines 7.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 {
6 private $scripts = array();
7 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');
8 private $domove = array('gaJsHost','load_cmc','jd.gallery.transitions.js','swfobject.embedSWF(','tiny_mce.js','tinyMCEPreInit.go');
9 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');
10 private $trycatch = 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 {
21 //Remove everything that's not the header
22 if($options['justhead'] == true)
23 {
24 $content = explode('</head>',$this->content,2);
25 $this->content = $content[0].'</head>';
26 $this->restofcontent = $content[1];
27 }
28
29 $excludeJS = $options['js_exclude'];
30 if ($excludeJS!=="") {
31 $exclJSArr = array_filter(array_map('trim',explode(",",$excludeJS)));
32 $this->dontmove = array_merge($exclJSArr,$this->dontmove);
33 }
34
35 //Should we add try-catch?
36 if($options['trycatch'] == true)
37 $this->trycatch = true;
38
39 // force js in head?
40 if($options['forcehead'] == true)
41 $this->forcehead = true;
42
43 // get cdn url
44 $this->cdn_url = $options['cdn_url'];
45
46 // noptimize me
47 $this->content = $this->hide_noptimize($this->content);
48
49 //Save IE hacks
50 $this->content = preg_replace('#(<\!--\[if.*\]>.*<\!\[endif\]-->)#Usie','\'%%IEHACK%%\'.base64_encode("$1").\'%%IEHACK%%\'',$this->content);
51
52 //Get script files
53 if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches))
54 {
55 foreach($matches[0] as $tag)
56 {
57 if(preg_match('#src=("|\')(.*)("|\')#Usmi',$tag,$source))
58 {
59 //External script
60 $url = current(explode('?',$source[2],2));
61 $path = $this->getpath($url);
62 if($path !== false && preg_match('#\.js$#',$path))
63 {
64 //Inline
65 if($this->ismergeable($tag))
66 {
67 //We can merge it
68 $this->scripts[] = $path;
69 }else{
70 //No merge, but maybe we can move it
71 if($this->ismovable($tag))
72 {
73 //Yeah, move it
74 if($this->movetolast($tag))
75 {
76 $this->move['last'][] = $tag;
77 }else{
78 $this->move['first'][] = $tag;
79 }
80 }else{
81 //We shouldn't touch this
82 $tag = '';
83 }
84 }
85 }else{
86 //External script (example: google analytics)
87 //OR Script is dynamic (.php etc)
88 if($this->ismovable($tag))
89 {
90 if($this->movetolast($tag))
91 {
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 if($this->ismergeable($tag))
104 {
105 preg_match('#<script.*>(.*)</script>#Usmi',$tag,$code);
106 $code = preg_replace('#.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*#sm','$1',$code[1]);
107 $code = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/','',$code);
108 $this->scripts[] = 'INLINE;'.$code;
109 }else{
110 //Can we move this?
111 if($this->ismovable($tag))
112 {
113 if($this->movetolast($tag))
114 {
115 $this->move['last'][] = $tag;
116 }else{
117 $this->move['first'][] = $tag;
118 }
119 }else{
120 //We shouldn't touch this
121 $tag = '';
122 }
123 }
124 }
125
126 //Remove the original script tag
127 $this->content = str_replace($tag,'',$this->content);
128 }
129
130 return true;
131 }
132
133 //No script files :(
134 return false;
135 }
136
137 //Joins and optimizes JS
138 public function minify()
139 {
140 foreach($this->scripts as $script)
141 {
142 if(preg_match('#^INLINE;#',$script))
143 {
144 //Inline script
145 $script = preg_replace('#^INLINE;#','',$script);
146 //Add try-catch?
147 if($this->trycatch)
148 $script = 'try{'.$script.'}catch(e){}';
149 $this->jscode .= "\n".$script;
150 }else{
151 //External script
152 if($script !== false && file_exists($script) && is_readable($script))
153 {
154 $script = file_get_contents($script);
155 $script = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$script);
156 //Add try-catch?
157 if($this->trycatch)
158 $script = 'try{'.$script.'}catch(e){}';
159 $this->jscode .= "\n".$script;
160 }/*else{
161 //Couldn't read JS. Maybe getpath isn't working?
162 }*/
163 }
164 }
165
166 //Check for already-minified code
167 $this->md5hash = md5($this->jscode);
168 $ccheck = new autoptimizeCache($this->md5hash,'js');
169 if($ccheck->check())
170 {
171 $this->jscode = $ccheck->retrieve();
172 return true;
173 }
174 unset($ccheck);
175
176 //$this->jscode has all the uncompressed code now.
177 if(class_exists('JSMin'))
178 {
179 $this->jscode = trim(JSMin::minify($this->jscode));
180 return true;
181 }else{
182 return false;
183 }
184 }
185
186 //Caches the JS in uncompressed, deflated and gzipped form.
187 public function cache()
188 {
189 $cache = new autoptimizeCache($this->md5hash,'js');
190 if(!$cache->check())
191 {
192 //Cache our code
193 $cache->cache($this->jscode,'text/javascript');
194 }
195 $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
196 $this->url = $this->url_replace_cdn($this->url);
197 }
198
199 // Returns the content
200 public function getcontent()
201 {
202 // Restore the full content
203 if(!empty($this->restofcontent))
204 {
205 $this->content .= $this->restofcontent;
206 $this->restofcontent = '';
207 }
208
209 // Add the scripts taking forcehead/ deferred (default) into account
210 if($this->forcehead == true) {
211 $replaceTag="</head>";
212 $defer="";
213 } else {
214 $replaceTag="</body>";
215 $defer="defer ";
216 }
217
218 $bodyreplacement = implode('',$this->move['first']);
219 $bodyreplacement .= '<script type="text/javascript" '.$defer.'src="'.$this->url.'"></script>';
220 $bodyreplacement .= implode('',$this->move['last']).$replaceTag;
221 $this->content = str_replace($replaceTag,$bodyreplacement,$this->content);
222
223 // Restore IE hacks
224 $this->content = preg_replace('#%%IEHACK%%(.*)%%IEHACK%%#Usie','stripslashes(base64_decode("$1"))',$this->content);
225
226 // Restore noptimize
227 $this->content = $this->restore_noptimize($this->content);
228
229 // Return the modified HTML
230 return $this->content;
231 }
232
233 //Checks agains the whitelist
234 private function ismergeable($tag)
235 {
236 foreach($this->domove as $match)
237 {
238 if(strpos($tag,$match)!==false)
239 {
240 //Matched something
241 return false;
242 }
243 }
244
245 foreach($this->dontmove as $match)
246 {
247 if(strpos($tag,$match)!==false)
248 {
249 //Matched something
250 return false;
251 }
252 }
253
254 //If we're here it's safe to merge
255 return true;
256 }
257
258 //Checks agains the blacklist
259 private function ismovable($tag)
260 {
261
262 foreach($this->domove as $match)
263 {
264 if(strpos($tag,$match)!==false)
265 {
266 //Matched something
267 return true;
268 }
269 }
270
271 foreach($this->dontmove as $match)
272 {
273 if(strpos($tag,$match)!==false)
274 {
275 //Matched something
276 return false;
277 }
278 }
279
280 //If we're here it's safe to move
281 return true;
282 }
283
284 private function movetolast($tag)
285 {
286 foreach($this->domovelast as $match)
287 {
288 if(strpos($tag,$match)!==false)
289 {
290 //Matched, return true
291 return true;
292 }
293 }
294
295 //Should be in 'first'
296 return false;
297 }
298 }
299