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

timize_do_cachepurged_action()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
3
4
class autoptimizeCache {
5
    private $filename;
6
    private $mime;
0 ignored issues
show
Unused Code introduced by
The property $mime is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
7
    private $cachedir;
8
    private $delayed;
9
    
10
    public function __construct($md5,$ext='php') {
11
        $this->cachedir = AUTOPTIMIZE_CACHE_DIR;
12
        $this->delayed = AUTOPTIMIZE_CACHE_DELAY;
13
        $this->nogzip = AUTOPTIMIZE_CACHE_NOGZIP;
0 ignored issues
show
Bug introduced by
The property nogzip 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...
14
        if($this->nogzip == false) {
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...
15
            $this->filename = AUTOPTIMIZE_CACHEFILE_PREFIX.$md5.'.php';
16
        } else {
17
            if (in_array($ext, array("js","css")))     {
18
                $this->filename = $ext.'/'.AUTOPTIMIZE_CACHEFILE_PREFIX.$md5.'.'.$ext;
19
            } else {
20
                $this->filename = AUTOPTIMIZE_CACHEFILE_PREFIX.$md5.'.'.$ext;
21
            }
22
        }
23
    }
24
    
25
    public function check() {
26
        if(!file_exists($this->cachedir.$this->filename)) {
27
            // No cached file, sorry
28
            return false;
29
        }
30
        // Cache exists!
31
        return true;
32
    }
33
    
34
    public function retrieve() {
35
        if($this->check()) {
36
            if($this->nogzip == false) {
37
                return file_get_contents($this->cachedir.$this->filename.'.none');
38
            } else {
39
                return file_get_contents($this->cachedir.$this->filename);
40
            }
41
        }
42
        return false;
43
    }
44
    
45
    public function cache($code,$mime) {
46
        if($this->nogzip == false) {
47
            $file = ($this->delayed ? 'delayed.php' : 'default.php');
48
            $phpcode = file_get_contents(AUTOPTIMIZE_PLUGIN_DIR.'/config/'.$file);
49
            $phpcode = str_replace(array('%%CONTENT%%','exit;'),array($mime,''),$phpcode);
50
            file_put_contents($this->cachedir.$this->filename,$phpcode, LOCK_EX);
51
            file_put_contents($this->cachedir.$this->filename.'.none',$code, LOCK_EX);
52 View Code Duplication
            if(!$this->delayed) {
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...
53
                // Compress now!
54
                file_put_contents($this->cachedir.$this->filename.'.deflate',gzencode($code,9,FORCE_DEFLATE), LOCK_EX);
55
                file_put_contents($this->cachedir.$this->filename.'.gzip',gzencode($code,9,FORCE_GZIP), LOCK_EX);
56
            }
57 View Code Duplication
        } else {
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...
58
            // Write code to cache without doing anything else
59
            file_put_contents($this->cachedir.$this->filename,$code, LOCK_EX);
60
            if (apply_filters('autoptimize_filter_cache_create_static_gzip', false)) {
61
                // Create an additional cached gzip file
62
                file_put_contents($this->cachedir.$this->filename.'.gz', gzencode($code,9,FORCE_GZIP), LOCK_EX);
63
            }
64
        }
65
    }
66
    
67
    public function getname() {
68
        apply_filters('autoptimize_filter_cache_getname',AUTOPTIMIZE_CACHE_URL.$this->filename);
69
        return $this->filename;
70
    }
71
    
72
    static function clearall() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
73
        if(!autoptimizeCache::cacheavail()) {
74
            return false;
75
        }
76
    
77
        // scan the cachedirs        
78 View Code Duplication
        foreach (array("","js","css") as $scandirName) {
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...
79
            $scan[$scandirName] = scandir(AUTOPTIMIZE_CACHE_DIR.$scandirName);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$scan was never initialized. Although not strictly required by PHP, it is generally a good practice to add $scan = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
80
        }
81
        
82
        // clear the cachedirs
83
        foreach ($scan as $scandirName=>$scanneddir) {
0 ignored issues
show
Bug introduced by
The variable $scan does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
84
            $thisAoCacheDir=rtrim(AUTOPTIMIZE_CACHE_DIR.$scandirName,"/")."/";
85
            foreach($scanneddir as $file) {
86
                if(!in_array($file,array('.','..')) && strpos($file,AUTOPTIMIZE_CACHEFILE_PREFIX) !== false && is_file($thisAoCacheDir.$file)) {
87
                    @unlink($thisAoCacheDir.$file);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
88
                }
89
            }
90
        }
91
92
        @unlink(AUTOPTIMIZE_CACHE_DIR."/.htaccess");
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
93
        delete_transient("autoptimize_stats");
94
95
        // add cachepurged action 
96
        if (!function_exists('autoptimize_do_cachepurged_action')) {
97
            function autoptimize_do_cachepurged_action() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
98
                do_action("autoptimize_action_cachepurged");
99
            }
100
        }
101
        add_action("shutdown","autoptimize_do_cachepurged_action",11);
102
        
103
        // try to purge caching plugins cache-files?
104
        include_once(AUTOPTIMIZE_PLUGIN_DIR.'classlesses/autoptimizePageCacheFlush.php');
105
        add_action("autoptimize_action_cachepurged","autoptimize_flush_pagecache",10,0);
106
107
        // warm cache (part of speedupper)?
108
        if ( apply_filters('autoptimize_filter_speedupper', true) ) {
109
            $warmCacheUrl = site_url()."/?ao_speedup_cachebuster=".rand(1,100000);
110
            $warmCache = @wp_remote_get($warmCacheUrl);
111
            unset($warmCache);
112
        }
113
114
        return true;
115
    }
116
117
    static function stats()    {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
118
        $AOstats=get_transient("autoptimize_stats");
119
120
        if (empty($AOstats)) {
121
            // Cache not available :(
122
            if(!autoptimizeCache::cacheavail()) {
123
                return 0;
124
            }
125
            
126
            // Count cached info
127
            $count = 0;
128
            $size = 0;
129
            
130
            // scan the cachedirs        
131 View Code Duplication
            foreach (array("","js","css") as $scandirName) {
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...
132
                $scan[$scandirName] = scandir(AUTOPTIMIZE_CACHE_DIR.$scandirName);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$scan was never initialized. Although not strictly required by PHP, it is generally a good practice to add $scan = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
133
            }
134
            
135
            foreach ($scan as $scandirName=>$scanneddir) {
0 ignored issues
show
Bug introduced by
The variable $scan does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
136
                $thisAoCacheDir=rtrim(AUTOPTIMIZE_CACHE_DIR.$scandirName,"/")."/";
137
                foreach($scanneddir as $file) {
138
                    if(!in_array($file,array('.','..')) && strpos($file,AUTOPTIMIZE_CACHEFILE_PREFIX) !== false) {
139
                        if(is_file($thisAoCacheDir.$file)) {
140
                            if(AUTOPTIMIZE_CACHE_NOGZIP && (strpos($file,'.js') !== false || strpos($file,'.css') !== false || strpos($file,'.img') !== false || strpos($file,'.txt') !== false )) {
141
                                $count++;
142
                            } elseif(!AUTOPTIMIZE_CACHE_NOGZIP && strpos($file,'.none') !== false) {
143
                                $count++;
144
                            }
145
                            $size+=filesize($thisAoCacheDir.$file);
146
                        }
147
                    }
148
                }
149
            }
150
            $AOstats=array($count,$size,time());
151
            if ($count>100) {
152
                set_transient( "autoptimize_stats", $AOstats, apply_filters( 'autoptimize_filter_cache_statsexpiry', HOUR_IN_SECONDS ) );
153
            }
154
        }
155
        // print the number of instances
156
        return $AOstats;
157
    }    
158
159
    static function cacheavail() {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
160
        if(!defined('AUTOPTIMIZE_CACHE_DIR')) {
161
            // We didn't set a cache
162
            return false;
163
        }
164
        
165
        foreach (array("","js","css") as $checkDir) {
166
            if(!autoptimizeCache::checkCacheDir(AUTOPTIMIZE_CACHE_DIR.$checkDir)) {
167
                return false;
168
            }
169
        }
170
        
171
        /** write index.html here to avoid prying eyes */
172
        $indexFile=AUTOPTIMIZE_CACHE_DIR.'/index.html';
173
        if(!is_file($indexFile)) {
174
            @file_put_contents($indexFile,'<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
175
        }
176
177
        /** write .htaccess here to overrule wp_super_cache */
178
        $htAccess=AUTOPTIMIZE_CACHE_DIR.'/.htaccess';
179
        if(!is_file($htAccess)) {
180
            /** 
181
             * create wp-content/AO_htaccess_tmpl with 
182
             * whatever htaccess rules you might need
183
             * if you want to override default AO htaccess
184
             */
185
            $htaccess_tmpl=WP_CONTENT_DIR."/AO_htaccess_tmpl";
186
            if (is_file($htaccess_tmpl)) { 
187
                $htAccessContent=file_get_contents($htaccess_tmpl);
188
            } else if (is_multisite() || AUTOPTIMIZE_CACHE_NOGZIP == false) {
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...
189
                $htAccessContent='<IfModule mod_expires.c>
190
        ExpiresActive On
191
        ExpiresByType text/css A30672000
192
        ExpiresByType text/javascript A30672000
193
        ExpiresByType application/javascript A30672000
194
</IfModule>
195
<IfModule mod_headers.c>
196
    Header append Cache-Control "public, immutable"
197
</IfModule>
198
<IfModule mod_deflate.c>
199
        <FilesMatch "\.(js|css)$">
200
        SetOutputFilter DEFLATE
201
    </FilesMatch>
202
</IfModule>
203
<IfModule mod_authz_core.c>
204
    <Files *.php>
205
        Require all granted
206
    </Files>
207
</IfModule>
208
<IfModule !mod_authz_core.c>
209
    <Files *.php>
210
        Order allow,deny
211
        Allow from all
212
    </Files>
213
</IfModule>';
214
            } else {
215
                $htAccessContent='<IfModule mod_expires.c>
216
        ExpiresActive On
217
        ExpiresByType text/css A30672000
218
        ExpiresByType text/javascript A30672000
219
        ExpiresByType application/javascript A30672000
220
</IfModule>
221
<IfModule mod_headers.c>
222
    Header append Cache-Control "public, immutable"
223
</IfModule>
224
<IfModule mod_deflate.c>
225
    <FilesMatch "\.(js|css)$">
226
        SetOutputFilter DEFLATE
227
    </FilesMatch>
228
</IfModule>
229
<IfModule mod_authz_core.c>
230
    <Files *.php>
231
        Require all denied
232
    </Files>
233
</IfModule>
234
<IfModule !mod_authz_core.c>
235
    <Files *.php>
236
        Order deny,allow
237
        Deny from all
238
    </Files>
239
</IfModule>';
240
            }
241
            @file_put_contents($htAccess,$htAccessContent);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
242
        }
243
244
        // All OK
245
        return true;
246
    }
247
248
    static function checkCacheDir($dir) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
249
        // Check and create if not exists
250
        if(!file_exists($dir))    {
251
            @mkdir($dir,0775,true);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
252
            if(!file_exists($dir))    {
253
                return false;
254
            }
255
        }
256
257
        // check if we can now write
258
        if(!is_writable($dir))    {
259
            return false;
260
        }
261
262
        // and write index.html here to avoid prying eyes
263
        $indexFile=$dir.'/index.html';
264
        if(!is_file($indexFile)) {
265
            @file_put_contents($indexFile,'<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>');
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
266
        }
267
        
268
        return true;
269
    }
270
}
271