1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* |
4
|
|
|
* This file is part of phpFastCache. |
5
|
|
|
* |
6
|
|
|
* @license MIT License (MIT) |
7
|
|
|
* |
8
|
|
|
* For full copyright and license information, please see the docs/CREDITS.txt file. |
9
|
|
|
* |
10
|
|
|
* @author Khoa Bui (khoaofgod) <[email protected]> http://www.phpfastcache.com |
11
|
|
|
* @author Georges.L (Geolim4) <[email protected]> |
12
|
|
|
* |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace phpFastCache\Drivers\Couchdb; |
16
|
|
|
|
17
|
|
|
use Doctrine\CouchDB\CouchDBClient as CouchdbClient; |
18
|
|
|
use Doctrine\CouchDB\CouchDBException; |
19
|
|
|
use phpFastCache\Core\Pool\DriverBaseTrait; |
20
|
|
|
use phpFastCache\Core\Pool\ExtendedCacheItemPoolInterface; |
21
|
|
|
use phpFastCache\Entities\DriverStatistic; |
22
|
|
|
use phpFastCache\Exceptions\phpFastCacheDriverCheckException; |
23
|
|
|
use phpFastCache\Exceptions\phpFastCacheDriverException; |
24
|
|
|
use phpFastCache\Exceptions\phpFastCacheInvalidArgumentException; |
25
|
|
|
use phpFastCache\Exceptions\phpFastCacheLogicException; |
26
|
|
|
use Psr\Cache\CacheItemInterface; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Class Driver |
30
|
|
|
* @package phpFastCache\Drivers |
31
|
|
|
* @property CouchdbClient $instance Instance of driver service |
32
|
|
|
*/ |
33
|
|
|
class Driver implements ExtendedCacheItemPoolInterface |
34
|
|
|
{ |
35
|
|
|
use DriverBaseTrait; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Driver constructor. |
39
|
|
|
* @param array $config |
40
|
|
|
* @throws phpFastCacheDriverException |
41
|
|
|
*/ |
42
|
|
View Code Duplication |
public function __construct(array $config = []) |
43
|
|
|
{ |
44
|
|
|
$this->setup($config); |
45
|
|
|
|
46
|
|
|
if (!$this->driverCheck()) { |
47
|
|
|
throw new phpFastCacheDriverCheckException(sprintf(self::DRIVER_CHECK_FAILURE, $this->getDriverName())); |
48
|
|
|
} else { |
49
|
|
|
$this->driverConnect(); |
50
|
|
|
} |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @return bool |
55
|
|
|
*/ |
56
|
|
|
public function driverCheck() |
57
|
|
|
{ |
58
|
|
|
return class_exists('Doctrine\CouchDB\CouchDBClient'); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
63
|
|
|
* @return mixed |
64
|
|
|
* @throws phpFastCacheDriverException |
65
|
|
|
* @throws phpFastCacheInvalidArgumentException |
66
|
|
|
*/ |
67
|
|
|
protected function driverWrite(CacheItemInterface $item) |
68
|
|
|
{ |
69
|
|
|
/** |
70
|
|
|
* Check for Cross-Driver type confusion |
71
|
|
|
*/ |
72
|
|
|
if ($item instanceof Item) { |
73
|
|
|
try{ |
74
|
|
|
$this->instance->putDocument(['data' => $this->encode($this->driverPreWrap($item))], $item->getEncodedKey(), $this->getLatestDocumentRevision($item->getEncodedKey())); |
75
|
|
|
}catch (CouchDBException $e){ |
|
|
|
|
76
|
|
|
throw new phpFastCacheDriverException('Got error while trying to upsert a document: ' . $e->getMessage(), null, $e); |
77
|
|
|
} |
78
|
|
|
return true; |
79
|
|
|
} else { |
80
|
|
|
throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected'); |
81
|
|
|
} |
82
|
|
|
} |
83
|
|
|
|
84
|
|
|
/** |
85
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
86
|
|
|
* @return mixed |
87
|
|
|
* @throws phpFastCacheDriverException |
88
|
|
|
*/ |
89
|
|
|
protected function driverRead(CacheItemInterface $item) |
90
|
|
|
{ |
91
|
|
|
try{ |
92
|
|
|
$response = $this->instance->findDocument($item->getEncodedKey()); |
93
|
|
|
}catch (CouchDBException $e){ |
|
|
|
|
94
|
|
|
throw new phpFastCacheDriverException('Got error while trying to get a document: ' . $e->getMessage(), null, $e); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
if($response->status === 404 || empty($response->body['data'])){ |
98
|
|
|
return null; |
99
|
|
|
}else if($response->status === 200){ |
100
|
|
|
return $this->decode($response->body['data']); |
101
|
|
|
}else{ |
102
|
|
|
throw new phpFastCacheDriverException('Got unexpected HTTP status: ' . $response->status); |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @param \Psr\Cache\CacheItemInterface $item |
108
|
|
|
* @return bool |
109
|
|
|
* @throws phpFastCacheDriverException |
110
|
|
|
* @throws phpFastCacheInvalidArgumentException |
111
|
|
|
*/ |
112
|
|
|
protected function driverDelete(CacheItemInterface $item) |
113
|
|
|
{ |
114
|
|
|
/** |
115
|
|
|
* Check for Cross-Driver type confusion |
116
|
|
|
*/ |
117
|
|
|
if ($item instanceof Item) { |
118
|
|
|
try{ |
119
|
|
|
$this->instance->deleteDocument($item->getEncodedKey(), $this->getLatestDocumentRevision($item->getEncodedKey())); |
120
|
|
|
}catch (CouchDBException $e){ |
|
|
|
|
121
|
|
|
throw new phpFastCacheDriverException('Got error while trying to delete a document: ' . $e->getMessage(), null, $e); |
122
|
|
|
} |
123
|
|
|
return true; |
124
|
|
|
} else { |
125
|
|
|
throw new phpFastCacheInvalidArgumentException('Cross-Driver type confusion detected'); |
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @return bool |
131
|
|
|
* @throws phpFastCacheDriverException |
132
|
|
|
*/ |
133
|
|
|
protected function driverClear() |
134
|
|
|
{ |
135
|
|
|
try{ |
136
|
|
|
$this->instance->deleteDatabase($this->getDatabaseName()); |
137
|
|
|
$this->createDatabase(); |
138
|
|
|
}catch (CouchDBException $e){ |
|
|
|
|
139
|
|
|
throw new phpFastCacheDriverException('Got error while trying to delete and recreate the database: ' . $e->getMessage(), null, $e); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
|
143
|
|
|
return true; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @return bool |
148
|
|
|
* @throws phpFastCacheLogicException |
149
|
|
|
*/ |
150
|
|
|
protected function driverConnect() |
151
|
|
|
{ |
152
|
|
|
if ($this->instance instanceof CouchdbClient) { |
|
|
|
|
153
|
|
|
throw new phpFastCacheLogicException('Already connected to Couchdb server'); |
154
|
|
|
} else { |
155
|
|
|
$host = isset($this->config[ 'host' ]) ? $this->config[ 'host' ] : '127.0.0.1'; |
156
|
|
|
$ssl = isset($this->config[ 'ssl' ]) ? $this->config[ 'ssl' ] : false; |
157
|
|
|
$port = isset($this->config[ 'port' ]) ? $this->config[ 'port' ] : 5984; |
158
|
|
|
$path = isset($this->config[ 'path' ]) ? $this->config[ 'path' ] : '/'; |
159
|
|
|
$username = isset($this->config[ 'username' ]) ? $this->config[ 'username' ] : ''; |
160
|
|
|
$password = isset($this->config[ 'password' ]) ? $this->config[ 'password' ] : ''; |
161
|
|
|
$timeout = isset($this->config[ 'timeout' ]) ? $this->config[ 'timeout' ] : 10; |
162
|
|
|
|
163
|
|
|
$url = ($ssl ? 'https://' : 'http://'); |
164
|
|
|
if($username) |
165
|
|
|
{ |
166
|
|
|
$url .= "{$username}"; |
167
|
|
|
if($password) |
168
|
|
|
{ |
169
|
|
|
$url .= ":{$password}"; |
170
|
|
|
} |
171
|
|
|
$url .= '@'; |
172
|
|
|
} |
173
|
|
|
$url .= $host; |
174
|
|
|
$url .= ":{$port}"; |
175
|
|
|
$url .= $path; |
176
|
|
|
|
177
|
|
|
$this->instance = CouchDBClient::create([ |
178
|
|
|
'dbname' => $this->getDatabaseName(), |
179
|
|
|
'url' => $url, |
180
|
|
|
'timeout' => $timeout |
181
|
|
|
]); |
182
|
|
|
|
183
|
|
|
$this->createDatabase(); |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
return true; |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* @return string|null |
191
|
|
|
*/ |
192
|
|
|
protected function getLatestDocumentRevision($docId) |
193
|
|
|
{ |
194
|
|
|
$path = '/' . $this->getDatabaseName() . '/' . urlencode($docId); |
195
|
|
|
|
196
|
|
|
$response = $this->instance->getHttpClient()->request( |
197
|
|
|
'GET',// At this moment HEAD requests are not working: https://github.com/doctrine/couchdb-client/issues/72 |
198
|
|
|
$path, |
199
|
|
|
null, |
200
|
|
|
false |
201
|
|
|
); |
202
|
|
|
if(!empty($response->headers['etag'])){ |
203
|
|
|
return trim($response->headers['etag'], " '\"\t\n\r\0\x0B"); |
204
|
|
|
}else{ |
205
|
|
|
return null; |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
/** |
210
|
|
|
* @return string |
211
|
|
|
*/ |
212
|
|
|
protected function getDatabaseName() |
213
|
|
|
{ |
214
|
|
|
return isset($this->config[ 'database' ]) ? $this->config[ 'database' ] : 'phpfastcache'; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
/** |
218
|
|
|
* @return void |
219
|
|
|
*/ |
220
|
|
|
protected function createDatabase() |
221
|
|
|
{ |
222
|
|
|
if(!in_array($this->instance->getDatabase(), $this->instance->getAllDatabases(), true)){ |
223
|
|
|
$this->instance->createDatabase($this->instance->getDatabase()); |
224
|
|
|
} |
225
|
|
|
} |
226
|
|
|
|
227
|
|
|
/******************** |
228
|
|
|
* |
229
|
|
|
* PSR-6 Extended Methods |
230
|
|
|
* |
231
|
|
|
*******************/ |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* @return string |
235
|
|
|
*/ |
236
|
|
|
public function getHelp() |
237
|
|
|
{ |
238
|
|
|
return <<<HELP |
239
|
|
|
<p> |
240
|
|
|
To install the Couchdb HTTP client library via Composer: |
241
|
|
|
<code>composer require "doctrine/couchdb" "@dev"</code> |
242
|
|
|
</p> |
243
|
|
|
HELP; |
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
/** |
247
|
|
|
* @return DriverStatistic |
248
|
|
|
*/ |
249
|
|
|
public function getStats() |
250
|
|
|
{ |
251
|
|
|
$info = $this->instance->getDatabaseInfo(); |
252
|
|
|
|
253
|
|
|
return (new DriverStatistic()) |
254
|
|
|
->setSize($info['sizes']['active']) |
255
|
|
|
->setRawData($info) |
256
|
|
|
->setData(implode(', ', array_keys($this->itemInstances))) |
257
|
|
|
->setInfo('Couchdb version ' . $this->instance->getVersion() . "\n For more information see RawData."); |
258
|
|
|
} |
259
|
|
|
} |
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.