Completed
Push — v5 ( 0b505a...012ddd )
by Georges
02:41
created

Driver::driverClear()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 0
Metric Value
cc 1
eloc 2
c 3
b 2
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
2
/**
3
 *
4
 * This file is part of phpFastCache.
5
 *
6
 * @license MIT License (MIT)
7
 *
8
 * For full copyright and license information, please see the docs/CREDITS.txt file.
9
 *
10
 * @author Khoa Bui (khoaofgod)  <[email protected]> http://www.phpfastcache.com
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 *
13
 */
14
15
namespace phpFastCache\Drivers\Files;
16
17
use phpFastCache\Cache\ExtendedCacheItemInterface;
18
use phpFastCache\Core\DriverAbstract;
19
use phpFastCache\Core\PathSeekerTrait;
20
use phpFastCache\Core\StandardPsr6StructureTrait;
21
use phpFastCache\Entities\driverStatistic;
22
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
23
use phpFastCache\Exceptions\phpFastCacheDriverException;
24
use phpFastCache\Util\Directory;
25
use Psr\Cache\CacheItemInterface;
26
27
/**
28
 * Class Driver
29
 * @package phpFastCache\Drivers
30
 */
31
class Driver extends DriverAbstract
32
{
33
    use PathSeekerTrait, StandardPsr6StructureTrait;
34
    /**
35
     *
36
     */
37
    const FILE_DIR = 'files';
38
39
    /**
40
     * Driver constructor.
41
     * @param array $config
42
     * @throws phpFastCacheDriverException
43
     */
44
    public function __construct(array $config = [])
45
    {
46
        $this->setup($config);
47
48
        if (!$this->driverCheck()) {
49
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
50
        }
51
    }
52
53
    /**
54
     * @return bool
55
     */
56
    public function driverCheck()
57
    {
58
        return is_writable($this->getFileDir()) || @mkdir($this->getFileDir(), $this->setChmodAuto(), true);
0 ignored issues
show
Security File Manipulation introduced by
$this->getFileDir() can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
59
    }
60
61
    /**
62
     * @param \Psr\Cache\CacheItemInterface $item
63
     * @return mixed
64
     * @throws \InvalidArgumentException
65
     */
66
    public function driverWrite(CacheItemInterface $item)
67
    {
68
        /**
69
         * Check for Cross-Driver type confusion
70
         */
71
        if ($item instanceof Item) {
72
            $file_path = $this->getFilePath($item->getKey());
73
            $data = $this->encode($this->driverPreWrap($item));
74
75
            $toWrite = true;
76
            /*
77
             * Skip if Existing Caching in Options
78
             */
79
            if (isset($option[ 'skipExisting' ]) && $option[ 'skipExisting' ] == true && file_exists($file_path)) {
0 ignored issues
show
Bug introduced by
The variable $option seems to never exist, and therefore isset should always return false. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
80
                $content = $this->readfile($file_path);
81
                $old = $this->decode($content);
82
                $toWrite = false;
83
                if ($old->isExpired()) {
84
                    $toWrite = true;
85
                }
86
            }
87
88
            // Force write
89
            try {
90
                if ($toWrite == 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...
91
                    $f = fopen($file_path, 'w+');
92
                    fwrite($f, $data);
93
                    fclose($f);
94
95
                    return true;
96
                }
97
            } catch (\Exception $e) {
98
                return false;
99
            }
100
        } else {
101
            throw new \InvalidArgumentException('Cross-Driver type confusion detected');
102
        }
103
    }
104
105
    /**
106
     * @param string $key
107
     * @return mixed
108
     * @throws \InvalidArgumentException
109
     */
110
    public function driverRead($key)
111
    {
112
        /**
113
         * Check for Cross-Driver type confusion
114
         */
115
        $file_path = $this->getFilePath($key);
116
        if (!file_exists($file_path)) {
117
            return null;
118
        }
119
120
        $content = $this->readfile($file_path);
121
        $object = $this->decode($content);
122
123
        if ($this->driverUnwrapTime($object)->getTimestamp() < time()) {
124
            @unlink($file_path);
0 ignored issues
show
Security File Manipulation introduced by
$file_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
125
126
            return null;
127
        }
128
129
        return $object;
130
131
    }
132
133
    /**
134
     * @param \Psr\Cache\CacheItemInterface $item
135
     * @return bool
136
     * @throws \InvalidArgumentException
137
     */
138
    public function driverDelete(CacheItemInterface $item)
139
    {
140
        /**
141
         * Check for Cross-Driver type confusion
142
         */
143
        if ($item instanceof Item) {
144
            $file_path = $this->getFilePath($item->getKey(), true);
145
            if (file_exists($file_path) && @unlink($file_path)) {
0 ignored issues
show
Security File Manipulation introduced by
$file_path can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
146
                return true;
147
            } else {
148
                return false;
149
            }
150
        } else {
151
            throw new \InvalidArgumentException('Cross-Driver type confusion detected');
152
        }
153
    }
154
155
    /**
156
     * @return bool
157
     */
158
    public function driverClear()
159
    {
160
        return (bool) Directory::rrmdir($this->getPath(true));
161
    }
162
163
    /**
164
     * @return bool
165
     */
166
    public function driverConnect()
167
    {
168
        return true;
169
    }
170
171
    /**
172
     * @param \Psr\Cache\CacheItemInterface $item
173
     * @return bool
174
     * @throws \InvalidArgumentException
175
     */
176
    public function driverIsHit(CacheItemInterface $item)
177
    {
178
        $file_path = $this->getFilePath($item->getKey(), true);
179
        if (!file_exists($file_path)) {
180
            return false;
181
        } else {
182
            // check expired or not
183
            $value = $this->driverRead($item->getKey());
184
185
            return !($value == null);
186
        }
187
    }
188
189
    /**
190
     * @param string $optionName
191
     * @param mixed $optionValue
192
     * @return bool
193
     * @throws \InvalidArgumentException
194
     */
195
    public static function isValidOption($optionName, $optionValue)
196
    {
197
        parent::isValidOption($optionName, $optionValue);
198
        switch($optionName)
199
        {
200
            case 'path':
201
                return is_string($optionValue);
202
                break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
203
204
            case 'default_chmod':
205
                return is_numeric($optionValue);
206
                break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
207
208
            case 'securityKey':
209
                return is_string($optionValue);
210
                break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
211
            case 'htaccess':
212
                return is_bool($optionValue);
213
                break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
214
            default:
215
                return false;
216
            break;
1 ignored issue
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
217
        }
218
    }
219
220
    /**
221
     * @return array
222
     */
223
    public static function getValidOptions()
224
    {
225
        return ['path', 'default_chmod', 'securityKey', 'htaccess'];
226
    }
227
228
    /**
229
     * @return array
230
     */
231
    public static function getRequiredOptions()
232
    {
233
        return ['path'];
234
    }
235
236
    /********************
237
     *
238
     * PSR-6 Extended Methods
239
     *
240
     *******************/
241
242
    /**
243
     * @return driverStatistic
244
     * @throws \phpFastCache\Exceptions\phpFastCacheCoreException
245
     * @throws \phpFastCache\Exceptions\phpFastCacheDriverException
246
     */
247 View Code Duplication
    public function getStats()
1 ignored issue
show
Duplication introduced by
This method seems to be duplicated in 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...
248
    {
249
        $stat = new driverStatistic();
250
        $path = $this->getFilePath(false);
251
        
252
        if (!is_dir($path)) {
253
            throw new phpFastCacheDriverException("Can't read PATH:" . $path, 94);
254
        }
255
256
        $stat->setData(implode(', ', array_keys($this->itemInstances)))
257
          ->setRawData([])
258
          ->setSize(Directory::dirSize($path))
259
          ->setInfo('Number of files used to build the cache: ' . Directory::getFileCount($path));
260
261
        return $stat;
262
    }
263
}