PluginProbe
Autoptimize / 1.9.1
Autoptimize v1.9.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.9.1, at classes/autoptimizeScripts.php

302 lines 8.8 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','GoogleAnalyticsObject','plupload.full.min.js','syntaxhighlighter','adsbygoogle','potentialAction');
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 // unhide comments, as javascript may be wrapped in comment-tags for old times' sake
102 $tag = $this->restore_comments($tag);
103 if($this->ismergeable($tag) && ( apply_filters('autoptimize_js_include_inline',true) )) {
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 if($this->movetolast($tag)) {
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 // re-hide comments to be able to do the removal based on tag from $this->content
122 $tag = $this->hide_comments($tag);
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, great ;-)
133 return false;
134 }
135
136 //Joins and optimizes JS
137 public function minify() {
138 foreach($this->scripts as $script) {
139 if(preg_match('#^INLINE;#',$script)) {
140 //Inline script
141 $script = preg_replace('#^INLINE;#','',$script);
142 $script = rtrim( $script, ";\n\t\r" ) . ';';
143 //Add try-catch?
144 if($this->trycatch) {
145 $script = 'try{'.$script.'}catch(e){}';
146 }
147 $this->jscode .= "\n" . $script;
148 } else {
149 //External script
150 if($script !== false && file_exists($script) && is_readable($script)) {
151 $script = file_get_contents($script);
152 $script = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$script);
153 $script = rtrim($script,";\n\t\r").';';
154 //Add try-catch?
155 if($this->trycatch) {
156 $script = 'try{'.$script.'}catch(e){}';
157 }
158 $this->jscode .= "\n".$script;
159 }/*else{
160 //Couldn't read JS. Maybe getpath isn't working?
161 }*/
162 }
163 }
164
165 //Check for already-minified code
166 $this->md5hash = md5($this->jscode);
167 $ccheck = new autoptimizeCache($this->md5hash,'js');
168 if($ccheck->check()) {
169 $this->jscode = $ccheck->retrieve();
170 return true;
171 }
172 unset($ccheck);
173
174 //$this->jscode has all the uncompressed code now.
175 if(class_exists('JSMin') && apply_filters( 'autoptimize_js_do_minify' , true)) {
176 if (@is_callable(array(new JSMin,"minify"))) {
177 $tmp_jscode = trim(JSMin::minify($this->jscode));
178 if (!empty($tmp_jscode)) {
179 $this->jscode = $tmp_jscode;
180 unset($tmp_jscode);
181 }
182 return true;
183 } else {
184 return false;
185 }
186 } else {
187 return false;
188 }
189 }
190
191 //Caches the JS in uncompressed, deflated and gzipped form.
192 public function cache()
193 {
194 $cache = new autoptimizeCache($this->md5hash,'js');
195 if(!$cache->check()) {
196 //Cache our code
197 $cache->cache($this->jscode,'text/javascript');
198 }
199 $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
200 $this->url = $this->url_replace_cdn($this->url);
201 }
202
203 // Returns the content
204 public function getcontent() {
205 // Restore the full content
206 if(!empty($this->restofcontent)) {
207 $this->content .= $this->restofcontent;
208 $this->restofcontent = '';
209 }
210
211 // Add the scripts taking forcehead/ deferred (default) into account
212 if($this->forcehead == true) {
213 $replaceTag=array("</title>","after");
214 $defer="";
215 } else {
216 $replaceTag=array("</body>","before");
217 $defer="defer ";
218 }
219
220 $defer = apply_filters( 'autoptimize_filter_js_defer', $defer );
221 $replaceTag = apply_filters( 'autoptimize_filter_js_replacetag', $replaceTag );
222
223 $bodyreplacement = implode('',$this->move['first']);
224 $bodyreplacement .= '<script type="text/javascript" '.$defer.'src="'.$this->url.'"></script>';
225 $bodyreplacement .= implode('',$this->move['last']);
226
227 $this->inject_in_html($bodyreplacement,$replaceTag);
228
229 // restore comments
230 $this->content = $this->restore_comments($this->content);
231
232 // Restore IE hacks
233 $this->content = $this->restore_iehacks($this->content);
234
235 // Restore noptimize
236 $this->content = $this->restore_noptimize($this->content);
237
238 // Return the modified HTML
239 return $this->content;
240 }
241
242 //Checks agains the whitelist
243 private function ismergeable($tag) {
244 foreach($this->domove as $match) {
245 if(strpos($tag,$match)!==false) {
246 //Matched something
247 return false;
248 }
249 }
250
251 if ($this->movetolast($tag)) {
252 return false;
253 }
254
255 foreach($this->dontmove as $match) {
256 if(strpos($tag,$match)!==false) {
257 //Matched something
258 return false;
259 }
260 }
261
262 //If we're here it's safe to merge
263 return true;
264 }
265
266 //Checks agains the blacklist
267 private function ismovable($tag) {
268 foreach($this->domove as $match) {
269 if(strpos($tag,$match)!==false) {
270 //Matched something
271 return true;
272 }
273 }
274
275 if ($this->movetolast($tag)) {
276 return true;
277 }
278
279 foreach($this->dontmove as $match) {
280 if(strpos($tag,$match)!==false) {
281 //Matched something
282 return false;
283 }
284 }
285
286 //If we're here it's safe to move
287 return true;
288 }
289
290 private function movetolast($tag) {
291 foreach($this->domovelast as $match) {
292 if(strpos($tag,$match)!==false) {
293 //Matched, return true
294 return true;
295 }
296 }
297
298 //Should be in 'first'
299 return false;
300 }
301 }
302