Completed
Push — v5 ( a234cb...4f37c0 )
by Georges
02:54
created

Driver::driverCheck()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
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\Cookie;
16
17
use phpFastCache\Core\DriverAbstract;
18
use phpFastCache\Core\StandardPsr6StructureTrait;
19
use phpFastCache\Entities\driverStatistic;
20
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
21
use phpFastCache\Exceptions\phpFastCacheDriverException;
22
use Psr\Cache\CacheItemInterface;
23
24
/**
25
 * Class Driver
26
 * @package phpFastCache\Drivers
27
 */
28
class Driver extends DriverAbstract
29
{
30
    use StandardPsr6StructureTrait;
31
    const PREFIX = 'PFC_';
32
33
    /**
34
     * Driver constructor.
35
     * @param array $config
36
     * @throws phpFastCacheDriverException
37
     */
38 View Code Duplication
    public function __construct(array $config = [])
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...
39
    {
40
        $this->setup($config);
41
42
        if (!$this->driverCheck()) {
43
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
44
        }
45
    }
46
47
    /**
48
     * @return bool
49
     */
50
    public function driverCheck()
51
    {
52
        if (function_exists('setcookie')) {
53
            return true;
54
        } else {
55
            return false;
56
        }
57
    }
58
59
    /**
60
     * @return bool
61
     */
62
    protected function driverConnect()
0 ignored issues
show
Coding Style introduced by
driverConnect uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
63
    {
64
        return !(!array_key_exists('phpFastCache', $_COOKIE) && !@setcookie('phpFastCache', 1, 10));
65
    }
66
67
    /**
68
     * @param \Psr\Cache\CacheItemInterface $item
69
     * @return mixed
70
     * @throws \InvalidArgumentException
71
     */
72
    protected function driverWrite(CacheItemInterface $item)
73
    {
74
        /**
75
         * Check for Cross-Driver type confusion
76
         */
77
        if ($item instanceof Item) {
78
            $this->driverConnect();
79
            $keyword = self::PREFIX . $item->getKey();
80
            $v = json_encode($this->driverPreWrap($item));
81
82
            if (isset($this->config[ 'limited_memory_each_object' ]) && strlen($v) > $this->config[ 'limited_memory_each_object' ]) {
83
                return false;
84
            }
85
86
            return setcookie($keyword, $v, $item->getExpirationDate()->getTimestamp(), '/');
87
        } else {
88
            throw new \InvalidArgumentException('Cross-Driver type confusion detected');
89
        }
90
    }
91
92
    /**
93
     * @param \Psr\Cache\CacheItemInterface $item
94
     * @return mixed
95
     * @throws \phpFastCache\Exceptions\phpFastCacheDriverException
96
     */
97
    protected function driverRead(CacheItemInterface $item)
0 ignored issues
show
Coding Style introduced by
driverRead uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
98
    {
99
        $this->driverConnect();
100
        // return null if no caching
101
        // return value if in caching
102
        $keyword = self::PREFIX . $item->getKey();
103
        $x = isset($_COOKIE[ $keyword ]) ? $this->decode(json_decode($_COOKIE[ $keyword ], true)) : false;
104
105
        if ($x == false) {
106
            return null;
107
        } else {
108
            if (!is_scalar($this->driverUnwrapData($x)) && !is_null($this->driverUnwrapData($x))) {
109
                throw new phpFastCacheDriverException('Hacking attempt: The decoding returned a non-scalar value, Cookie driver does not allow this.');
110
            }
111
112
            return $x;
113
        }
114
    }
115
116
    /**
117
     * @param $key
118
     * @return int
119
     */
120
    protected function driverReadExpirationDate($key)
0 ignored issues
show
Coding Style introduced by
driverReadExpirationDate uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
121
    {
122
        $this->driverConnect();
123
        $keyword = self::PREFIX . $key;
124
        $x = isset($_COOKIE[ $keyword ]) ? $this->decode(json_decode($_COOKIE[ $keyword ])->t) : false;
125
126
        return $x ? $x - time() : $x;
127
    }
128
129
    /**
130
     * @param \Psr\Cache\CacheItemInterface $item
131
     * @return bool
132
     * @throws \InvalidArgumentException
133
     */
134
    protected function driverDelete(CacheItemInterface $item)
0 ignored issues
show
Coding Style introduced by
driverDelete uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
135
    {
136
        /**
137
         * Check for Cross-Driver type confusion
138
         */
139
        if ($item instanceof Item) {
140
            $this->driverConnect();
141
            $keyword = self::PREFIX . $item->getKey();
142
            $_COOKIE[ $keyword ] = null;
143
144
            return @setcookie($keyword, null, -10);
145
        } else {
146
            throw new \InvalidArgumentException('Cross-Driver type confusion detected');
147
        }
148
    }
149
150
    /**
151
     * @return bool
152
     */
153
    protected function driverClear()
0 ignored issues
show
Coding Style introduced by
driverClear uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
154
    {
155
        $return = null;
156
        $this->driverConnect();
157
        foreach ($_COOKIE as $keyword => $value) {
158
            if (strpos($keyword, self::PREFIX) !== false) {
159
                $_COOKIE[ $keyword ] = null;
160
                $result = @setcookie($keyword, null, -10);
161
                if ($return !== false) {
162
                    $return = $result;
163
                }
164
            }
165
        }
166
167
        return $return;
168
    }
169
170
    /********************
171
     *
172
     * PSR-6 Extended Methods
173
     *
174
     *******************/
175
176
    /**
177
     * @return driverStatistic
178
     */
179
    public function getStats()
0 ignored issues
show
Coding Style introduced by
getStats uses the super-global variable $_COOKIE which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
180
    {
181
        $size = 0;
182
        $stat = new driverStatistic();
183
        $stat->setData($_COOKIE);
184
185
        /**
186
         * Only count PFC Cookie
187
         */
188
        foreach ($_COOKIE as $key => $value) {
189
            if (strpos($key, self::PREFIX) === 0) {
190
                $size += strlen($value);
191
            }
192
        }
193
194
        $stat->setSize($size);
195
196
        return $stat;
197
    }
198
}