1
|
|
|
<?php |
2
|
|
|
/* |
3
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
4
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
5
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
6
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
7
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
8
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
9
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
10
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
11
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
12
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
13
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
14
|
|
|
* |
15
|
|
|
* This software consists of voluntary contributions made by many individuals |
16
|
|
|
* and is licensed under the MIT license. For more information, see |
17
|
|
|
* <http://www.doctrine-project.org>. |
18
|
|
|
*/ |
19
|
|
|
|
20
|
|
|
declare(strict_types=1); |
21
|
|
|
|
22
|
|
|
namespace Doctrine\Common\Cache; |
23
|
|
|
|
24
|
|
|
use Couchbase\Bucket; |
25
|
|
|
use Couchbase\Document; |
26
|
|
|
use Couchbase\Exception; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Couchbase ^2.3.0 cache provider. |
30
|
|
|
*/ |
31
|
|
|
final class CouchbaseBucketCache extends CacheProvider |
32
|
|
|
{ |
33
|
|
|
private const MINIMUM_VERSION = '2.3.0'; |
34
|
|
|
|
35
|
|
|
private const KEY_NOT_FOUND = 13; |
36
|
|
|
|
37
|
|
|
private const MAX_KEY_LENGTH = 250; |
38
|
|
|
|
39
|
|
|
private const THIRTY_DAYS_IN_SECONDS = 2592000; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* @var Bucket |
43
|
|
|
*/ |
44
|
|
|
private $bucket; |
45
|
|
|
|
46
|
|
|
/** |
47
|
|
|
* CouchbaseCache constructor. |
48
|
|
|
* @param Bucket $bucket |
49
|
|
|
*/ |
50
|
78 |
|
public function __construct(Bucket $bucket) |
51
|
|
|
{ |
52
|
78 |
|
if (version_compare(phpversion('couchbase'), self::MINIMUM_VERSION) < 0) { |
53
|
|
|
// Manager is required to flush cache and pull stats. |
54
|
|
|
throw new \RuntimeException(sprintf('ext-couchbase:^%s is required.', self::MINIMUM_VERSION)); |
55
|
|
|
} |
56
|
|
|
|
57
|
78 |
|
$this->bucket = $bucket; |
58
|
78 |
|
} |
59
|
|
|
|
60
|
|
|
/** |
61
|
|
|
* {@inheritdoc} |
62
|
|
|
*/ |
63
|
76 |
|
protected function doFetch($id) |
64
|
|
|
{ |
65
|
76 |
|
$id = $this->normalizeKey($id); |
66
|
|
|
|
67
|
|
|
try { |
68
|
76 |
|
$document = $this->bucket->get($id); |
69
|
66 |
|
} catch (Exception $e) { |
|
|
|
|
70
|
66 |
|
return false; |
71
|
|
|
} |
72
|
|
|
|
73
|
73 |
|
if ($document instanceof Document && $document->value !== false) { |
|
|
|
|
74
|
73 |
|
return unserialize($document->value); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
return false; |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* {@inheritdoc} |
82
|
|
|
*/ |
83
|
73 |
|
protected function doContains($id) |
84
|
|
|
{ |
85
|
73 |
|
$id = $this->normalizeKey($id); |
86
|
|
|
|
87
|
|
|
try { |
88
|
73 |
|
$document = $this->bucket->get($id); |
89
|
53 |
|
} catch (Exception $e) { |
|
|
|
|
90
|
53 |
|
return false; |
91
|
|
|
} |
92
|
|
|
|
93
|
69 |
|
if ($document instanceof Document) { |
|
|
|
|
94
|
69 |
|
return ! $document->error; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return false; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* {@inheritdoc} |
102
|
|
|
*/ |
103
|
74 |
|
protected function doSave($id, $data, $lifeTime = 0) |
104
|
|
|
{ |
105
|
74 |
|
$id = $this->normalizeKey($id); |
106
|
|
|
|
107
|
74 |
|
$lifeTime = $this->normalizeExpiry($lifeTime); |
108
|
|
|
|
109
|
|
|
try { |
110
|
74 |
|
$encoded = serialize($data); |
111
|
|
|
|
112
|
74 |
|
$document = $this->bucket->upsert($id, $encoded, [ |
113
|
74 |
|
'expiry' => (int) $lifeTime, |
114
|
|
|
]); |
115
|
|
|
} catch (Exception $e) { |
|
|
|
|
116
|
|
|
return false; |
117
|
|
|
} |
118
|
|
|
|
119
|
74 |
|
if ($document instanceof Document) { |
|
|
|
|
120
|
74 |
|
return ! $document->error; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
return false; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* {@inheritdoc} |
128
|
|
|
*/ |
129
|
45 |
|
protected function doDelete($id) |
130
|
|
|
{ |
131
|
45 |
|
$id = $this->normalizeKey($id); |
132
|
|
|
|
133
|
|
|
try { |
134
|
45 |
|
$document = $this->bucket->remove($id); |
135
|
3 |
|
} catch (Exception $e) { |
|
|
|
|
136
|
3 |
|
return $e->getCode() === self::KEY_NOT_FOUND; |
137
|
|
|
} |
138
|
|
|
|
139
|
43 |
|
if ($document instanceof Document) { |
|
|
|
|
140
|
43 |
|
return ! $document->error; |
141
|
|
|
} |
142
|
|
|
|
143
|
|
|
return false; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* {@inheritdoc} |
148
|
|
|
*/ |
149
|
2 |
|
protected function doFlush() |
150
|
|
|
{ |
151
|
2 |
|
$manager = $this->bucket->manager(); |
152
|
|
|
|
153
|
|
|
// Flush does not return with success or failure, and must be enabled per bucket on the server. |
154
|
|
|
// Store a marker item so that we will know if it was successful. |
155
|
2 |
|
$this->doSave(__METHOD__, true, 60); |
|
|
|
|
156
|
|
|
|
157
|
2 |
|
$manager->flush(); |
158
|
|
|
|
159
|
2 |
|
if ($this->doContains(__METHOD__)) { |
160
|
|
|
$this->doDelete(__METHOD__); |
161
|
|
|
|
162
|
|
|
return false; |
163
|
|
|
} |
164
|
|
|
|
165
|
2 |
|
return true; |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
/** |
169
|
|
|
* {@inheritdoc} |
170
|
|
|
*/ |
171
|
1 |
|
protected function doGetStats() |
172
|
|
|
{ |
173
|
1 |
|
$manager = $this->bucket->manager(); |
174
|
1 |
|
$stats = $manager->info(); |
175
|
1 |
|
$nodes = $stats['nodes']; |
176
|
1 |
|
$node = $nodes[0]; |
177
|
1 |
|
$interestingStats = $node['interestingStats']; |
178
|
|
|
|
179
|
|
|
return [ |
180
|
1 |
|
Cache::STATS_HITS => $interestingStats['get_hits'], |
181
|
1 |
|
Cache::STATS_MISSES => $interestingStats['cmd_get'] - $interestingStats['get_hits'], |
182
|
1 |
|
Cache::STATS_UPTIME => $node['uptime'], |
183
|
1 |
|
Cache::STATS_MEMORY_USAGE => $interestingStats['mem_used'], |
184
|
1 |
|
Cache::STATS_MEMORY_AVAILABLE => $node['memoryFree'], |
185
|
|
|
]; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
/** |
189
|
|
|
* @param string $id |
190
|
|
|
* @return string |
191
|
|
|
*/ |
192
|
76 |
|
private function normalizeKey(string $id) : string |
193
|
|
|
{ |
194
|
76 |
|
$normalized = substr($id, 0, self::MAX_KEY_LENGTH); |
195
|
|
|
|
196
|
76 |
|
if ($normalized === false) { |
197
|
|
|
return $id; |
198
|
|
|
} |
199
|
|
|
|
200
|
76 |
|
return $normalized; |
201
|
|
|
} |
202
|
|
|
|
203
|
|
|
/** |
204
|
|
|
* Expiry treated as a unix timestamp instead of an offset if expiry is greater than 30 days. |
205
|
|
|
* @src https://developer.couchbase.com/documentation/server/4.1/developer-guide/expiry.html |
206
|
|
|
* |
207
|
|
|
* @param int $expiry |
208
|
|
|
* @return int |
209
|
|
|
*/ |
210
|
74 |
|
private function normalizeExpiry(int $expiry) : int |
211
|
|
|
{ |
212
|
74 |
|
if ($expiry > self::THIRTY_DAYS_IN_SECONDS) { |
213
|
1 |
|
return time() + $expiry; |
214
|
|
|
} |
215
|
|
|
|
216
|
73 |
|
return $expiry; |
217
|
|
|
} |
218
|
|
|
} |
219
|
|
|
|
Scrutinizer analyzes your
composer.json
/composer.lock
file if available to determine the classes, and functions that are defined by your dependencies.It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.