PluginProbe
Autoptimize / 1.6.5
Autoptimize v1.6.5
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.5, at classes/autoptimizeScripts.php

292 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class autoptimizeScripts extends autoptimizeBase
4 {
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/');
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 $forcehead = false;
11 private $yui = 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['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 //Do we use yui?
44 $this->yui = $options['yui'];
45
46 //Save IE hacks
47 $this->content = preg_replace('#(<\!--\[if.*\]>.*<\!\[endif\]-->)#Usie','\'%%IEHACK%%\'.base64_encode("$1").\'%%IEHACK%%\'',$this->content);
48
49 //Get script files
50 if(preg_match_all('#<script.*</script>#Usmi',$this->content,$matches))
51 {
52 foreach($matches[0] as $tag)
53 {
54 if(preg_match('#src=("|\')(.*)("|\')#Usmi',$tag,$source))
55 {
56 //External script
57 $url = current(explode('?',$source[2],2));
58 $path = $this->getpath($url);
59 if($path !==false && preg_match('#\.js$#',$path))
60 {
61 //Inline
62 if($this->ismergeable($tag))
63 {
64 //We can merge it
65 $this->scripts[] = $path;
66 }else{
67 //No merge, but maybe we can move it
68 if($this->ismovable($tag))
69 {
70 //Yeah, move it
71 if($this->movetolast($tag))
72 {
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 {
87 if($this->movetolast($tag))
88 {
89 $this->move['last'][] = $tag;
90 }else{
91 $this->move['first'][] = $tag;
92 }
93 }else{
94 //We shouldn't touch this
95 $tag = '';
96 }
97 }
98 }else{
99 //Inline script
100 if($this->ismergeable($tag))
101 {
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 {
110 if($this->movetolast($tag))
111 {
112 $this->move['last'][] = $tag;
113 }else{
114 $this->move['first'][] = $tag;
115 }
116 }else{
117 //We shouldn't touch this
118 $tag = '';
119 }
120 }
121 }
122
123 //Remove the original script tag
124 $this->content = str_replace($tag,'',$this->content);
125 }
126
127 return true;
128 }
129
130 //No script files :(
131 return false;
132 }
133
134 //Joins and optimizes JS
135 public function minify()
136 {
137 foreach($this->scripts as $script)
138 {
139 if(preg_match('#^INLINE;#',$script))
140 {
141 //Inline script
142 $script = preg_replace('#^INLINE;#','',$script);
143 //Add try-catch?
144 if($this->trycatch)
145 $script = 'try{'.$script.'}catch(e){}';
146 $this->jscode .= "\n".$script;
147 }else{
148 //External script
149 if($script !== false && file_exists($script) && is_readable($script))
150 {
151 $script = file_get_contents($script);
152 //Add try-catch?
153 if($this->trycatch)
154 $script = 'try{'.$script.'}catch(e){}';
155 $this->jscode .= "\n".$script;
156 }/*else{
157 //Couldn't read JS. Maybe getpath isn't working?
158 }*/
159 }
160 }
161
162 //Check for already-minified code
163 $this->md5hash = md5($this->jscode);
164 $ccheck = new autoptimizeCache($this->md5hash,'js');
165 if($ccheck->check())
166 {
167 $this->jscode = $ccheck->retrieve();
168 return true;
169 }
170 unset($ccheck);
171
172 //$this->jscode has all the uncompressed code now.
173 if($this->yui == false && class_exists('JSMin'))
174 {
175 $this->jscode = trim(JSMin::minify($this->jscode));
176 return true;
177 }elseif($this->yui == true && autoptimizeYUI::available()){
178 $this->jscode = autoptimizeYUI::compress('js',$this->jscode);
179 return true;
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 {
191 //Cache our code
192 $cache->cache($this->jscode,'text/javascript');
193 }
194 $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
195 }
196
197 //Returns the content
198 public function getcontent()
199 {
200 //Restore the full content
201 if(!empty($this->restofcontent))
202 {
203 $this->content .= $this->restofcontent;
204 $this->restofcontent = '';
205 }
206
207 //Add the scripts
208 if($this->forcehead == true) {
209 $replaceTag="</head>";
210 } else {
211 $replaceTag="</body>";
212 }
213
214 $bodyreplacement = implode('',$this->move['first']);
215 $bodyreplacement .= '<script type="text/javascript" src="'.$this->url.'"></script>';
216 $bodyreplacement .= implode('',$this->move['last']).$replaceTag;
217 $this->content = str_replace($replaceTag,$bodyreplacement,$this->content);
218
219 //Restore IE hacks
220 $this->content = preg_replace('#%%IEHACK%%(.*)%%IEHACK%%#Usie','stripslashes(base64_decode("$1"))',$this->content);
221
222 //Return the modified HTML
223 return $this->content;
224 }
225
226 //Checks agains the whitelist
227 private function ismergeable($tag)
228 {
229 foreach($this->domove as $match)
230 {
231 if(strpos($tag,$match)!==false)
232 {
233 //Matched something
234 return false;
235 }
236 }
237
238 foreach($this->dontmove as $match)
239 {
240 if(strpos($tag,$match)!==false)
241 {
242 //Matched something
243 return false;
244 }
245 }
246
247 //If we're here it's safe to merge
248 return true;
249 }
250
251 //Checks agains the blacklist
252 private function ismovable($tag)
253 {
254
255 foreach($this->domove as $match)
256 {
257 if(strpos($tag,$match)!==false)
258 {
259 //Matched something
260 return true;
261 }
262 }
263
264 foreach($this->dontmove as $match)
265 {
266 if(strpos($tag,$match)!==false)
267 {
268 //Matched something
269 return false;
270 }
271 }
272
273 //If we're here it's safe to move
274 return true;
275 }
276
277 private function movetolast($tag)
278 {
279 foreach($this->domovelast as $match)
280 {
281 if(strpos($tag,$match)!==false)
282 {
283 //Matched, return true
284 return true;
285 }
286 }
287
288 //Should be in 'first'
289 return false;
290 }
291 }
292