Completed
Pull Request — final (#566)
by Georges
03:33
created

Driver::driverConnect()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 34
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 34
rs 8.439
c 0
b 0
f 0
cc 5
eloc 20
nc 16
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\Predis;
16
17
use phpFastCache\Core\Pool\DriverBaseTrait;
18
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface;
19
use phpFastCache\Entities\DriverStatistic;
20
use phpFastCache\Exceptions\phpFastCacheDriverCheckException;
21
use phpFastCache\Exceptions\phpFastCacheDriverException;
22
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException;
23
use Predis\Client as PredisClient;
24
use Predis\Connection\ConnectionException as PredisConnectionException;
25
use Psr\Cache\CacheItemInterface;
26
27
/**
28
 * Class Driver
29
 * @package phpFastCache\Drivers
30
 * @property PredisClient $instance Instance of driver service
31
 */
32
class Driver implements ExtendedCacheItemPoolInterface
33
{
34
    use DriverBaseTrait;
35
36
    /**
37
     * Driver constructor.
38
     * @param array $config
39
     * @throws phpFastCacheDriverException
40
     */
41
    public function __construct(array $config = [])
42
    {
43
        $this->setup($config);
44
45
        if (!$this->driverCheck()) {
46
            throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName()));
47
        } else {
48
            $this->driverConnect();
49
        }
50
    }
51
52
    /**
53
     * @return bool
54
     */
55
    public function driverCheck()
56
    {
57
        if (extension_loaded('Redis')) {
58
            trigger_error('The native Redis extension is installed, you should use Redis instead of Predis to increase performances', E_USER_NOTICE);
59
        }
60
61
        return class_exists('Predis\Client');
62
    }
63
64
    /**
65
     * @param \Psr\Cache\CacheItemInterface $item
66
     * @return mixed
67
     * @throws phpFastCacheInvalidArgumentException
68
     */
69 View Code Duplication
    protected function driverWrite(CacheItemInterface $item)
70
    {
71
        /**
72
         * Check for Cross-Driver type confusion
73
         */
74
        if ($item instanceof Item) {
75
            $ttl = $item->getExpirationDate()->getTimestamp() - time();
76
77
            /**
78
             * @see https://redis.io/commands/setex
79
             * @see https://redis.io/commands/expire
80
             */
81
            if($ttl <= 0){
82
                return $this->instance->expire($item->getKey(), 0);
83
            }else{
84
                return $this->instance->setex($item->getKey(), $ttl, $this->encode($this->driverPreWrap($item)));
85
            }
86
        } else {
87
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
88
        }
89
    }
90
91
    /**
92
     * @param \Psr\Cache\CacheItemInterface $item
93
     * @return null|array
94
     */
95 View Code Duplication
    protected function driverRead(CacheItemInterface $item)
96
    {
97
        $val = $this->instance->get($item->getKey());
98
        if ($val == false) {
99
            return null;
100
        } else {
101
            return $this->decode($val);
102
        }
103
    }
104
105
    /**
106
     * @param \Psr\Cache\CacheItemInterface $item
107
     * @return bool
108
     * @throws phpFastCacheInvalidArgumentException
109
     */
110 View Code Duplication
    protected function driverDelete(CacheItemInterface $item)
111
    {
112
        /**
113
         * Check for Cross-Driver type confusion
114
         */
115
        if ($item instanceof Item) {
116
            return $this->instance->del([$item->getKey()]);
117
        } else {
118
            throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected');
119
        }
120
    }
121
122
    /**
123
     * @return bool
124
     */
125
    protected function driverClear()
126
    {
127
        return $this->instance->flushdb();
128
    }
129
130
    /**
131
     * @return bool
132
     * @throws phpFastCacheDriverException
133
     */
134
    protected function driverConnect()
135
    {
136
        /** Backward compatibility */
137
        $config = isset($this->config[ 'predis' ]) ? $this->config[ 'predis' ] : $this->config;
138
        $path = isset($config[ 'path' ]) ? (string) $config[ 'path' ] : false;
139
140
        $defaultConfig = [
141
          'host' => '127.0.0.1',
142
          'port' => 6379,
143
          'password' => null,
144
          'database' => null,
145
        ];
146
        $config = array_merge($defaultConfig, $config);
147
148
        /**
149
         * If path is provided we consider it as an UNIX Socket
150
         */
151
        if($path){
0 ignored issues
show
Bug Best Practice introduced by
The expression $path of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
152
            $this->instance = new PredisClient([
153
              'scheme' => 'unix',
154
              'path' =>  $path
155
            ]);
156
        }else{
157
            $this->instance = new PredisClient($config);
158
        }
159
160
        try {
161
            $this->instance->connect();
162
        } catch (PredisConnectionException $e) {
163
            throw new phpFastCacheDriverException('Failed to connect to predis server. Check the Predis documentation: https://github.com/nrk/predis/tree/v1.1#how-to-install-and-use-predis', 0, $e);
164
        }
165
166
        return true;
167
    }
168
169
    /********************
170
     *
171
     * PSR-6 Extended Methods
172
     *
173
     *******************/
174
175
176
    /**
177
     * @return string
178
     */
179
    public function getHelp()
180
    {
181
        return <<<HELP
182
<p>
183
To install the Predis library via Composer:
184
<code>composer require "predis/predis" "~1.1.0"</code>
185
</p>
186
HELP;
187
    }
188
189
    /**
190
     * @return DriverStatistic
191
     */
192 View Code Duplication
    public function getStats()
193
    {
194
        $info = $this->instance->info();
195
        $size = (isset($info[ 'Memory' ][ 'used_memory' ]) ? $info[ 'Memory' ][ 'used_memory' ] : 0);
196
        $version = (isset($info[ 'Server' ][ 'redis_version' ]) ? $info[ 'Server' ][ 'redis_version' ] : 0);
197
        $date = (isset($info[ 'Server' ][ 'uptime_in_seconds' ]) ? (new \DateTime())->setTimestamp(time() - $info[ 'Server' ][ 'uptime_in_seconds' ]) : 'unknown date');
198
199
        return (new DriverStatistic())
200
          ->setData(implode(', ', array_keys($this->itemInstances)))
201
          ->setRawData($info)
202
          ->setSize($size)
203
          ->setInfo(sprintf("The Redis daemon v%s is up since %s.\n For more information see RawData. \n Driver size includes the memory allocation size.",
204
            $version, $date->format(DATE_RFC2822)));
205
    }
206
}