Issues (27)

src/Memcached.php (2 issues)

1
<?php
2
3
/*
4
 * This file is part of the Cache package.
5
 *
6
 * Copyright (c) Daniel González
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 *
11
 * @author Daniel González <[email protected]>
12
 * @author Arnold Daniels <[email protected]>
13
 */
14
15
declare(strict_types=1);
16
17
namespace Desarrolla2\Cache;
18
19
use Desarrolla2\Cache\Exception\InvalidArgumentException;
20
use Desarrolla2\Cache\Packer\PackerInterface;
21
use Desarrolla2\Cache\Packer\NopPacker;
22
use Memcached as MemcachedServer;
23
24
/**
25
 * Memcached
26
 */
27
class Memcached extends AbstractCache
28
{
29
    /**
30
     * @var MemcachedServer
31
     */
32
    protected $server;
33
34
    /**
35
     * @param MemcachedServer $server
36
     */
37 197
    public function __construct(MemcachedServer $server)
38
    {
39 197
        $this->server = $server;
40
    }
41
42
43
    /**
44
     * Create the default packer for this cache implementation
45
     *
46
     * @return PackerInterface
47
     */
48 80
    protected static function createDefaultPacker(): PackerInterface
49
    {
50 80
        return new NopPacker();
51
    }
52
53
    /**
54
     * Validate the key
55
     *
56
     * @param string $key
57
     * @return void
58
     * @throws InvalidArgumentException
59
     */
60 189
    protected function assertKey($key): void
61
    {
62 189
        parent::assertKey($key);
63
64 117
        if (strlen($key) > 250) {
65
            throw new InvalidArgumentException("Key to long, max 250 characters");
66
        }
67
    }
68
69
    /**
70
     * Pack all values and turn keys into ids
71
     *
72
     * @param iterable $values
73
     * @return array
74
     */
75 41
    protected function packValues(iterable $values): array
76
    {
77 41
        $packed = [];
78
79 41
        foreach ($values as $key => $value) {
80 41
            $this->assertKey(is_int($key) ? (string)$key : $key);
81 41
            $packed[$key] = $this->pack($value);
82
        }
83
84 24
        return $packed;
85
    }
86
87
88
    /**
89
     * {@inheritdoc}
90
     */
91 51
    public function get($key, $default = null)
92
    {
93 51
        $this->assertKey($key);
94
95 33
        $data = $this->server->get($key);
96
97 33
        if ($this->server->getResultCode() !== MemcachedServer::RES_SUCCESS) {
98 11
            return $default;
99
        }
100
101 26
        return $this->unpack($data);
102
    }
103
104
    /**
105
     * {@inheritdoc}
106
     */
107 21
    public function has($key)
108
    {
109 21
        $this->assertKey($key);
110 3
        $this->server->get($key);
111
112 3
        $result = $this->server->getResultCode();
113
114 3
        return $result === MemcachedServer::RES_SUCCESS;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120 57
    public function set($key, $value, $ttl = null)
121
    {
122 57
        $this->assertKey($key);
123
124 39
        $packed = $this->pack($value);
125 39
        $ttlTime = $this->ttlToMemcachedTime($ttl);
126
127 29
        if ($ttlTime === false) {
0 ignored issues
show
The condition $ttlTime === false is always false.
Loading history...
128 1
            return $this->delete($key);
129
        }
130
131 29
        $success = $this->server->set($key, $packed, $ttlTime);
132
133 29
        return $success;
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139 40
    public function delete($key)
140
    {
141 40
        $this->server->delete($this->keyToId($key));
142
143 22
        $result = $this->server->getResultCode();
144
145 22
        return $result === MemcachedServer::RES_SUCCESS || $result === MemcachedServer::RES_NOTFOUND;
146
    }
147
148
    /**
149
     * {@inheritdoc}
150
     */
151 30
    public function getMultiple($keys, $default = null)
152
    {
153 30
        $this->assertIterable($keys, 'keys not iterable');
154 29
        $keysArr = is_array($keys) ? $keys : iterator_to_array($keys, false);
155 29
        array_walk($keysArr, [$this, 'assertKey']);
156
157 11
        $result = $this->server->getMulti($keysArr);
158
159 11
        if ($result === false) {
160
            return false;
161
        }
162
163 11
        $items = array_fill_keys($keysArr, $default);
164
165 11
        foreach ($result as $key => $value) {
166 11
            $items[$key] = $this->unpack($value);
167
        }
168
169 11
        return $items;
170
    }
171
172
    /**
173
     * {@inheritdoc}
174
     */
175 42
    public function setMultiple($values, $ttl = null)
176
    {
177 42
        $this->assertIterable($values, 'values not iterable');
178
179 41
        $packed = $this->packValues($values);
180 24
        $ttlTime = $this->ttlToMemcachedTime($ttl);
181
182 14
        if ($ttlTime === false) {
0 ignored issues
show
The condition $ttlTime === false is always false.
Loading history...
183 1
            return $this->server->deleteMulti(array_keys($packed));
184
        }
185
186 13
        return $this->server->setMulti($packed, $ttlTime);
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 197
    public function clear()
193
    {
194 197
       return $this->server->flush();
195
    }
196
197
198
    /**
199
     * Convert ttl to timestamp or seconds.
200
     *
201
     * @see http://php.net/manual/en/memcached.expiration.php
202
     *
203
     * @param null|int|\DateInterval $ttl
204
     * @return int|null
205
     * @throws InvalidArgumentException
206
     */
207 63
    protected function ttlToMemcachedTime($ttl)
208
    {
209 63
        $seconds = $this->ttlToSeconds($ttl);
210
211 43
        if ($seconds <= 0) {
212 41
            return isset($seconds) ? false : 0;
213
        }
214
215
        /* 2592000 seconds = 30 days */
216 2
        return $seconds <= 2592000 ? $seconds : $this->ttlToTimestamp($ttl);
217
    }
218
}
219