PluginProbe
Autoptimize / 1.6.3
Autoptimize v1.6.3
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.3, at classes/autoptimizeScripts.php

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