Completed
Push — v5 ( e7c877...af97c1 )
by Georges
02:33
created

DriverBaseTrait::isExistingDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
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
namespace phpFastCache\Cache;
15
16
use phpFastCache\Exceptions\phpFastCacheDriverException;
17
18
/**
19
 * Class DriverBaseTrait
20
 * @package phpFastCache\Cache
21
 */
22
trait DriverBaseTrait
23
{
24
    /**
25
     * @var array
26
     */
27
    public $extension_dir = '_extensions';
28
29
    /**
30
     * @var array
31
     */
32
    public $tmp = [];
33
34
    /**
35
     * @var array default options, this will be merge to Driver's Options
36
     */
37
    public $config = [];
38
39
    /**
40
     * @var bool
41
     */
42
    public $fallback = false;
43
44
    /**
45
     * @var mixed Instance of driver service
46
     */
47
    public $instance;
48
    
49
    /**
50
     * @param $keyword
51
     * @return string
52
     */
53
    protected function encodeFilename($keyword)
54
    {
55
        return md5($keyword);
56
    }
57
58
    /**
59
     * @param $config_name
60
     * @param string $value
61
     */
62
    public function setup($config_name, $value = '')
63
    {
64
        /**
65
         * Config for class
66
         */
67
        if (is_array($config_name)) {
68
            $this->config = array_merge($this->config, $config_name);
69
        } else {
70
            $this->config[ $config_name ] = $value;
71
        }
72
    }
73
74
75
    /**
76
     * @param $file
77
     * @return string
78
     * @throws \Exception
79
     */
80
    protected function readfile($file)
81
    {
82
        if (function_exists('file_get_contents')) {
83
            return file_get_contents($file);
0 ignored issues
show
Security File Exposure introduced by
$file can contain request data and is used in file inclusion 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...
84
        } else {
85
            $string = '';
86
87
            $file_handle = @fopen($file, 'r');
88
            if (!$file_handle) {
89
                throw new phpFastCacheDriverException("Can't Read File", 96);
90
91
            }
92
            while (!feof($file_handle)) {
93
                $line = fgets($file_handle);
94
                $string .= $line;
95
            }
96
            fclose($file_handle);
97
98
            return $string;
99
        }
100
    }
101
102
    /**
103
     * Encode data types such as object/array
104
     * for driver that does not support
105
     * non-scalar value
106
     * @param $data
107
     * @return string
108
     */
109
    protected function encode($data)
110
    {
111
        return serialize($data);
112
    }
113
114
    /**
115
     * Decode data types such as object/array
116
     * for driver that does not support
117
     * non-scalar value
118
     * @param $value
119
     * @return mixed
120
     */
121
    protected function decode($value)
122
    {
123
        $x = @unserialize($value);
0 ignored issues
show
Security Object Injection introduced by
$value can contain request data and is used in unserialized 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
        if ($x == false) {
125
            return $value;
126
        } else {
127
            return $x;
128
        }
129
    }
130
131
    /**
132
     * Check phpModules or CGI
133
     * @return bool
134
     */
135
    protected function isPHPModule()
136
    {
137
        if (PHP_SAPI === 'apache2handler') {
138
            return true;
139
        } else {
140
            if (strpos(PHP_SAPI, 'handler') !== false) {
141
                return true;
142
            }
143
        }
144
145
        return false;
146
    }
147
148
149
    /**
150
     * @param $class
151
     * @return bool
152
     */
153
    protected function isExistingDriver($class)
154
    {
155
        return class_exists("\\phpFastCache\\Drivers\\{$class}");
156
    }
157
158
159
    /**
160
     * @param $tag
161
     * @return string
162
     */
163
    protected function _getTagName($tag)
164
    {
165
        return "__tag__" . $tag;
166
    }
167
168
    /**
169
     * @param \phpFastCache\Cache\ExtendedCacheItemInterface $item
170
     * @return array
171
     */
172
    public function driverPreWrap(ExtendedCacheItemInterface $item)
173
    {
174
        return [
175
          self::DRIVER_DATA_WRAPPER_INDEX => $item->get(),
176
          self::DRIVER_TIME_WRAPPER_INDEX => $item->getExpirationDate(),
177
          self::DRIVER_TAGS_WRAPPER_INDEX => $item->getTags(),
178
        ];
179
    }
180
181
    /**
182
     * @param array $wrapper
183
     * @return mixed
184
     */
185
    public function driverUnwrapData(array $wrapper)
186
    {
187
        return $wrapper[ self::DRIVER_DATA_WRAPPER_INDEX ];
188
    }
189
190
    /**
191
     * @param array $wrapper
192
     * @return mixed
193
     */
194
    public function driverUnwrapTags(array $wrapper)
195
    {
196
        return $wrapper[ self::DRIVER_TAGS_WRAPPER_INDEX ];
197
    }
198
199
200
    /**
201
     * @param array $wrapper
202
     * @return \DateTime
203
     */
204
    public function driverUnwrapTime(array $wrapper)
205
    {
206
        return $wrapper[ self::DRIVER_TIME_WRAPPER_INDEX ];
207
    }
208
209
    /**
210
     * @return string
211
     */
212
    public function getDriverName()
213
    {
214
        static $driverName;
215
216
        return ($driverName ?: $driverName = ucfirst(substr(strrchr((new \ReflectionObject($this))->getNamespaceName(), '\\'), 1)));
217
    }
218
219
    /**
220
     * @param \phpFastCache\Cache\ExtendedCacheItemInterface $item
221
     * @return bool
222
     */
223
    public function driverWriteTags(ExtendedCacheItemInterface $item)
224
    {
225
        $tagsItems = $this->getItems($this->getTagKeys($item->getTags()));
1 ignored issue
show
Bug introduced by
It seems like getItems() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
226
227
        foreach ($tagsItems as $tagsItem) {
228
            $data = $tagsItem->get();
229
            $expTimestamp = $item->getExpirationDate()->getTimestamp();
230
231
            /**
232
             * Using the key will
233
             * avoid to use array_unique
234
             * that has slow performances
235
             */
236
237
            $tagsItem->set(array_merge((array) $data, [$item->getKey() => $expTimestamp]));
238
239
            /**
240
             * Set the expiration date
241
             * of the $tagsItem based
242
             * on the older $item
243
             * expiration date
244
             */
245
            if ($expTimestamp > $tagsItem->getExpirationDate()->getTimestamp()) {
246
                $tagsItem->expiresAt($item->getExpirationDate());
247
            }
248
            $this->driverWrite($tagsItem);
1 ignored issue
show
Bug introduced by
The method driverWrite() does not exist on phpFastCache\Cache\DriverBaseTrait. Did you maybe mean driverWriteTags()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
249
        }
250
251
        /**
252
         * Also update removed tags to
253
         * keep the index up to date
254
         */
255
        $tagsItems = $this->getItems($this->getTagKeys($item->getRemovedTags()));
1 ignored issue
show
Bug introduced by
It seems like getItems() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
256
257
        foreach ($tagsItems as $tagsItem) {
258
            $data = (array) $tagsItem->get();
259
260
            unset($data[ $item->getKey() ]);
261
            $tagsItem->set($data);
262
263
            /**
264
             * Recalculate the expiration date
265
             *
266
             * If the $tagsItem does not have
267
             * any cache item references left
268
             * then remove it from tagsItems index
269
             */
270
            if (count($data)) {
271
                $tagsItem->expiresAt(max($data));
272
                $this->driverWrite($tagsItem);
1 ignored issue
show
Bug introduced by
The method driverWrite() does not exist on phpFastCache\Cache\DriverBaseTrait. Did you maybe mean driverWriteTags()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
273
            } else {
274
                $this->driverDelete($tagsItem);
1 ignored issue
show
Bug introduced by
It seems like driverDelete() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
275
            }
276
        }
277
278
        return true;
279
    }
280
281
    /**
282
     * @param $key
283
     * @return string
284
     */
285
    public function getTagKey($key)
286
    {
287
        return self::DRIVER_TAGS_KEY_PREFIX . $key;
288
    }
289
290
    /**
291
     * @param $key
292
     * @return string
293
     */
294
    public function getTagKeys(array $keys)
295
    {
296
        foreach ($keys as &$key) {
297
            $key = $this->getTagKey($key);
298
        }
299
300
        return $keys;
301
    }
302
}