Completed
Push — master ( 6551bc...007179 )
by frank
02:19
created

autoptimizeScripts   D

Complexity

Total Complexity 92

Size/Duplication

Total Lines 463
Duplicated Lines 5.4 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 25
loc 463
rs 4.8717
c 0
b 0
f 0
wmc 92
lcom 1
cbo 3

9 Methods

Rating   Name   Duplication   Size   Complexity  
F read() 19 188 38
A cache() 0 9 2
B getcontent() 0 42 4
D ismergeable() 0 34 10
C ismovable() 0 26 8
A movetolast() 0 11 3
A should_aggregate() 0 10 3
C minify() 6 72 19
B can_inject_late() 0 13 5

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like autoptimizeScripts often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use autoptimizeScripts, and based on these observations, apply Extract Interface, too.

1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
class autoptimizeScripts extends autoptimizeBase {
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/','admin-bar.min.js','GoogleAnalyticsObject','plupload.full.min.js','syntaxhighlighter','adsbygoogle','gist.github.com','_stq','nonce','post_id','data-noptimize');
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 $alreadyminified = false;
11
    private $forcehead = true;
12
    private $include_inline = false;
13
    private $jscode = '';
14
    private $url = '';
15
    private $move = array('first' => array(), 'last' => array());
16
    private $restofcontent = '';
17
    private $md5hash = '';
18
    private $whitelist = '';
19
    private $jsremovables = array();
20
    private $inject_min_late = '';
21
    
22
    //Reads the page and collects script tags
23
    public function read($options) {
24
        $noptimizeJS = apply_filters( 'autoptimize_filter_js_noptimize', false, $this->content );
25
        if ($noptimizeJS) return false;
26
27
        // only optimize known good JS?
28
        $whitelistJS = apply_filters( 'autoptimize_filter_js_whitelist', "" );
29
        if (!empty($whitelistJS)) {
30
            $this->whitelist = array_filter(array_map('trim',explode(",",$whitelistJS)));
0 ignored issues
show
Documentation Bug introduced by
It seems like array_filter(array_map('...de(',', $whitelistJS))) of type array is incompatible with the declared type string of property $whitelist.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
31
        }
32
33
        // is there JS we should simply remove
34
        $removableJS = apply_filters( 'autoptimize_filter_js_removables', '');
35 View Code Duplication
        if (!empty($removableJS)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
36
            $this->jsremovables = array_filter(array_map('trim',explode(",",$removableJS)));
37
        }
38
39
        // only header?
40 View Code Duplication
        if( apply_filters('autoptimize_filter_js_justhead',$options['justhead']) == true ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
41
            $content = explode('</head>',$this->content,2);
42
            $this->content = $content[0].'</head>';
43
            $this->restofcontent = $content[1];
44
        }
45
        
46
        // include inline?
47
        if( apply_filters('autoptimize_js_include_inline',$options['include_inline']) == true ) {
48
            $this->include_inline = true;
49
        }
50
51
        // filter to "late inject minified JS", default to true for now (it is faster)
52
        $this->inject_min_late = apply_filters('autoptimize_filter_js_inject_min_late',true);
53
54
        // filters to override hardcoded do(nt)move(last) array contents (array in, array out!)
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
55
        $this->dontmove = apply_filters( 'autoptimize_filter_js_dontmove', $this->dontmove );        
56
        $this->domovelast = apply_filters( 'autoptimize_filter_js_movelast', $this->domovelast );
57
        $this->domove = apply_filters( 'autoptimize_filter_js_domove', $this->domove );
58
59
        // get extra exclusions settings or filter
60
        $excludeJS = $options['js_exclude'];
61
        $excludeJS = apply_filters( 'autoptimize_filter_js_exclude', $excludeJS );
62
        if ($excludeJS!=="") {
63
            if (is_array($excludeJS)) {
64
                if(($removeKeys = array_keys($excludeJS,"remove")) !== false) {
65
                    foreach ($removeKeys as $removeKey) {
66
                        unset($excludeJS[$removeKey]);
67
                        $this->jsremovables[]=$removeKey;
68
                    }
69
                }
70
                $exclJSArr = array_keys($excludeJS);
71
            } else {
72
                $exclJSArr = array_filter(array_map('trim',explode(",",$excludeJS)));
73
            }
74
            $this->dontmove = array_merge($exclJSArr,$this->dontmove);
75
        }
76
77
        //Should we add try-catch?
78
        if($options['trycatch'] == true)
79
            $this->trycatch = true;
80
81
        // force js in head?    
82
        if($options['forcehead'] == true) {
83
            $this->forcehead = true;
84
        } else {
85
            $this->forcehead = false;
86
        }
87
        $this->forcehead = apply_filters( 'autoptimize_filter_js_forcehead', $this->forcehead );
88
89
        // get cdn url
90
        $this->cdn_url = $options['cdn_url'];
0 ignored issues
show
Bug introduced by
The property cdn_url does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
91
            
92
        // noptimize me
93
        $this->content = $this->hide_noptimize($this->content);
94
95
        // Save IE hacks
96
        $this->content = $this->hide_iehacks($this->content);
97
98
        // comments
99
        $this->content = $this->hide_comments($this->content);
100
101
        // Get script files
102
        if (preg_match_all('#<script.*</script>#Usmi',$this->content,$matches)) {
103
            foreach($matches[0] as $tag) {
104
                // only consider script aggregation for types whitelisted in should_aggregate-function
105
                if( !$this->should_aggregate($tag) ) {
106
                    $tag='';
107
                    continue;
108
                }
109
110
                if (preg_match('#<script[^>]*src=("|\')([^>]*)("|\')#Usmi',$tag,$source)) {
111
                    // non-inline script
112 View Code Duplication
                    if ($this->isremovable($tag,$this->jsremovables)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
113
                        $this->content = str_replace($tag,'',$this->content);
114
                        continue;
115
                    }
116
                    $explUrl = explode('?',$source[2],2);
117
                    $url = $explUrl[0];
118
                    $path = $this->getpath($url);
119
                    if($path !== false && preg_match('#\.js$#',$path) && $this->ismergeable($tag)) {
120
                        // ok to optimize, add to array
121
                        $this->scripts[] = $path;
122
                    } else {
123
                        $origTag = $tag;
124
                        $newTag = $tag;
125
                        
126
                        // non-mergeable script (excluded or dynamic or external)
127
                        if (is_array($excludeJS)) {
128
                            // should we add flags?
129
                            foreach ($excludeJS as $exclTag => $exclFlags) {
130
                                if ( strpos($origTag,$exclTag)!==false && in_array($exclFlags,array("async","defer")) ) {
131
                                   $newTag = str_replace('<script ','<script '.$exclFlags.' ',$newTag);
132
                                }
133
                            }
134
                        }
135
                        
136
   						// should we minify the non-aggregated script?
137
						if ($path && apply_filters('autoptimize_filter_js_minify_excluded',false)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $path of type false|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
138
							$_CachedMinifiedUrl = $this->minify_single($path);
139
140
							// replace orig URL with minified URL from cache if so
141
							if (!empty($_CachedMinifiedUrl)) {
142
								$newTag = str_replace($url, $_CachedMinifiedUrl, $newTag);
143
							}
144
							
145
							// remove querystring from URL in newTag
146 View Code Duplication
							if ( !empty($explUrl[1]) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
								$newTag = str_replace("?".$explUrl[1],"",$newTag);
148
							}
149
						}
150
151
						// should we move the non-aggregated script?
152
                        if( $this->ismovable($newTag) ) {
153
                            // can be moved, flags and all
154
                            if( $this->movetolast($newTag) )    {
155
                                $this->move['last'][] = $newTag;
156
                            } else {
157
                                $this->move['first'][] = $newTag;
158
                            }
159
                        } else {
160
                            // cannot be moved, so if flag was added re-inject altered tag immediately
161
                            if ( $origTag !== $newTag ) {
162
                                $this->content = str_replace($origTag,$newTag,$this->content);
163
                                $origTag = '';
0 ignored issues
show
Unused Code introduced by
$origTag is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
164
                            }
165
                            // and forget about the $tag (not to be touched any more)
166
                            $tag = '';
167
                        }
168
                    }
169
                } else {
170
                    // Inline script
171 View Code Duplication
                    if ($this->isremovable($tag,$this->jsremovables)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
172
                        $this->content = str_replace($tag,'',$this->content);
173
                        continue;
174
                    }
175
                    
176
                    // unhide comments, as javascript may be wrapped in comment-tags for old times' sake
177
                    $tag = $this->restore_comments($tag);
178
                    if($this->ismergeable($tag) && ( $this->include_inline )) {
179
                        preg_match('#<script.*>(.*)</script>#Usmi',$tag,$code);
180
                        $code = preg_replace('#.*<!\[CDATA\[(?:\s*\*/)?(.*)(?://|/\*)\s*?\]\]>.*#sm','$1',$code[1]);
181
                        $code = preg_replace('/(?:^\\s*<!--\\s*|\\s*(?:\\/\\/)?\\s*-->\\s*$)/','',$code);
182
                        $this->scripts[] = 'INLINE;'.$code;
183
                    } else {
184
                        // Can we move this?
185
                        $autoptimize_js_moveable = apply_filters( 'autoptimize_js_moveable', '', $tag );
186
                        if( $this->ismovable($tag) || $autoptimize_js_moveable !== '' ) {
187
                            if( $this->movetolast($tag) || $autoptimize_js_moveable === 'last' ) {
188
                                $this->move['last'][] = $tag;
189
                            } else {
190
                                $this->move['first'][] = $tag;
191
                            }
192
                        } else {
193
                            //We shouldn't touch this
194
                            $tag = '';
195
                        }
196
                    }
197
                    // re-hide comments to be able to do the removal based on tag from $this->content
198
                    $tag = $this->hide_comments($tag);
199
                }
200
                
201
                //Remove the original script tag
202
                $this->content = str_replace($tag,'',$this->content);
203
            }
204
            
205
            return true;
206
        }
207
    
208
        // No script files, great ;-)
209
        return false;
210
    }
211
    
212
    //Joins and optimizes JS
213
    public function minify() {
214
        foreach($this->scripts as $script) {
215
            if(preg_match('#^INLINE;#',$script)) {
216
                //Inline script
217
                $script = preg_replace('#^INLINE;#','',$script);
218
                $script = rtrim( $script, ";\n\t\r" ) . ';';
219
                //Add try-catch?
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
220
                if($this->trycatch) {
221
                    $script = 'try{'.$script.'}catch(e){}';
222
                }
223
                $tmpscript = apply_filters( 'autoptimize_js_individual_script', $script, "" );
224
                if ( has_filter('autoptimize_js_individual_script') && !empty($tmpscript) ) {
225
                    $script=$tmpscript;
226
                    $this->alreadyminified=true;
227
                }
228
                $this->jscode .= "\n" . $script;
229
            } else {
230
                //External script
231
                if($script !== false && file_exists($script) && is_readable($script)) {
232
                    $scriptsrc = file_get_contents($script);
233
                    $scriptsrc = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$scriptsrc);
234
                    $scriptsrc = rtrim($scriptsrc,";\n\t\r").';';
235
                    //Add try-catch?
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
236
                    if($this->trycatch) {
237
                        $scriptsrc = 'try{'.$scriptsrc.'}catch(e){}';
238
                    }
239
                    $tmpscriptsrc = apply_filters( 'autoptimize_js_individual_script', $scriptsrc, $script );
240 View Code Duplication
                    if ( has_filter('autoptimize_js_individual_script') && !empty($tmpscriptsrc) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
                        $scriptsrc=$tmpscriptsrc;
242
                        $this->alreadyminified=true;
243
                    } else if ($this->can_inject_late($script)) {
244
                        $scriptsrc="/*!%%INJECTLATER%%".base64_encode($script)."|".md5($scriptsrc)."%%INJECTLATER%%*/";
245
                    }
246
                    $this->jscode .= "\n".$scriptsrc;
247
                }/*else{
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
248
                    //Couldn't read JS. Maybe getpath isn't working?
249
                }*/
250
            }
251
        }
252
253
        //Check for already-minified code
254
        $this->md5hash = md5($this->jscode);
255
        $ccheck = new autoptimizeCache($this->md5hash,'js');
256
        if($ccheck->check()) {
257
            $this->jscode = $ccheck->retrieve();
0 ignored issues
show
Documentation Bug introduced by
It seems like $ccheck->retrieve() can also be of type false. However, the property $jscode is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
258
            return true;
259
        }
260
        unset($ccheck);
261
        
262
        //$this->jscode has all the uncompressed code now.
263
        if ($this->alreadyminified!==true) {
264
          if (class_exists('JSMin') && apply_filters( 'autoptimize_js_do_minify' , true)) {
265
            if (@is_callable(array("JSMin","minify"))) {
266
                $tmp_jscode = trim(JSMin::minify($this->jscode));
267
                if (!empty($tmp_jscode)) {
268
                    $this->jscode = $tmp_jscode;
269
                    unset($tmp_jscode);
270
                }
271
                $this->jscode = $this->inject_minified($this->jscode);
272
                $this->jscode = apply_filters( 'autoptimize_js_after_minify', $this->jscode );
273
                return true;
274
            } else {
275
                $this->jscode = $this->inject_minified($this->jscode);
276
                return false;
277
            }
278
          } else {
279
              $this->jscode = $this->inject_minified($this->jscode);
280
            return false;
281
          }
282
        }
283
        return true;
284
    }
285
    
286
    //Caches the JS in uncompressed, deflated and gzipped form.
287
    public function cache()    {
288
        $cache = new autoptimizeCache($this->md5hash,'js');
289
        if(!$cache->check()) {
290
            //Cache our code
291
            $cache->cache($this->jscode,'text/javascript');
292
        }
293
        $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
294
        $this->url = $this->url_replace_cdn($this->url);
295
    }
296
    
297
    // Returns the content
298
    public function getcontent() {
299
        // Restore the full content
300
        if(!empty($this->restofcontent)) {
301
            $this->content .= $this->restofcontent;
302
            $this->restofcontent = '';
303
        }
304
        
305
        // Add the scripts taking forcehead/ deferred (default) into account
306
        if($this->forcehead == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
307
            $replaceTag=array("</head>","before");
308
            $defer="";
309
        } else {
310
            $replaceTag=array("</body>","before");
311
            $defer="defer ";
312
        }
313
        
314
        $defer = apply_filters( 'autoptimize_filter_js_defer', $defer );
315
        $bodyreplacementpayload = '<script type="text/javascript" '.$defer.'src="'.$this->url.'"></script>';
316
        $bodyreplacementpayload = apply_filters('autoptimize_filter_js_bodyreplacementpayload',$bodyreplacementpayload);
317
318
        $bodyreplacement = implode('',$this->move['first']);
319
        $bodyreplacement .= $bodyreplacementpayload;
320
        $bodyreplacement .= implode('',$this->move['last']);
321
322
        $replaceTag = apply_filters( 'autoptimize_filter_js_replacetag', $replaceTag );
323
324
        if (strlen($this->jscode)>0) {
325
            $this->inject_in_html($bodyreplacement,$replaceTag);
326
        }
327
        
328
        // restore comments
329
        $this->content = $this->restore_comments($this->content);
330
331
        // Restore IE hacks
332
        $this->content = $this->restore_iehacks($this->content);
333
        
334
        // Restore noptimize
335
        $this->content = $this->restore_noptimize($this->content);
336
337
        // Return the modified HTML
338
        return $this->content;
339
    }
340
    
341
    // Checks against the white- and blacklists
342
    private function ismergeable($tag) {
343
		if (apply_filters('autoptimize_filter_js_dontaggregate',false)) {
344
			return false;
345
        } else if (!empty($this->whitelist)) {
346
            foreach ($this->whitelist as $match) {
0 ignored issues
show
Bug introduced by
The expression $this->whitelist of type string is not traversable.
Loading history...
347
                if(strpos($tag,$match)!==false) {
348
                    return true;
349
                }
350
            }
351
            // no match with whitelist
352
            return false;
353
        } else {
354
            foreach($this->domove as $match) {
355
                if(strpos($tag,$match)!==false)    {
356
                    // Matched something
357
                    return false;
358
                }
359
            }
360
            
361
            if ($this->movetolast($tag)) {
362
                return false;
363
            }
364
            
365
            foreach($this->dontmove as $match) {
366
                if(strpos($tag,$match)!==false)    {
367
                    //Matched something
368
                    return false;
369
                }
370
            }
371
            
372
            // If we're here it's safe to merge
373
            return true;
374
        }
375
    }
376
    
377
    // Checks againstt the blacklist
378
    private function ismovable($tag) {
379
        if ($this->include_inline !== true || apply_filters('autoptimize_filter_js_unmovable',true)) {
380
            return false;
381
        }
382
        
383
        foreach($this->domove as $match) {
384
            if(strpos($tag,$match)!==false)    {
385
                // Matched something
386
                return true;
387
            }
388
        }
389
        
390
        if ($this->movetolast($tag)) {
391
            return true;
392
        }
393
        
394
        foreach($this->dontmove as $match) {
395
            if(strpos($tag,$match)!==false) {
396
                // Matched something
397
                return false;
398
            }
399
        }
400
        
401
        // If we're here it's safe to move
402
        return true;
403
    }
404
    
405
    private function movetolast($tag) {
406
        foreach($this->domovelast as $match) {
407
            if(strpos($tag,$match)!==false)    {
408
                // Matched, return true
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
409
                return true;
410
            }
411
        }
412
        
413
        // Should be in 'first'
414
        return false;
415
    }
416
    
417
    /**
418
     * Determines wheter a <script> $tag should be aggregated or not.
419
     *
420
     * We consider these as "aggregation-safe" currently:
421
     * - script tags without a `type` attribute
422
     * - script tags with an explicit `type` of `text/javascript`, 'text/ecmascript', 
423
     *   'application/javascript' or 'application/ecmascript'
424
     *
425
     * Everything else should return false.
426
     *
427
     * @param string $tag
428
     * @return bool
429
     * 
430
     * original function by https://github.com/zytzagoo/ on his AO fork, thanks Tomas!
431
     */
432
    public function should_aggregate($tag) {
433
        preg_match('#<(script[^>]*)>#i',$tag,$scripttag);
434
        if ( strpos($scripttag[1], 'type')===false ) {
435
            return true;
436
        } else if ( preg_match('/type\s*=\s*["\']?(?:text|application)\/(?:javascript|ecmascript)["\']?/i', $scripttag[1]) ) {
437
            return true;
438
        } else {
439
            return false;
440
        }
441
    }
442
443
    /**
444
     * Determines wheter a <script> $tag can be excluded from minification (as already minified) based on:
445
     * - inject_min_late being active
446
     * - filename ending in `min.js`
447
     * - filename matching `js/jquery/jquery.js` (wordpress core jquery, is minified)
448
     * - filename matching one passed in the consider minified filter
449
     * 
450
     * @param string $jsPath
451
     * @return bool
452
	 */
453
	private function can_inject_late($jsPath) {
454
		$consider_minified_array = apply_filters('autoptimize_filter_js_consider_minified',false);
455
        if ( $this->inject_min_late !== true ) {
456
            // late-inject turned off
457
            return false;
458
        } else if ( (strpos($jsPath,"min.js") === false) && ( strpos($jsPath,"wp-includes/js/jquery/jquery.js") === false ) && ( str_replace($consider_minified_array, '', $jsPath) === $jsPath ) ) {
459
			// file not minified based on filename & filter
460
			return false;
461
        } else {
462
            // phew, all is safe, we can late-inject
463
            return true;
464
        }
465
    }
466
}
467