Passed
Push — master ( e9b91c...231a7e )
by Luís
14:22 queued 12s
created

MemcachedCache::validateCacheId()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 6
nc 4
nop 1
dl 0
loc 12
ccs 7
cts 7
cp 1
crap 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Doctrine\Common\Cache;
4
5
use Memcached;
6
use function array_keys;
7
use function preg_match;
8
use function strlen;
9
use function strpos;
10
use function time;
11
12
/**
13
 * Memcached cache provider.
14
 *
15
 * @link   www.doctrine-project.org
16
 */
17
class MemcachedCache extends CacheProvider
18
{
19
    public const CACHE_ID_MAX_LENGTH = 250;
20
21
    /** @var Memcached|null */
22
    private $memcached;
23
24
    /**
25
     * Sets the memcache instance to use.
26
     *
27
     * @return void
28
     */
29 84
    public function setMemcached(Memcached $memcached)
30
    {
31 84
        $this->memcached = $memcached;
32 84
    }
33
34
    /**
35
     * Gets the memcached instance used by the cache.
36
     *
37
     * @return Memcached|null
38
     */
39 1
    public function getMemcached()
40
    {
41 1
        return $this->memcached;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47 81
    protected function doFetch($id)
48
    {
49 81
        return $this->memcached->get($id);
0 ignored issues
show
Bug introduced by
The method get() does not exist on null. ( Ignorable by Annotation )

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

49
        return $this->memcached->/** @scrutinizer ignore-call */ get($id);

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...
50
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 2
    protected function doFetchMultiple(array $keys)
56
    {
57 2
        return $this->memcached->getMulti($keys) ?: [];
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 4
    protected function doSaveMultiple(array $keysAndValues, $lifetime = 0)
64
    {
65 4
        foreach (array_keys($keysAndValues) as $id) {
66 4
            $this->validateCacheId($id);
67
        }
68
69 1
        if ($lifetime > 30 * 24 * 3600) {
70
            $lifetime = time() + $lifetime;
71
        }
72
73 1
        return $this->memcached->setMulti($keysAndValues, $lifetime);
74
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 70
    protected function doContains($id)
80
    {
81 70
        $this->memcached->get($id);
82
83 70
        return $this->memcached->getResultCode() === Memcached::RES_SUCCESS;
84
    }
85
86
    /**
87
     * {@inheritdoc}
88
     */
89 74
    protected function doSave($id, $data, $lifeTime = 0)
90
    {
91 74
        $this->validateCacheId($id);
92
93 71
        if ($lifeTime > 30 * 24 * 3600) {
94 1
            $lifeTime = time() + $lifeTime;
95
        }
96
97 71
        return $this->memcached->set($id, $data, (int) $lifeTime);
98
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 1
    protected function doDeleteMultiple(array $keys)
104
    {
105 1
        return $this->memcached->deleteMulti($keys)
106 1
            || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112 41
    protected function doDelete($id)
113
    {
114 41
        return $this->memcached->delete($id)
115 41
            || $this->memcached->getResultCode() === Memcached::RES_NOTFOUND;
116
    }
117
118
    /**
119
     * {@inheritdoc}
120
     */
121 2
    protected function doFlush()
122
    {
123 2
        return $this->memcached->flush();
124
    }
125
126
    /**
127
     * {@inheritdoc}
128
     */
129 1
    protected function doGetStats()
130
    {
131 1
        $stats   = $this->memcached->getStats();
132 1
        $servers = $this->memcached->getServerList();
133 1
        $key     = $servers[0]['host'] . ':' . $servers[0]['port'];
134 1
        $stats   = $stats[$key];
135
136
        return [
137 1
            Cache::STATS_HITS   => $stats['get_hits'],
138 1
            Cache::STATS_MISSES => $stats['get_misses'],
139 1
            Cache::STATS_UPTIME => $stats['uptime'],
140 1
            Cache::STATS_MEMORY_USAGE     => $stats['bytes'],
141 1
            Cache::STATS_MEMORY_AVAILABLE => $stats['limit_maxbytes'],
142
        ];
143
    }
144
145
    /**
146
     * Validate the cache id
147
     *
148
     * @see https://github.com/memcached/memcached/blob/1.5.12/doc/protocol.txt#L41-L49
149
     *
150
     * @param string $id
151
     *
152
     * @return void
153
     *
154
     * @throws InvalidCacheId
155
     */
156 77
    private function validateCacheId($id)
157
    {
158 77
        if (strlen($id) > self::CACHE_ID_MAX_LENGTH) {
159 2
            throw InvalidCacheId::exceedsMaxLength($id, self::CACHE_ID_MAX_LENGTH);
160
        }
161
162 76
        if (strpos($id, ' ') !== false) {
163 2
            throw InvalidCacheId::containsUnauthorizedCharacter($id, ' ');
164
        }
165
166 75
        if (preg_match('/[\t\r\n]/', $id) === 1) {
167 2
            throw InvalidCacheId::containsControlCharacter($id);
168
        }
169 74
    }
170
}
171