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

294 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/');
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 $yui = false;
13 private $jscode = '';
14 private $url = '';
15 private $move = array('first' => array(), 'last' => array());
16 private $restofcontent = '';
17 private $md5hash = '';
18
19 //Reads the page and collects script tags
20 public function read($options)
21 {
22 //Remove everything that's not the header
23 if($options['justhead'] == true)
24 {
25 $content = explode('</head>',$this->content,2);
26 $this->content = $content[0].'</head>';
27 $this->restofcontent = $content[1];
28 }
29
30 $excludeJS = $options['exclude'];
31 if ($excludeJS!=="") {
32 $exclJSArr = array_filter(array_map('trim',explode(",",$excludeJS)));
33 $this->dontmove = array_merge($exclJSArr,$this->dontmove);
34 }
35
36 //Should we add try-catch?
37 if($options['trycatch'] == true)
38 $this->trycatch = true;
39
40 // force js in head?
41 if($options['forcehead'] == true)
42 $this->forcehead = true;
43 //Do we use yui?
44 $this->yui = $options['yui'];
45
46 // noptimize me
47 $this->content = $this->hide_noptimize($this->content);
48 //Save IE hacks
49 $this->content = preg_replace('#(<\!--\[if.*\]>.*<\!\[endif\]-->)#Usie','\'%%IEHACK%%\'.base64_encode("$1").\'%%IEHACK%%\'',$this->content);
50
51 //Get script files
52 if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches))
53 {
54 foreach($matches[0] as $tag)
55 {
56 if(preg_match('#src=("|\')(.*)("|\')#Usmi',$tag,$source))
57 {
58 //External script
59 $url = current(explode('?',$source[2],2));
60 $path = $this->getpath($url);
61 if($path !==false && preg_match('#\.js$#',$path))
62 {
63 //Inline
64 if($this->ismergeable($tag))
65 {
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 {
72 //Yeah, move it
73 if($this->movetolast($tag))
74 {
75 $this->move['last'][] = $tag;
76 }else{
77 $this->move['first'][] = $tag;
78 }
79 }else{
80 //We shouldn't touch this
81 $tag = '';
82 }
83 }
84 }else{
85 //External script (example: google analytics)
86 //OR Script is dynamic (.php etc)
87 if($this->ismovable($tag))
88 {
89 if($this->movetolast($tag))
90 {
91 $this->move['last'][] = $tag;
92 }else{
93 $this->move['first'][] = $tag;
94 }
95 }else{
96 //We shouldn't touch this
97 $tag = '';
98 }
99 }
100 }else{
101 //Inline script
102 if($this->ismergeable($tag))
103 {
104 preg_match('#<script.*>(.*)</script>#Usmi',$tag,$code);
105 $code = preg_replace('#.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*#sm','$1',$code[1]);
106 $code = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/','',$code);
107 $this->scripts[] = 'INLINE;'.$code;
108 }else{
109 //Can we move this?
110 if($this->ismovable($tag))
111 {
112 if($this->movetolast($tag))
113 {
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 }
124
125 //Remove the original script tag
126 $this->content = str_replace($tag,'',$this->content);
127 }
128
129 return true;
130 }
131
132 //No script files :(
133 return false;
134 }
135
136 //Joins and optimizes JS
137 public function minify()
138 {
139 foreach($this->scripts as $script)
140 {
141 if(preg_match('#^INLINE;#',$script))
142 {
143 //Inline script
144 $script = preg_replace('#^INLINE;#','',$script);
145 //Add try-catch?
146 if($this->trycatch)
147 $script = 'try{'.$script.'}catch(e){}';
148 $this->jscode .= "\n".$script;
149 }else{
150 //External script
151 if($script !== false && file_exists($script) && is_readable($script))
152 {
153 $script = file_get_contents($script);
154 //Add try-catch?
155 if($this->trycatch)
156 $script = 'try{'.$script.'}catch(e){}';
157 $this->jscode .= "\n".$script;
158 }/*else{
159 //Couldn't read JS. Maybe getpath isn't working?
160 }*/
161 }
162 }
163
164 //Check for already-minified code
165 $this->md5hash = md5($this->jscode);
166 $ccheck = new autoptimizeCache($this->md5hash,'js');
167 if($ccheck->check())
168 {
169 $this->jscode = $ccheck->retrieve();
170 return true;
171 }
172 unset($ccheck);
173
174 //$this->jscode has all the uncompressed code now.
175 if($this->yui == false && class_exists('JSMin'))
176 {
177 $this->jscode = trim(JSMin::minify($this->jscode));
178 return true;
179 }elseif($this->yui == true && autoptimizeYUI::available()){
180 $this->jscode = autoptimizeYUI::compress('js',$this->jscode);
181 return true;
182 }else{
183 return false;
184 }
185 }
186
187 //Caches the JS in uncompressed, deflated and gzipped form.
188 public function cache()
189 {
190 $cache = new autoptimizeCache($this->md5hash,'js');
191 if(!$cache->check())
192 {
193 //Cache our code
194 $cache->cache($this->jscode,'text/javascript');
195 }
196 $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
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
210 if($this->forcehead == true) {
211 $replaceTag="</head>";
212 } else {
213 $replaceTag="</body>";
214 }
215
216 $bodyreplacement = implode('',$this->move['first']);
217 $bodyreplacement .= '<script type="text/javascript" src="'.$this->url.'"></script>';
218 $bodyreplacement .= implode('',$this->move['last']).$replaceTag;
219 $this->content = str_replace($replaceTag,$bodyreplacement,$this->content);
220 //Restore IE hacks
221 $this->content = preg_replace('#%%IEHACK%%(.*)%%IEHACK%%#Usie','stripslashes(base64_decode("$1"))',$this->content);
222
223 // restore noptimize
224 $this->content = $this->restore_noptimize($this->content);
225 //Return the modified HTML
226 return $this->content;
227 }
228
229 //Checks agains the whitelist
230 private function ismergeable($tag)
231 {
232 foreach($this->domove as $match)
233 {
234 if(strpos($tag,$match)!==false)
235 {
236 //Matched something
237 return false;
238 }
239 }
240
241 foreach($this->dontmove as $match)
242 {
243 if(strpos($tag,$match)!==false)
244 {
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 {
257
258 foreach($this->domove as $match)
259 {
260 if(strpos($tag,$match)!==false)
261 {
262 //Matched something
263 return true;
264 }
265 }
266
267 foreach($this->dontmove as $match)
268 {
269 if(strpos($tag,$match)!==false)
270 {
271 //Matched something
272 return false;
273 }
274 }
275
276 //If we're here it's safe to move
277 return true;
278 }
279
280 private function movetolast($tag)
281 {
282 foreach($this->domovelast as $match)
283 {
284 if(strpos($tag,$match)!==false)
285 {
286 //Matched, return true
287 return true;
288 }
289 }
290
291 //Should be in 'first'
292 return false;
293 }
294 }