PluginProbe
Autoptimize / 1.8.1
Autoptimize v1.8.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.8.1, at classes/autoptimizeScripts.php

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