Completed
Branch final (ad8b8d)
by Georges
03:08 queued 28s
created

Driver   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 214
Duplicated Lines 7.48 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 16
loc 214
rs 10
wmc 30
lcom 1
cbo 8

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 2
C driverWrite() 0 38 8
A driverDelete() 0 16 4
A driverCheck() 0 4 2
A driverRead() 0 22 3
A driverClear() 0 4 1
A driverConnect() 0 4 1
B isValidOption() 0 23 5
A getValidOptions() 0 4 1
A getRequiredOptions() 0 4 1
A getStats() 16 16 2

How to fix   Duplicated Code   

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:

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\Core\DriverAbstract;
18
use phpFastCache\Core\PathSeekerTrait;
19
use phpFastCache\Core\StandardPsr6StructureTrait;
20
use phpFastCache\Entities\driverStatistic;
21
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
22
use phpFastCache\Exceptions\phpFastCacheDriverException;
23
use phpFastCache\Util\Directory;
24
use Psr\Cache\CacheItemInterface;
25
26
/**
27
 * Class Driver
28
 * @package phpFastCache\Drivers
29
 */
30
class Driver extends DriverAbstract
31
{
32
    use PathSeekerTrait;
33
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
    protected 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 \Psr\Cache\CacheItemInterface $item
107
     * @return mixed
108
     */
109
    protected function driverRead(CacheItemInterface $item)
110
    {
111
        /**
112
         * Check for Cross-Driver type confusion
113
         */
114
        $file_path = $this->getFilePath($item->getKey());
115
        if (!file_exists($file_path)) {
116
            return null;
117
        }
118
119
        $content = $this->readfile($file_path);
120
        $object = $this->decode($content);
121
122
        if ($this->driverUnwrapTime($object)->getTimestamp() < time()) {
123
            @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...
124
125
            return null;
126
        }
127
128
        return $object;
129
130
    }
131
132
    /**
133
     * @param \Psr\Cache\CacheItemInterface $item
134
     * @return bool
135
     * @throws \InvalidArgumentException
136
     */
137
    protected function driverDelete(CacheItemInterface $item)
138
    {
139
        /**
140
         * Check for Cross-Driver type confusion
141
         */
142
        if ($item instanceof Item) {
143
            $file_path = $this->getFilePath($item->getKey(), true);
144
            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...
145
                return true;
146
            } else {
147
                return false;
148
            }
149
        } else {
150
            throw new \InvalidArgumentException('Cross-Driver type confusion detected');
151
        }
152
    }
153
154
    /**
155
     * @return bool
156
     */
157
    protected function driverClear()
158
    {
159
        return (bool) Directory::rrmdir($this->getPath(true));
160
    }
161
162
    /**
163
     * @return bool
164
     */
165
    protected function driverConnect()
166
    {
167
        return true;
168
    }
169
170
    /**
171
     * @param string $optionName
172
     * @param mixed $optionValue
173
     * @return bool
174
     * @throws \InvalidArgumentException
175
     */
176
    public static function isValidOption($optionName, $optionValue)
177
    {
178
        parent::isValidOption($optionName, $optionValue);
179
        switch ($optionName) {
180
            case 'path':
181
                return is_string($optionValue);
182
                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...
183
184
            case 'default_chmod':
185
                return is_numeric($optionValue);
186
                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...
187
188
            case 'securityKey':
189
                return is_string($optionValue);
190
                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...
191
            case 'htaccess':
192
                return is_bool($optionValue);
193
                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...
194
            default:
195
                return false;
196
                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...
197
        }
198
    }
199
200
    /**
201
     * @return array
202
     */
203
    public static function getValidOptions()
204
    {
205
        return ['path', 'default_chmod', 'securityKey', 'htaccess'];
206
    }
207
208
    /**
209
     * @return array
210
     */
211
    public static function getRequiredOptions()
212
    {
213
        return ['path'];
214
    }
215
216
    /********************
217
     *
218
     * PSR-6 Extended Methods
219
     *
220
     *******************/
221
222
    /**
223
     * @return driverStatistic
224
     * @throws \phpFastCache\Exceptions\phpFastCacheCoreException
225
     * @throws \phpFastCache\Exceptions\phpFastCacheDriverException
226
     */
227 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...
228
    {
229
        $stat = new driverStatistic();
230
        $path = $this->getFilePath(false);
231
232
        if (!is_dir($path)) {
233
            throw new phpFastCacheDriverException("Can't read PATH:" . $path, 94);
234
        }
235
236
        $stat->setData(implode(', ', array_keys($this->itemInstances)))
237
          ->setRawData([])
238
          ->setSize(Directory::dirSize($path))
239
          ->setInfo('Number of files used to build the cache: ' . Directory::getFileCount($path));
240
241
        return $stat;
242
    }
243
}