Completed
Push — master ( 9a01d9...c990d6 )
by frank
08:32
created

autoptimizeScripts   D

Complexity

Total Complexity 92

Size/Duplication

Total Lines 466
Duplicated Lines 5.36 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 25
loc 466
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
C minify() 6 75 19
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
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','histats.com/js','statcounter.com/counter/counter.js','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','wordfence_logHuman');
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', '', $this->content );
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', '', $this->content );
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, $this->content );
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
                    $scripthash = md5($scriptsrc);
234
                    $scriptsrc = preg_replace('/\x{EF}\x{BB}\x{BF}/','',$scriptsrc);
235
                    $scriptsrc = rtrim($scriptsrc,";\n\t\r").';';
236
237
                    //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...
238
                    if($this->trycatch) {
239
                        $scriptsrc = 'try{'.$scriptsrc.'}catch(e){}';
240
                    }
241
                    $tmpscriptsrc = apply_filters( 'autoptimize_js_individual_script', $scriptsrc, $script );
242 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...
243
                        $scriptsrc=$tmpscriptsrc;
244
                        $this->alreadyminified=true;
245
                    } else if ($this->can_inject_late($script)) {
246
                        $scriptsrc="/*!%%INJECTLATER".AUTOPTIMIZE_HASH."%%".base64_encode($script)."|".$scripthash."%%INJECTLATER%%*/";
247
                    }
248
                    $this->jscode .= "\n".$scriptsrc;
249
                }/*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...
250
                    //Couldn't read JS. Maybe getpath isn't working?
251
                }*/
252
            }
253
        }
254
255
        //Check for already-minified code
256
        $this->md5hash = md5($this->jscode);
257
        $ccheck = new autoptimizeCache($this->md5hash,'js');
258
        if($ccheck->check()) {
259
            $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...
260
            return true;
261
        }
262
        unset($ccheck);
263
        
264
        //$this->jscode has all the uncompressed code now.
265
        if ($this->alreadyminified!==true) {
266
          if (class_exists('JSMin') && apply_filters( 'autoptimize_js_do_minify' , true)) {
267
            if (@is_callable(array("JSMin","minify"))) {
268
                $tmp_jscode = trim(JSMin::minify($this->jscode));
269
                if (!empty($tmp_jscode)) {
270
                    $this->jscode = $tmp_jscode;
271
                    unset($tmp_jscode);
272
                }
273
                $this->jscode = $this->inject_minified($this->jscode);
274
                $this->jscode = apply_filters( 'autoptimize_js_after_minify', $this->jscode );
275
                return true;
276
            } else {
277
                $this->jscode = $this->inject_minified($this->jscode);
278
                return false;
279
            }
280
          } else {
281
              $this->jscode = $this->inject_minified($this->jscode);
282
              return false;
283
          }
284
        }
285
        $this->jscode = apply_filters( 'autoptimize_js_after_minify', $this->jscode );
286
        return true;
287
    }
288
    
289
    //Caches the JS in uncompressed, deflated and gzipped form.
290
    public function cache()    {
291
        $cache = new autoptimizeCache($this->md5hash,'js');
292
        if(!$cache->check()) {
293
            //Cache our code
294
            $cache->cache($this->jscode,'text/javascript');
295
        }
296
        $this->url = AUTOPTIMIZE_CACHE_URL.$cache->getname();
297
        $this->url = $this->url_replace_cdn($this->url);
298
    }
299
    
300
    // Returns the content
301
    public function getcontent() {
302
        // Restore the full content
303
        if(!empty($this->restofcontent)) {
304
            $this->content .= $this->restofcontent;
305
            $this->restofcontent = '';
306
        }
307
        
308
        // Add the scripts taking forcehead/ deferred (default) into account
309
        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...
310
            $replaceTag=array("</head>","before");
311
            $defer="";
312
        } else {
313
            $replaceTag=array("</body>","before");
314
            $defer="defer ";
315
        }
316
        
317
        $defer = apply_filters( 'autoptimize_filter_js_defer', $defer );
318
        $bodyreplacementpayload = '<script type="text/javascript" '.$defer.'src="'.$this->url.'"></script>';
319
        $bodyreplacementpayload = apply_filters('autoptimize_filter_js_bodyreplacementpayload',$bodyreplacementpayload);
320
321
        $bodyreplacement = implode('',$this->move['first']);
322
        $bodyreplacement .= $bodyreplacementpayload;
323
        $bodyreplacement .= implode('',$this->move['last']);
324
325
        $replaceTag = apply_filters( 'autoptimize_filter_js_replacetag', $replaceTag );
326
327
        if (strlen($this->jscode)>0) {
328
            $this->inject_in_html($bodyreplacement,$replaceTag);
329
        }
330
        
331
        // restore comments
332
        $this->content = $this->restore_comments($this->content);
333
334
        // Restore IE hacks
335
        $this->content = $this->restore_iehacks($this->content);
336
        
337
        // Restore noptimize
338
        $this->content = $this->restore_noptimize($this->content);
339
340
        // Return the modified HTML
341
        return $this->content;
342
    }
343
    
344
    // Checks against the white- and blacklists
345
    private function ismergeable($tag) {
346
		if (apply_filters('autoptimize_filter_js_dontaggregate',false)) {
347
			return false;
348
        } else if (!empty($this->whitelist)) {
349
            foreach ($this->whitelist as $match) {
0 ignored issues
show
Bug introduced by
The expression $this->whitelist of type string is not traversable.
Loading history...
350
                if(strpos($tag,$match)!==false) {
351
                    return true;
352
                }
353
            }
354
            // no match with whitelist
355
            return false;
356
        } else {
357
            foreach($this->domove as $match) {
358
                if(strpos($tag,$match)!==false)    {
359
                    // Matched something
360
                    return false;
361
                }
362
            }
363
            
364
            if ($this->movetolast($tag)) {
365
                return false;
366
            }
367
            
368
            foreach($this->dontmove as $match) {
369
                if(strpos($tag,$match)!==false)    {
370
                    //Matched something
371
                    return false;
372
                }
373
            }
374
            
375
            // If we're here it's safe to merge
376
            return true;
377
        }
378
    }
379
    
380
    // Checks againstt the blacklist
381
    private function ismovable($tag) {
382
        if ($this->include_inline !== true || apply_filters('autoptimize_filter_js_unmovable',true)) {
383
            return false;
384
        }
385
        
386
        foreach($this->domove as $match) {
387
            if(strpos($tag,$match)!==false)    {
388
                // Matched something
389
                return true;
390
            }
391
        }
392
        
393
        if ($this->movetolast($tag)) {
394
            return true;
395
        }
396
        
397
        foreach($this->dontmove as $match) {
398
            if(strpos($tag,$match)!==false) {
399
                // Matched something
400
                return false;
401
            }
402
        }
403
        
404
        // If we're here it's safe to move
405
        return true;
406
    }
407
    
408
    private function movetolast($tag) {
409
        foreach($this->domovelast as $match) {
410
            if(strpos($tag,$match)!==false)    {
411
                // 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...
412
                return true;
413
            }
414
        }
415
        
416
        // Should be in 'first'
417
        return false;
418
    }
419
    
420
    /**
421
     * Determines wheter a <script> $tag should be aggregated or not.
422
     *
423
     * We consider these as "aggregation-safe" currently:
424
     * - script tags without a `type` attribute
425
     * - script tags with an explicit `type` of `text/javascript`, 'text/ecmascript', 
426
     *   'application/javascript' or 'application/ecmascript'
427
     *
428
     * Everything else should return false.
429
     *
430
     * @param string $tag
431
     * @return bool
432
     * 
433
     * original function by https://github.com/zytzagoo/ on his AO fork, thanks Tomas!
434
     */
435
    public function should_aggregate($tag) {
436
        preg_match('#<(script[^>]*)>#i',$tag,$scripttag);
437
        if ( strpos($scripttag[1], 'type')===false ) {
438
            return true;
439
        } else if ( preg_match('/type\s*=\s*["\']?(?:text|application)\/(?:javascript|ecmascript)["\']?/i', $scripttag[1]) ) {
440
            return true;
441
        } else {
442
            return false;
443
        }
444
    }
445
446
    /**
447
     * Determines wheter a <script> $tag can be excluded from minification (as already minified) based on:
448
     * - inject_min_late being active
449
     * - filename ending in `min.js`
450
     * - filename matching `js/jquery/jquery.js` (wordpress core jquery, is minified)
451
     * - filename matching one passed in the consider minified filter
452
     * 
453
     * @param string $jsPath
454
     * @return bool
455
	 */
456
	private function can_inject_late($jsPath) {
457
		$consider_minified_array = apply_filters('autoptimize_filter_js_consider_minified',false);
458
        if ( $this->inject_min_late !== true ) {
459
            // late-inject turned off
460
            return false;
461
        } else if ( (strpos($jsPath,"min.js") === false) && ( strpos($jsPath,"wp-includes/js/jquery/jquery.js") === false ) && ( str_replace($consider_minified_array, '', $jsPath) === $jsPath ) ) {
462
			// file not minified based on filename & filter
463
			return false;
464
        } else {
465
            // phew, all is safe, we can late-inject
466
            return true;
467
        }
468
    }
469
}
470