• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 12704370970

10 Jan 2025 06:18AM UTC coverage: 84.454%. Remained the same
12704370970

Pull #9395

github

web-flow
Merge f916c0a32 into 708fb6d70
Pull Request #9395: chore: add more trailing commas in more places

337 of 397 new or added lines in 117 files covered. (84.89%)

1 existing line in 1 file now uncovered.

20464 of 24231 relevant lines covered (84.45%)

189.67 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

67.47
/system/Cache/Handlers/MemcachedHandler.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter\Cache\Handlers;
15

16
use CodeIgniter\Exceptions\CriticalError;
17
use CodeIgniter\I18n\Time;
18
use Config\Cache;
19
use Exception;
20
use Memcache;
21
use Memcached;
22

23
/**
24
 * Mamcached cache handler
25
 *
26
 * @see \CodeIgniter\Cache\Handlers\MemcachedHandlerTest
27
 */
28
class MemcachedHandler extends BaseHandler
29
{
30
    /**
31
     * The memcached object
32
     *
33
     * @var Memcache|Memcached
34
     */
35
    protected $memcached;
36

37
    /**
38
     * Memcached Configuration
39
     *
40
     * @var array
41
     */
42
    protected $config = [
43
        'host'   => '127.0.0.1',
44
        'port'   => 11211,
45
        'weight' => 1,
46
        'raw'    => false,
47
    ];
48

49
    /**
50
     * Note: Use `CacheFactory::getHandler()` to instantiate.
51
     */
52
    public function __construct(Cache $config)
53
    {
54
        $this->prefix = $config->prefix;
14✔
55

56
        $this->config = array_merge($this->config, $config->memcached);
14✔
57
    }
58

59
    /**
60
     * Closes the connection to Memcache(d) if present.
61
     */
62
    public function __destruct()
63
    {
64
        if ($this->memcached instanceof Memcached) {
2✔
65
            $this->memcached->quit();
2✔
66
        } elseif ($this->memcached instanceof Memcache) {
×
67
            $this->memcached->close();
×
68
        }
69
    }
70

71
    /**
72
     * {@inheritDoc}
73
     */
74
    public function initialize()
75
    {
76
        try {
77
            if (class_exists(Memcached::class)) {
14✔
78
                // Create new instance of Memcached
79
                $this->memcached = new Memcached();
14✔
80
                if ($this->config['raw']) {
14✔
81
                    $this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
2✔
82
                }
83

84
                // Add server
85
                $this->memcached->addServer(
14✔
86
                    $this->config['host'],
14✔
87
                    $this->config['port'],
14✔
88
                    $this->config['weight']
14✔
89
                );
14✔
90

91
                // attempt to get status of servers
92
                $stats = $this->memcached->getStats();
14✔
93

94
                // $stats should be an associate array with a key in the format of host:port.
95
                // If it doesn't have the key, we know the server is not working as expected.
96
                if (! isset($stats[$this->config['host'] . ':' . $this->config['port']])) {
14✔
97
                    throw new CriticalError('Cache: Memcached connection failed.');
×
98
                }
99
            } elseif (class_exists(Memcache::class)) {
×
100
                // Create new instance of Memcache
101
                $this->memcached = new Memcache();
×
102

103
                // Check if we can connect to the server
104
                $canConnect = $this->memcached->connect(
×
105
                    $this->config['host'],
×
NEW
106
                    $this->config['port']
×
107
                );
×
108

109
                // If we can't connect, throw a CriticalError exception
110
                if ($canConnect === false) {
×
111
                    throw new CriticalError('Cache: Memcache connection failed.');
×
112
                }
113

114
                // Add server, third parameter is persistence and defaults to TRUE.
115
                $this->memcached->addServer(
×
116
                    $this->config['host'],
×
117
                    $this->config['port'],
×
118
                    true,
×
NEW
119
                    $this->config['weight']
×
120
                );
×
121
            } else {
122
                throw new CriticalError('Cache: Not support Memcache(d) extension.');
14✔
123
            }
124
        } catch (Exception $e) {
×
125
            throw new CriticalError('Cache: Memcache(d) connection refused (' . $e->getMessage() . ').');
×
126
        }
127
    }
128

129
    /**
130
     * {@inheritDoc}
131
     */
132
    public function get(string $key)
133
    {
134
        $data = [];
2✔
135
        $key  = static::validateKey($key, $this->prefix);
2✔
136

137
        if ($this->memcached instanceof Memcached) {
2✔
138
            $data = $this->memcached->get($key);
2✔
139

140
            // check for unmatched key
141
            if ($this->memcached->getResultCode() === Memcached::RES_NOTFOUND) {
2✔
142
                return null;
2✔
143
            }
144
        } elseif ($this->memcached instanceof Memcache) {
×
145
            $flags = false;
×
146
            $data  = $this->memcached->get($key, $flags);
×
147

148
            // check for unmatched key (i.e. $flags is untouched)
149
            if ($flags === false) {
×
150
                return null;
×
151
            }
152
        }
153

154
        return is_array($data) ? $data[0] : $data;
2✔
155
    }
156

157
    /**
158
     * {@inheritDoc}
159
     */
160
    public function save(string $key, $value, int $ttl = 60)
161
    {
162
        $key = static::validateKey($key, $this->prefix);
10✔
163

164
        if (! $this->config['raw']) {
10✔
165
            $value = [
10✔
166
                $value,
10✔
167
                Time::now()->getTimestamp(),
10✔
168
                $ttl,
10✔
169
            ];
10✔
170
        }
171

172
        if ($this->memcached instanceof Memcached) {
10✔
173
            return $this->memcached->set($key, $value, $ttl);
10✔
174
        }
175

176
        if ($this->memcached instanceof Memcache) {
×
177
            return $this->memcached->set($key, $value, 0, $ttl);
×
178
        }
179

180
        return false;
×
181
    }
182

183
    /**
184
     * {@inheritDoc}
185
     */
186
    public function delete(string $key)
187
    {
188
        $key = static::validateKey($key, $this->prefix);
14✔
189

190
        return $this->memcached->delete($key);
14✔
191
    }
192

193
    /**
194
     * {@inheritDoc}
195
     *
196
     * @return never
197
     */
198
    public function deleteMatching(string $pattern)
199
    {
200
        throw new Exception('The deleteMatching method is not implemented for Memcached. You must select File, Redis or Predis handlers to use it.');
1✔
201
    }
202

203
    /**
204
     * {@inheritDoc}
205
     */
206
    public function increment(string $key, int $offset = 1)
207
    {
208
        if (! $this->config['raw']) {
1✔
209
            return false;
1✔
210
        }
211

212
        $key = static::validateKey($key, $this->prefix);
1✔
213

214
        return $this->memcached->increment($key, $offset, $offset, 60);
1✔
215
    }
216

217
    /**
218
     * {@inheritDoc}
219
     */
220
    public function decrement(string $key, int $offset = 1)
221
    {
222
        if (! $this->config['raw']) {
1✔
223
            return false;
1✔
224
        }
225

226
        $key = static::validateKey($key, $this->prefix);
1✔
227

228
        // FIXME: third parameter isn't other handler actions.
229

230
        return $this->memcached->decrement($key, $offset, $offset, 60);
1✔
231
    }
232

233
    /**
234
     * {@inheritDoc}
235
     */
236
    public function clean()
237
    {
238
        return $this->memcached->flush();
1✔
239
    }
240

241
    /**
242
     * {@inheritDoc}
243
     */
244
    public function getCacheInfo()
245
    {
246
        return $this->memcached->getStats();
1✔
247
    }
248

249
    /**
250
     * {@inheritDoc}
251
     */
252
    public function getMetaData(string $key)
253
    {
254
        $key    = static::validateKey($key, $this->prefix);
3✔
255
        $stored = $this->memcached->get($key);
3✔
256

257
        // if not an array, don't try to count for PHP7.2
258
        if (! is_array($stored) || count($stored) !== 3) {
3✔
259
            return false; // @TODO This will return null in a future release
1✔
260
        }
261

262
        [$data, $time, $limit] = $stored;
2✔
263

264
        return [
2✔
265
            'expire' => $limit > 0 ? $time + $limit : null,
2✔
266
            'mtime'  => $time,
2✔
267
            'data'   => $data,
2✔
268
        ];
2✔
269
    }
270

271
    /**
272
     * {@inheritDoc}
273
     */
274
    public function isSupported(): bool
275
    {
276
        return extension_loaded('memcached') || extension_loaded('memcache');
1✔
277
    }
278
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc