Completed
Pull Request — master (#7)
by Thomas
13:03
created

Memcache::delete()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 30
Code Lines 14

Duplication

Lines 16
Ratio 53.33 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 16
loc 30
rs 8.439
cc 6
eloc 14
nc 9
nop 1
1
<?php
2
/**
3
 *
4
 * This file is part of the Apix Project.
5
 *
6
 * (c) Franck Cassedanne <franck at ouarz.net>
7
 *
8
 * @license     http://opensource.org/licenses/BSD-3-Clause  New BSD License
9
 *
10
 */
11
12
namespace Apix\Cache;
13
14
/**
15
 * Memcache cache wrapper.
16
 *
17
 * @author Franck Cassedanne <franck at ouarz.net>
18
 *
19
 */
20
class Memcache extends AbstractCache
21
{
22
    /**
23
     * Holds an injected adapter.
24
     * @var \Memcache
25
     */
26
    protected $adapter = null;
27
28
    /**
29
     * Holds the array of TTLs.
30
     * @var array
31
     */
32
    protected $ttls = array();
33
34
    /**
35
     * Constructor.
36
     *
37
     * @param \Memcache $memcache A Memcache instance.
38
     * @param array     $options  Array of options.
39
     */
40
    public function __construct(\Memcache $memcache, array $options = null)
41
    {
42
        // default options
43
        $this->options['prefix_key'] = 'key_';  // prefix cache keys
44
        $this->options['prefix_tag'] = 'tag_';  // prefix cache tags
45
        $this->options['prefix_idx'] = 'idx_';  // prefix cache indexes
46
        $this->options['prefix_nsp'] = 'nsp_';  // prefix cache namespaces
47
48
        $this->options['serializer'] = 'php';   // none, php, json, igBinary.
49
50
        parent::__construct($memcache, $options);
51
52
        if ($this->options['tag_enable']) {
53
            $this->setSerializer($this->options['serializer']);
54
        }
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     */
60
    public function loadKey($key)
61
    {
62
        return $this->get($this->mapKey($key));
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function loadTag($tag)
69
    {
70
        return $this->getIndex($this->mapTag($tag))->load();
71
    }
72
73
    /**
74
     * {@inheritdoc}
75
     */
76 View Code Duplication
    public function save($data, $key, array $tags = null, $ttl = null)
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...
77
    {
78
        $ttl = $this->sanitiseTtl($ttl);
79
80
        $mKey = $this->mapKey($key);
81
82
        $data = array('data' => $data, 'ttl' => $ttl);
83
        $this->ttls[$mKey] = $ttl;
84
85
        // add the item
86
        $success = $this->adapter->set($mKey, $data, $ttl);
87
88
        if ($success && $this->options['tag_enable'] && !empty($tags)) {
89
90
            // add all the tags to the index key.
91
            $this->getIndex($this->mapIdx($key))->add($tags);
92
93
            // append the key to each tag.
94
            foreach ($tags as $tag) {
95
                $this->getIndex($this->mapTag($tag))->add($mKey);
96
            }
97
        }
98
99
        return $success;
100
    }
101
102
    /**
103
     * {@inheritdoc}
104
     */
105
    public function clean(array $tags)
106
    {
107
        $items = array();
108
109 View Code Duplication
        foreach ($tags as $tag) {
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...
110
            $keys = $this->loadTag($tag);
111
            if (null !== $keys) {
112
                foreach ($keys as $key) {
113
                    $items[] = $key;
114
                }
115
            }
116
117
            // add the tag to deletion
118
            $items[] = $this->mapTag($tag);
119
        }
120
121
        $success = true;
122
123
        foreach ($items as $item) {
124
            $success = $this->adapter->delete($item) && $success;
125
        }
126
127
        return $success;
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133
    public function delete($key)
134
    {
135
        $_key = $this->mapKey($key);
136
        $items = array($_key);
137
138 View Code Duplication
        if ($this->options['tag_enable']) {
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...
139
            $idx_key = $this->mapIdx($key);
140
141
            // load the tags from the index key
142
            $tags = $this->getIndex($idx_key)->load();
143
144
            if (is_array($tags)) {
145
                // mark the key as deleted in the tags.
146
                foreach ($tags as $tag) {
147
                    $this->getIndex($this->mapTag($tag))->remove($_key);
148
                }
149
150
                // delete that index key
151
                $items[] = $idx_key;
152
            }
153
        }
154
155
        $success = true;
156
157
        foreach ($items as $item) {
158
            $success = $this->adapter->delete($item) && $success;
159
        }
160
161
        return $success;
162
    }
163
164
    /**
165
     * {@inheritdoc}
166
     */
167
    public function flush($all = false)
168
    {
169
        return $this->adapter->flush();
170
    }
171
172
    /**
173
     * Retrieves the cache item for the given id.
174
     *
175
     * @param  string     $id        The cache id to retrieve.
176
     * @return mixed|null Returns the cached data or null.
177
     */
178
    public function get($id)
179
    {
180
        $data = $this->adapter->get($id);
181
182
        if (false !== $data) {
183
            $this->ttls[$id] = isset($data['ttl']) ? $data['ttl'] : 0;
184
185
            return isset($data['data']) ? $data['data'] : $data;
186
        }
187
188
        return null;
189
    }
190
191
    /**
192
     * Returns the ttl sanitased for this cache adapter.
193
     *
194
     * The number of seconds may not exceed 60*60*24*30 = 2,592,000 (30 days).
195
     * @see http://php.net/manual/en/Memcache.expiration.php
196
     *
197
     * @param  integer|null $ttl The time-to-live in seconds.
198
     * @return int
199
     */
200
    public function sanitiseTtl($ttl)
201
    {
202
        return $ttl > 2592000 ? time() + $ttl : $ttl;
203
    }
204
205
    /**
206
     * Returns the named indexer.
207
     *
208
     * @param  string          $name The name of the index.
209
     * @return Indexer\Adapter
210
     */
211
    public function getIndex($name)
212
    {
213
        return new Indexer\MemcacheIndexer($name, $this);
214
    }
215
216
    /**
217
     * Returns a prefixed and sanitased cache id.
218
     *
219
     * @param  string $key The base key to prefix.
220
     * @return string
221
     */
222
    public function mapIdx($key)
223
    {
224
        return $this->sanitise($this->options['prefix_idx'] . $key);
225
    }
226
227
    /**
228
     * Increments the value of the given key.
229
     *
230
     * @param  string  $key The key to increment.
231
     *
232
     * @return int|bool Returns the new item's value on success or FALSE on failure.
233
     */
234 View Code Duplication
    public function increment($key)
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...
235
    {
236
        $counter = $this->adapter->get($key);
237
238
        if (false === $counter) {
239
            $counter = 1;
240
            $this->adapter->set($key, $counter);
241
        } else {
242
            $counter = $this->adapter->increment($key);
243
        }
244
245
        return $counter;
246
    }
247
248
    /**
249
     * {@inheritdoc}
250
     *
251
     * The number of seconds may not exceed 60*60*24*30 = 2,592,000 (30 days).
252
     */
253
    public function getTtl($key)
254
    {
255
        $mKey = $this->mapKey($key);
256
257
        if (!isset($this->ttls[$mKey])) {
258
            $data = $this->adapter->get($mKey);
259
260
            $this->ttls[$mKey] = (isset($data['ttl']) ? $data['ttl'] : 0);
261
        }
262
263
        return $this->ttls[$mKey];
264
    }
265
266
    /**
267
     * Gets the injected adapter.
268
     *
269
     * @return \Memcache
270
     */
271
    public function getAdapter()
272
    {
273
        return $this->adapter;
274
    }
275
}
276