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

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