MongoDB::get()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3.3332

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
nc 3
nop 2
dl 0
loc 11
ccs 4
cts 6
cp 0.6667
crap 3.3332
rs 10
c 1
b 0
f 0
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\Packer\PackerInterface;
20
use Desarrolla2\Cache\Packer\MongoDBBinaryPacker;
21
use Desarrolla2\Cache\Option\InitializeTrait as InitializeOption;
22
use MongoDB\Collection;
23
use MongoDB\BSON\UTCDatetime as BSONUTCDateTime;
24
use MongoDB\Driver\Exception\RuntimeException as MongoDBRuntimeException;
25
26
/**
27
 * MongoDB cache implementation
28
 */
29
class MongoDB extends AbstractCache
30
{
31
    use InitializeOption;
32
33
    /**
34
     * @var Collection
35
     */
36
    protected $collection;
37
38
    /**
39
     * Class constructor
40
     *
41
     * @param Collection $collection
42
     */
43 198
    public function __construct(Collection $collection)
44
    {
45 198
        $this->collection = $collection;
46
    }
47
48
    /**
49
     * Initialize the DB collection.
50
     * Set TTL index.
51
     */
52
    protected function initialize(): void
53
    {
54
        $this->collection->createIndex(['ttl' => 1], ['expireAfterSeconds' => 0]);
55
    }
56
57
58
    /**
59
     * Create the default packer for this cache implementation.
60
     *
61
     * @return PackerInterface
62
     */
63 61
    protected static function createDefaultPacker(): PackerInterface
64
    {
65 61
        return new MongoDBBinaryPacker();
66
    }
67
68
    /**
69
     * Get filter for key and ttl.
70
     *
71
     * @param string|iterable $key
72
     * @return array
73
     */
74 45
    protected function filter($key)
75
    {
76 45
        if (is_array($key)) {
77 11
            $key = ['$in' => $key];
78
        }
79
80
        return [
81 45
            '_id' => $key,
82
            '$or' => [
83 45
                ['ttl' => ['$gt' => new BSONUTCDateTime($this->currentTimestamp() * 1000)]],
84
                ['ttl' => null]
85
            ]
86
        ];
87
    }
88
89
    /**
90
     * {@inheritdoc }
91
     */
92 52
    public function get($key, $default = null)
93
    {
94 52
        $filter = $this->filter($this->keyToId($key));
95
96
        try {
97 34
            $data = $this->collection->findOne($filter);
98
        } catch (MongoDBRuntimeException $e) {
99
            return $default;
100
        }
101
102 34
        return isset($data) ? $this->unpack($data['value']) : $default;
103
    }
104
105
    /**
106
     * {@inheritdoc}
107
     */
108 30
    public function getMultiple($keys, $default = null)
109
    {
110 30
        $idKeyPairs = $this->mapKeysToIds($keys);
111
112 11
        if (empty($idKeyPairs)) {
113
            return [];
114
        }
115
116 11
        $filter = $this->filter(array_keys($idKeyPairs));
117 11
        $items = array_fill_keys(array_values($idKeyPairs), $default);
118
119
        try {
120 11
            $rows = $this->collection->find($filter);
121
        } catch (MongoDBRuntimeException $e) {
122
            return $items;
123
        }
124
125 11
        foreach ($rows as $row) {
126 11
            $id = $row['_id'];
127 11
            $key = $idKeyPairs[$id];
128
129 11
            $items[$key] = $this->unpack($row['value']);
130
        }
131
132 11
        return $items;
133
    }
134
135
    /**
136
     * {@inheritdoc }
137
     */
138 22
    public function has($key)
139
    {
140 22
        $filter = $this->filter($this->keyToId($key));
141
142
        try {
143 4
            $count = $this->collection->count($filter);
0 ignored issues
show
Deprecated Code introduced by
The function MongoDB\Collection::count() has been deprecated: 1.4 ( Ignorable by Annotation )

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

143
            $count = /** @scrutinizer ignore-deprecated */ $this->collection->count($filter);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
144
        } catch (MongoDBRuntimeException $e) {
145
            return false;
146
        }
147
148 4
        return $count  > 0;
149
    }
150
151
    /**
152
     * {@inheritdoc }
153
     */
154 58
    public function set($key, $value, $ttl = null)
155
    {
156 58
        $id = $this->keyToId($key);
157
158
        $item = [
159
            '_id' => $id,
160 40
            'ttl' => $this->getTtlBSON($ttl),
161 30
            'value' => $this->pack($value)
162
        ];
163
164
        try {
165 30
            $this->collection->replaceOne(['_id' => $id], $item, ['upsert' => true]);
166
        } catch (MongoDBRuntimeException $e) {
167
            return false;
168
        }
169
170 30
        return true;
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 42
    public function setMultiple($values, $ttl = null)
177
    {
178 42
        $this->assertIterable($values, 'values not iterable');
179
180 41
        if (empty($values)) {
181
            return true;
182
        }
183
184 41
        $bsonTtl = $this->getTtlBSON($ttl);
185 31
        $items = [];
186
187 31
        foreach ($values as $key => $value) {
188 31
            $id = $this->keyToId(is_int($key) ? (string)$key : $key);
189
190 31
            $items[] = [
191
                'replaceOne' => [
192 31
                    ['_id' => $id],
193
                    [
194 31
                        '_id' => $id,
195
                        'ttl' => $bsonTtl,
196 31
                        'value' => $this->pack($value)
197
                    ],
198
                    [ 'upsert' => true ]
199
                ]
200
            ];
201
        }
202
203
        try {
204 14
            $this->collection->bulkWrite($items);
205
        } catch (MongoDBRuntimeException $e) {
206
            return false;
207
        }
208
209 14
        return true;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 20
    public function delete($key)
216
    {
217 20
        $id = $this->keyToId($key);
218
219
        try {
220 2
            $this->collection->deleteOne(['_id' => $id]);
221
        } catch (MongoDBRuntimeException $e) {
222
            return false;
223
        }
224
225 2
        return true;
226
    }
227
228
    /**
229
     * {@inheritdoc}
230
     */
231 21
    public function deleteMultiple($keys)
232
    {
233 21
        $idKeyPairs = $this->mapKeysToIds($keys);
234
235
        try {
236 2
            if (!empty($idKeyPairs)) {
237 2
                $this->collection->deleteMany(['_id' => ['$in' => array_keys($idKeyPairs)]]);
238
            }
239
        } catch (MongoDBRuntimeException $e) {
240
            return false;
241
        }
242
243 2
        return true;
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249 198
    public function clear()
250
    {
251
        try {
252 198
            $this->collection->drop();
253
        } catch (MongoDBRuntimeException $e) {
254
            return false;
255
        }
256
257 198
        $this->requireInitialization();
258
259 198
        return true;
260
    }
261
262
263
    /**
264
     * Get TTL as Date type BSON object
265
     *
266
     * @param null|int|\DateInterval $ttl
267
     * @return BSONUTCDatetime|null
268
     */
269 81
    protected function getTtlBSON($ttl): ?BSONUTCDatetime
270
    {
271 81
        return isset($ttl) ? new BSONUTCDateTime($this->ttlToTimestamp($ttl) * 1000) : null;
272
    }
273
}
274