Completed
Push — master ( 79d061...7993bb )
by Marco
06:18
created

Memcached::getMultiple()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 5.005

Importance

Changes 0
Metric Value
dl 0
loc 30
ccs 16
cts 17
cp 0.9412
rs 8.439
c 0
b 0
f 0
cc 5
eloc 17
nc 6
nop 2
crap 5.005
1
<?php namespace Comodojo\Cache\Drivers;
2
3
use \Comodojo\Cache\Traits\InstanceTrait;
4
use \Comodojo\Foundation\Utils\UniqueId;
5
use \Memcached as MemcachedInstance;
6
use \Exception;
7
8
/**
9
 * memcached provider
10
 *
11
 * @package     Comodojo Spare Parts
12
 * @author      Marco Giovinazzi <[email protected]>
13
 * @license     MIT
14
 *
15
 * LICENSE:
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 */
25
26
class Memcached extends AbstractDriver {
27
28
    use InstanceTrait;
29
30
    const DRIVER_NAME = "memcached";
31
32 86
    public function __construct(array $configuration) {
33
34 86
        if ( class_exists('Memcached') === false ) throw new Exception("ext-memcached not available");
35
36 86
        $instance = new MemcachedInstance($configuration['persistent_id']);
37
38 86
        $instance->addServer(
39 86
            $configuration['server'],
40 86
            $configuration['port'],
41 86
            $configuration['weight']
42 86
        );
43
44 86
        if ( !empty($configuration['username']) && !empty($configuration['password']) ) {
45
            $instance->setOption(MemcachedInstance::OPT_BINARY_PROTOCOL, true);
46
            $instance->setSaslAuthData($configuration['username'], $configuration['password']);
47
        }
48
49 86
        $this->setInstance($instance);
50
51 86
    }
52
53 86
    public function test() {
54
55 86
        return sizeof($this->getInstance()->getServerList()) > 0 && $this->ping();
56
57
    }
58
59 86
    public function ping() {
60
61
        // try to read a fake value from cache and check it's return code
62 86
        $instance = $this->getInstance();
63 86
        $instance->get('cache-internals');
64 86
        $code = $instance->getResultCode();
65
66
        // check if code represents a failure
67
        // $code != [MEMCACHED_SUCCESS, MEMCACHED_NOTFOUND]
0 ignored issues
show
Unused Code Comprehensibility introduced by
42% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
68 86
        return in_array($code, [0, 16]);
69
70
    }
71
72 34
    public function get($key, $namespace) {
73
74 34
        $scope = $this->getNamespaceKey($namespace);
75
76 34
        if ( $scope === false ) return null;
77
78 26
        $shadowName = "$scope-$key";
79
80 26
        $instance = $this->getInstance();
81
82 26
        $item = $instance->get($shadowName);
83
84 26
        return $instance->getResultCode() == MemcachedInstance::RES_NOTFOUND ? null : $item;
85
86
    }
87
88 52
    public function set($key, $namespace, $value, $ttl = null) {
89
90 52
        if ( $ttl == null ) $ttl = 0;
91
92 52
        $scope = $this->getNamespaceKey($namespace);
93
94 52
        if ( $scope === false ) $scope = $this->setNamespaceKey($namespace);
95
96 52
        if ( $scope === false ) return false;
97
98 52
        $shadowName = "$scope-$key";
99
100 52
        return $this->getInstance()->set($shadowName, $value, $ttl);
101
102
    }
103
104 8 View Code Duplication
    public function delete($key, $namespace) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
105
106 8
        $scope = $this->getNamespaceKey($namespace);
107
108 8
        if ( $scope === false ) return false;
109
110 8
        $shadowName = "$scope-$key";
111
112 8
        return $this->getInstance()->delete($shadowName);
113
114
    }
115
116 22
    public function clear($namespace = null) {
117
118 22 View Code Duplication
        if ( $namespace == null ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
120 18
            return $this->getInstance()->flush();
121
122
        } else {
123
124 4
            $scope = $this->getNamespaceKey($namespace);
125
126 4
            if ( $scope === false ) return false;
127
128 4
            return $this->getInstance()->delete($namespace);
129
130
        }
131
132
    }
133
134 2
    public function getMultiple(array $keys, $namespace) {
135
136 2
        if ( empty($keys) ) return [];
137
138 2
        $keypad = array_combine($keys, array_fill(0, count($keys), null));
139
140 2
        $scope = $this->getNamespaceKey($namespace);
141
142 2
        if ( $scope === false ) return $keypad;
143
144
        $keyscope = array_map(function($key) use($scope) {
145 2
            return "$scope-$key";
146 2
        }, $keys);
147
148 2
        if ( version_compare(phpversion(), '7.0.0', '<') ) {
149 2
            $data = $this->getInstance()->getMulti($keyscope, $null = null, MemcachedInstance::GET_PRESERVE_ORDER);
150 2
        } else {
151
            $data = $this->getInstance()->getMulti($keyscope, MemcachedInstance::GET_PRESERVE_ORDER);
152
        }
153
154 2
        $return = [];
155
156 2
        foreach ( $data as $scoped_key => $value ) {
157 2
            $key = substr($scoped_key, strlen("$scope-"));
158 2
            $return[$key] = $value;
159 2
        }
160
161 2
        return array_replace($keypad, $return);
162
163
    }
164
165 2
    public function setMultiple(array $key_values, $namespace, $ttl = null) {
166
167 2
        if ( $ttl == null ) $ttl = 0;
168
169 2
        $scope = $this->getNamespaceKey($namespace);
170
171 2
        if ( $scope === false ) $scope = $this->setNamespaceKey($namespace);
172
173 2
        if ( $scope === false ) return false;
174
175 2
        $shadowNames = [];
176
177 2
        foreach ( $key_values as $key => $value ) {
178 2
            $shadowNames["$scope-$key"] = $value;
179 2
        }
180
181 2
        return $this->getInstance()->setMulti($shadowNames, $ttl);
182
183
    }
184
185 4
    public function deleteMultiple(array $keys, $namespace) {
186
187 4
        $scope = $this->getNamespaceKey($namespace);
188
189 4
        if ( $scope === false ) return false;
190
191 4
        $shadowNames = array_map(function($key) use($scope) {
192 4
            return "$scope-$key";
193 4
        }, $keys);
194
195 4
        $delete = $this->getInstance()->deleteMulti($shadowNames);
196
197 4
        return count(array_diff(array_unique($delete), [true])) === 0;
198
199
    }
200
201 5
    public function has($key, $namespace) {
202
203 5
        return $this->get($key, $namespace) === null ? false : true;
204
205
    }
206
207 4
    public function stats() {
208
209 4
        return $this->getInstance()->getStats();
210
211
    }
212
213
    /**
214
     * Set namespace key
215
     *
216
     * @return  mixed
217
     */
218 9 View Code Duplication
    private function setNamespaceKey($namespace) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
219
220 9
        $uId = UniqueId::generate(64);
221
222 9
        return $this->getInstance()->set($namespace, $uId, 0) === false ? false : $uId;
223
224
    }
225
226
    /**
227
     * Get namespace key
228
     *
229
     * @return  string
230
     */
231 63
    private function getNamespaceKey($namespace) {
232
233 63
        return $this->getInstance()->get($namespace);
234
235
    }
236
237
}
238