Passed
Push — v7 ( ba093b...24d66b )
by Georges
02:14
created

Driver   A

Complexity

Total Complexity 28

Size/Duplication

Total Lines 167
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 167
rs 10
c 0
b 0
f 0
wmc 28

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A driverCheck() 0 3 1
A driverClear() 0 3 1
A driverDelete() 0 10 2
C driverConnect() 0 47 14
A driverWrite() 0 18 3
A driverRead() 0 9 2
A getStats() 0 14 4
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
declare(strict_types=1);
15
16
namespace Phpfastcache\Drivers\Memcached;
17
18
use Memcached as MemcachedSoftware;
19
use Phpfastcache\Config\ConfigurationOption;
20
use Phpfastcache\Core\Pool\{DriverBaseTrait, ExtendedCacheItemPoolInterface};
21
use Phpfastcache\Entities\DriverStatistic;
22
use Phpfastcache\Exceptions\{
23
  PhpfastcacheInvalidArgumentException, PhpfastcacheDriverException
24
};
25
use Phpfastcache\Util\{ArrayObject, MemcacheDriverCollisionDetectorTrait};
26
use Psr\Cache\CacheItemInterface;
27
28
/**
29
 * Class Driver
30
 * @package phpFastCache\Drivers
31
 * @property MemcachedSoftware $instance
32
 * @property Config $config Config object
33
 * @method Config getConfig() Return the config object
34
 */
35
class Driver implements ExtendedCacheItemPoolInterface
36
{
37
    use DriverBaseTrait {
38
        __construct as protected __parentConstruct;
39
    }
40
    use MemcacheDriverCollisionDetectorTrait;
41
42
    /**
43
     * Driver constructor.
44
     * @param ConfigurationOption $config
45
     * @param string $instanceId
46
     * @throws PhpfastcacheDriverException
47
     */
48
    public function __construct(ConfigurationOption $config, string $instanceId)
49
    {
50
        self::checkCollision('Memcached');
51
        $this->__parentConstruct($config, $instanceId);
52
    }
53
54
    /**
55
     * @return bool
56
     */
57
    public function driverCheck(): bool
58
    {
59
        return \class_exists('Memcached');
60
    }
61
62
    /**
63
     * @return bool
64
     */
65
    protected function driverConnect(): bool
66
    {
67
        $this->instance = new MemcachedSoftware();
68
        $this->instance->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
69
        $servers = $this->getConfig()->getServers();
70
71
        if (\count($servers) < 1) {
72
            $servers = [
73
              [
74
                'host' => $this->getConfig()->getHost(),
75
                'path' => $this->getConfig()->getPath(),
76
                'port' => $this->getConfig()->getPort(),
77
                'saslUser' => $this->getConfig()->getSaslUser() ?: false,
78
                'saslPassword' => $this->getConfig()->getSaslPassword() ?: false,
79
              ],
80
            ];
81
        }
82
83
        foreach ($servers as $server) {
84
            try {
85
                /**
86
                 * If path is provided we consider it as an UNIX Socket
87
                 */
88
                if(!empty($server[ 'path' ]) && !$this->instance->addServer($server[ 'path' ], 0)){
89
                    $this->fallback = true;
90
                }else if (!empty($server[ 'host' ]) && !$this->instance->addServer($server[ 'host' ], $server[ 'port' ])) {
91
                    $this->fallback = true;
92
                }
93
94
                if (!empty($server[ 'saslUser' ]) && !empty($server[ 'saslPassword' ])) {
95
                    $this->instance->setSaslAuthData($server[ 'saslUser' ], $server[ 'saslPassword' ]);
0 ignored issues
show
Bug introduced by
The method setSaslAuthData() does not exist on Memcached. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

95
                    $this->instance->/** @scrutinizer ignore-call */ 
96
                                     setSaslAuthData($server[ 'saslUser' ], $server[ 'saslPassword' ]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
96
                }
97
98
            } catch (\Exception $e) {
99
                $this->fallback = true;
100
            }
101
        }
102
103
        /**
104
         * Since Memcached does not throw
105
         * any error if not connected ...
106
         */
107
        $version = $this->instance->getVersion();
108
        if(!$version || $this->instance->getResultCode() !== MemcachedSoftware::RES_SUCCESS){
0 ignored issues
show
Bug Best Practice introduced by
The expression $version of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
109
            throw new PhpfastcacheDriverException('Memcached seems to not be connected');
110
        }
111
        return true;
112
    }
113
114
    /**
115
     * @param \Psr\Cache\CacheItemInterface $item
116
     * @return null|array
117
     */
118
    protected function driverRead(CacheItemInterface $item)
119
    {
120
        $val = $this->instance->get($item->getKey());
121
122
        if ($val === false) {
123
            return null;
124
        }
125
126
        return $val;
127
    }
128
129
    /**
130
     * @param \Psr\Cache\CacheItemInterface $item
131
     * @return bool
132
     * @throws PhpfastcacheInvalidArgumentException
133
     */
134
    protected function driverWrite(CacheItemInterface $item): bool
135
    {
136
        /**
137
         * Check for Cross-Driver type confusion
138
         */
139
        if ($item instanceof Item) {
140
            $ttl = $item->getExpirationDate()->getTimestamp() - \time();
141
142
            // Memcache will only allow a expiration timer less than 2592000 seconds,
143
            // otherwise, it will assume you're giving it a UNIX timestamp.
144
            if ($ttl > 2592000) {
145
                $ttl = \time() + $ttl;
146
            }
147
148
            return $this->instance->set($item->getKey(), $this->driverPreWrap($item), $ttl);
149
        }
150
151
        throw new PhpfastcacheInvalidArgumentException('Cross-Driver type confusion detected');
152
    }
153
154
    /**
155
     * @param \Psr\Cache\CacheItemInterface $item
156
     * @return bool
157
     * @throws PhpfastcacheInvalidArgumentException
158
     */
159
    protected function driverDelete(CacheItemInterface $item): bool
160
    {
161
        /**
162
         * Check for Cross-Driver type confusion
163
         */
164
        if ($item instanceof Item) {
165
            return $this->instance->delete($item->getKey());
166
        }
167
168
        throw new PhpfastcacheInvalidArgumentException('Cross-Driver type confusion detected');
169
    }
170
171
    /**
172
     * @return bool
173
     */
174
    protected function driverClear(): bool
175
    {
176
        return $this->instance->flush();
177
    }
178
179
    /********************
180
     *
181
     * PSR-6 Extended Methods
182
     *
183
     *******************/
184
185
    /**
186
     * @return DriverStatistic
187
     */
188
    public function getStats(): DriverStatistic
189
    {
190
        $stats = current($this->instance->getStats());
191
        $stats[ 'uptime' ] = (isset($stats[ 'uptime' ]) ? $stats[ 'uptime' ] : 0);
192
        $stats[ 'version' ] = (isset($stats[ 'version' ]) ? $stats[ 'version' ] : $this->instance->getVersion());
193
        $stats[ 'bytes' ] = (isset($stats[ 'bytes' ]) ? $stats[ 'version' ] : 0);
194
195
        $date = (new \DateTime())->setTimestamp(\time() - $stats[ 'uptime' ]);
196
197
        return (new DriverStatistic())
198
          ->setData(\implode(', ', \array_keys($this->itemInstances)))
199
          ->setInfo(\sprintf("The memcache daemon v%s is up since %s.\n For more information see RawData.", $stats[ 'version' ], $date->format(DATE_RFC2822)))
200
          ->setRawData($stats)
201
          ->setSize((int)$stats[ 'bytes' ]);
202
    }
203
}