Test Failed
Push — master ( 3f03af...9d5adc )
by
unknown
11:45
created

Driver::driverConnect()   B

Complexity

Conditions 11
Paths 40

Size

Total Lines 42
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 22
nc 40
nop 0
dl 0
loc 42
rs 7.3166
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 *
5
 * This file is part of Phpfastcache.
6
 *
7
 * @license MIT License (MIT)
8
 *
9
 * For full copyright and license information, please see the docs/CREDITS.txt and LICENCE files.
10
 *
11
 * @author Georges.L (Geolim4)  <[email protected]>
12
 * @author Contributors  https://github.com/PHPSocialNetwork/phpfastcache/graphs/contributors
13
 */
14
15
declare(strict_types=1);
16
17
namespace Phpfastcache\Drivers\Memcached;
18
19
use DateTime;
20
use Memcached as MemcachedSoftware;
21
use Phpfastcache\Cluster\AggregatablePoolInterface;
22
use Phpfastcache\Config\ConfigurationOption;
23
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
24
use Phpfastcache\Core\Pool\TaggableCacheItemPoolTrait;
25
use Phpfastcache\Core\Item\ExtendedCacheItemInterface;
26
use Phpfastcache\Entities\DriverStatistic;
27
use Phpfastcache\Event\EventManagerInterface;
28
use Phpfastcache\Exceptions\PhpfastcacheCoreException;
29
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
30
use Phpfastcache\Exceptions\PhpfastcacheDriverConnectException;
31
use Phpfastcache\Exceptions\PhpfastcacheDriverException;
32
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
33
use Phpfastcache\Exceptions\PhpfastcacheInvalidTypeException;
34
use Phpfastcache\Exceptions\PhpfastcacheIOException;
35
use Phpfastcache\Exceptions\PhpfastcacheLogicException;
36
use Phpfastcache\Util\MemcacheDriverCollisionDetectorTrait;
37
use Psr\Cache\CacheItemInterface;
38
39
/**
40
 * @property MemcachedSoftware $instance
41
 * @method Config getConfig()
42
 */
43
class Driver implements AggregatablePoolInterface
44
{
45
    use TaggableCacheItemPoolTrait {
46
        __construct as protected __parentConstruct;
47
    }
48
    use MemcacheDriverCollisionDetectorTrait;
49
50
    /**
51
     * Driver constructor.
52
     * @param ConfigurationOption $config
53
     * @param string $instanceId
54
     * @param EventManagerInterface $em
55
     * @throws PhpfastcacheDriverConnectException
56
     * @throws PhpfastcacheInvalidArgumentException
57
     * @throws PhpfastcacheCoreException
58
     * @throws PhpfastcacheDriverCheckException
59
     * @throws PhpfastcacheIOException
60
     */
61
    public function __construct(ConfigurationOption $config, string $instanceId, EventManagerInterface $em)
62
    {
63
        self::checkCollision('Memcached');
64
        $this->__parentConstruct($config, $instanceId, $em);
65
    }
66
67
    /**
68
     * @return bool
69
     */
70
    public function driverCheck(): bool
71
    {
72
        return class_exists('Memcached');
73
    }
74
75
    /**
76
     * @return DriverStatistic
77
     */
78
    public function getStats(): DriverStatistic
79
    {
80
        $stats = current($this->instance->getStats());
81
        $stats['uptime'] = $stats['uptime'] ?? 0;
82
        $stats['bytes'] = $stats['bytes'] ?? 0;
83
        $stats['version'] = $stats['version'] ?? $this->instance->getVersion();
84
85
        $date = (new DateTime())->setTimestamp(time() - $stats['uptime']);
86
87
        return (new DriverStatistic())
0 ignored issues
show
Deprecated Code introduced by
The function Phpfastcache\Entities\DriverStatistic::setData() has been deprecated: as of phpfastcache 9.2.3, will be removed as of v10 ( Ignorable by Annotation )

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

87
        return /** @scrutinizer ignore-deprecated */ (new DriverStatistic())

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
88
            ->setData(implode(', ', array_keys($this->itemInstances)))
89
            ->setInfo(sprintf("The memcache daemon v%s is up since %s.\n For more information see RawData.", $stats['version'], $date->format(DATE_RFC2822)))
90
            ->setRawData($stats)
91
            ->setSize((int)$stats['bytes']);
92
    }
93
94
    /**
95
     * @return bool
96
     * @throws PhpfastcacheDriverException
97
     */
98
    protected function driverConnect(): bool
99
    {
100
        $this->instance = new MemcachedSoftware();
101
        $optPrefix = $this->getConfig()->getOptPrefix();
102
        $this->instance->setOption(MemcachedSoftware::OPT_BINARY_PROTOCOL, true);
103
104
        if ($optPrefix) {
105
            $this->instance->setOption(MemcachedSoftware::OPT_PREFIX_KEY, $optPrefix);
106
        }
107
108
        foreach ($this->getConfig()->getServers() as $server) {
109
            $connected = false;
110
            /**
111
             * If path is provided we consider it as an UNIX Socket
112
             */
113
            if (!empty($server['path'])) {
114
                $connected = $this->instance->addServer($server['path'], 0);
115
            } elseif (!empty($server['host'])) {
116
                $connected = $this->instance->addServer($server['host'], $server['port']);
117
            }
118
            if (!empty($server['saslUser']) && !empty($server['saslPassword'])) {
119
                $this->instance->setSaslAuthData($server['saslUser'], $server['saslPassword']);
120
            }
121
            if (!$connected) {
122
                throw new PhpfastcacheDriverConnectException(
123
                    sprintf(
124
                        'Failed to connect to memcache host/path "%s".',
125
                        $server['host'] ?: $server['path'],
126
                    )
127
                );
128
            }
129
        }
130
131
        /**
132
         * Since Memcached does not throw
133
         * any error if not connected ...
134
         */
135
        $version = $this->instance->getVersion();
136
        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...
137
            throw new PhpfastcacheDriverException('Memcached seems to not be connected');
138
        }
139
        return true;
140
    }
141
142
    /**
143
     * @param ExtendedCacheItemInterface $item
144
     * @return ?array<string, mixed>
145
     */
146
    protected function driverRead(ExtendedCacheItemInterface $item): ?array
147
    {
148
        $val = $this->instance->get($item->getKey());
149
150
        if (empty($val) || !\is_array($val)) {
151
            return null;
152
        }
153
154
        return $val;
155
    }
156
157
    /**
158
     * @param ExtendedCacheItemInterface ...$items
159
     * @return array<array<string, mixed>>
160
     */
161
    protected function driverReadMultiple(ExtendedCacheItemInterface ...$items): array
162
    {
163
        $keys = $this->getKeys($items);
164
165
        $val = $this->instance->getMulti($keys);
166
167
        if (empty($val) || !\is_array($val)) {
168
            return [];
169
        }
170
171
        return $val;
172
    }
173
174
175
    /**
176
     * @return array<string, mixed>
177
     * @throws PhpfastcacheInvalidArgumentException
178
     */
179
    protected function driverReadAllKeys(string $pattern = ''): iterable
180
    {
181
        if ($pattern !== '') {
182
            $this->throwUnsupportedDriverReadAllPattern('https://www.php.net/manual/en/memcached.getallkeys.php');
183
        }
184
        $keys = $this->instance->getAllKeys();
185
186
        if (is_iterable($keys)) {
187
            return $keys;
188
        } else {
189
            return [];
190
        }
191
    }
192
193
    /**
194
     * @param ExtendedCacheItemInterface $item
195
     * @return bool
196
     * @throws PhpfastcacheInvalidArgumentException
197
     * @throws PhpfastcacheLogicException
198
     */
199
    protected function driverWrite(ExtendedCacheItemInterface $item): bool
200
    {
201
202
        $ttl = $item->getExpirationDate()->getTimestamp() - time();
203
204
        // Memcache will only allow a expiration timer less than 2592000 seconds,
205
        // otherwise, it will assume you're giving it a UNIX timestamp.
206
        if ($ttl > 2592000) {
207
            $ttl = time() + $ttl;
208
        }
209
210
        return $this->instance->set($item->getKey(), $this->driverPreWrap($item), $ttl);
211
    }
212
213
    /**
214
     * @param string $key
215
     * @param string $encodedKey
216
     * @return bool
217
     */
218
    protected function driverDelete(string $key, string $encodedKey): bool
219
    {
220
        return $this->instance->delete($key);
221
    }
222
223
    /**
224
     * @return bool
225
     */
226
    protected function driverClear(): bool
227
    {
228
        return $this->instance->flush();
229
    }
230
}
231