1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * @file Couch.php |
||||
5 | * @brief This file contains the Couch class. |
||||
6 | * @details |
||||
7 | * @author Filippo F. Fadda |
||||
8 | */ |
||||
9 | |||||
10 | //! This is the main Elephant on Couch library namespace. |
||||
11 | namespace EoC; |
||||
12 | |||||
13 | |||||
14 | use Surfer\Surfer; |
||||
15 | use Surfer\Adapter\IClientAdapter; |
||||
16 | use Surfer\Message\Request; |
||||
17 | use Surfer\Message\Response; |
||||
18 | use Surfer\Hook\IChunkHook; |
||||
19 | |||||
20 | use stdClass; |
||||
21 | |||||
22 | |||||
23 | /** |
||||
24 | * @brief The CouchDB's client. You need an instance of this class to interact with CouchDB. |
||||
25 | * @nosubgrouping |
||||
26 | * @todo Add Memcached support. Remember to use Memcached extension, not memcache. |
||||
27 | * @todo Check ISO-8859-1 because CouchDB uses it, in particular utf8_encode(). |
||||
28 | */ |
||||
29 | final class Couch extends Surfer { |
||||
30 | |||||
31 | //! The user agent name. |
||||
32 | const USER_AGENT_NAME = "EoC Client"; |
||||
33 | |||||
34 | //! Default CouchDB revisions limit number. |
||||
35 | const REVS_LIMIT = 1000; |
||||
36 | |||||
37 | /** @name Document Paths */ |
||||
38 | //!@{ |
||||
0 ignored issues
–
show
|
|||||
39 | |||||
40 | const STD_DOC_PATH = ""; //!< Path for standard documents. |
||||
41 | const LOCAL_DOC_PATH = "_local/"; //!< Path for local documents. |
||||
42 | const DESIGN_DOC_PATH = "_design/"; //!< Path for design documents. |
||||
43 | |||||
44 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
45 | |||||
46 | // A database's name prefix. |
||||
47 | private $prefix = ''; |
||||
48 | |||||
49 | |||||
50 | /** |
||||
51 | * @brief Creates a Couch class instance. |
||||
52 | * @param[in] IClientAdapter $adapter An instance of a class that implements the IClientAdapter interface. |
||||
53 | */ |
||||
54 | public function __construct(IClientAdapter $adapter) { |
||||
55 | parent::__construct($adapter); |
||||
56 | } |
||||
57 | |||||
58 | |||||
59 | /** |
||||
60 | * @brief Returns a CouchDB wild card. |
||||
61 | * @details A standard object is translated to JSON as `{}` same of a JavaScript empty object. |
||||
62 | * @return stdClass |
||||
63 | */ |
||||
64 | public static function WildCard() { |
||||
65 | return new stdClass(); |
||||
66 | } |
||||
67 | |||||
68 | |||||
69 | /** |
||||
70 | * @brief Sets the document class and type in case the document hasn't one. |
||||
71 | * @param[in] Doc\IDoc $doc A document. |
||||
72 | */ |
||||
73 | private function setDocInfo(Doc\IDoc $doc) { |
||||
74 | // Sets the class name. |
||||
75 | $class = get_class($doc); |
||||
76 | $doc->setClass($class); |
||||
77 | |||||
78 | // Sets the document type. |
||||
79 | if (!$doc->hasType()) { |
||||
80 | preg_match('/([\w]+$)/', $class, $matches); |
||||
81 | $type = strtolower($matches[1]); |
||||
82 | $doc->setType($type); |
||||
83 | } |
||||
84 | } |
||||
85 | |||||
86 | |||||
87 | /** |
||||
88 | * @brief Overrides the rows, adding a new row for every key hasn't been matched. |
||||
89 | * @details CouchDB doesn't return rows for the keys a match is not found. To make joins having a row for each key is |
||||
90 | * essential. The algorithm below overrides the rows, adding a new row for every key hasn't been matched. The JSON |
||||
91 | * encoding is necessary because we might have complex keys. A complex key is no more than an array. |
||||
92 | * @param array $keys An array containing the keys. |
||||
93 | * @param[out] array $rows An associative array containing the rows. |
||||
94 | */ |
||||
95 | private function addMissingRows(array $keys, &$rows) { |
||||
96 | |||||
97 | if (!empty($keys) && isset($rows)) { |
||||
98 | |||||
99 | // These are the rows for the matched keys. |
||||
100 | $matches = []; |
||||
101 | foreach ($rows as $row) { |
||||
102 | $hash = md5(json_encode($row['key'])); |
||||
103 | $matches[$hash] = $row; |
||||
104 | } |
||||
105 | |||||
106 | $allRows = []; |
||||
107 | foreach ($keys as $key) { |
||||
108 | $hash = md5(json_encode($key)); |
||||
109 | |||||
110 | if (isset($matches[$hash])) // Match found. |
||||
111 | $allRows[] = $matches[$hash]; |
||||
112 | else // No match found. |
||||
113 | $allRows[] = ['id' => NULL, 'key' => $key, 'value' => NULL]; |
||||
114 | } |
||||
115 | |||||
116 | // Overrides the response, replacing rows. |
||||
117 | $rows = $allRows; |
||||
118 | } |
||||
119 | |||||
120 | } |
||||
121 | |||||
122 | |||||
123 | /** |
||||
124 | * @brief Sets a prefix which is used to compose the database's name. |
||||
125 | * @param string $prefix A string prefix. |
||||
126 | */ |
||||
127 | public function setDbPrefix($prefix) { |
||||
128 | $this->prefix = $prefix; |
||||
129 | } |
||||
130 | |||||
131 | |||||
132 | /** |
||||
133 | * @brief Gets the prefix used to compose the database's name if any. |
||||
134 | * @return string |
||||
135 | */ |
||||
136 | public function getDbPrefix() { |
||||
137 | return $this->prefix; |
||||
138 | } |
||||
139 | |||||
140 | |||||
141 | /** |
||||
142 | * @brief This method is used to send a Request to CouchDB. |
||||
143 | * @details If you want call a not supported CouchDB API, you can use this function to send your request.\n |
||||
144 | * You can also provide an instance of a class that implements the IChunkHook interface, to deal with a chunked |
||||
145 | * response. |
||||
146 | * @param Request $request The Request object. |
||||
147 | * @param IChunkHook $chunkHook (optional) A class instance that implements the IChunkHook interface. |
||||
148 | * @return Response |
||||
149 | */ |
||||
150 | public function send(Request $request, IChunkHook $chunkHook = NULL) { |
||||
151 | // Sets user agent information. |
||||
152 | $request->setHeaderField(Request::USER_AGENT_HF, self::USER_AGENT_NAME." ".Version::getNumber()); |
||||
153 | |||||
154 | // We accept JSON. |
||||
155 | $request->setHeaderField(Request::ACCEPT_HF, "application/json"); |
||||
156 | |||||
157 | // We close the connection after read the response. |
||||
158 | // NOTE: we don't use anymore the connection header field, because we use the same socket until the end of script. |
||||
159 | //$request->setHeaderField(Message::CONNECTION_HF, "close"); |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% 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. ![]() |
|||||
160 | |||||
161 | return parent::send($request, $chunkHook); |
||||
162 | } |
||||
163 | |||||
164 | |||||
165 | /** @name Validation and Encoding Methods */ |
||||
166 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
167 | |||||
168 | /** |
||||
169 | * @brief This method raise an exception when a user provide an invalid document path. |
||||
170 | * @details This method is called by any other methods that interacts with CouchDB. You don't need to call, unless |
||||
171 | * you are making a not supported call to CouchDB. |
||||
172 | * @param string $path Document path. |
||||
173 | * @param bool $excludeLocal Document path. |
||||
174 | */ |
||||
175 | public function validateDocPath($path, $excludeLocal = FALSE) { |
||||
176 | if (empty($path)) // STD_DOC_PATH |
||||
177 | return; |
||||
178 | |||||
179 | if ($path == self::DESIGN_DOC_PATH) |
||||
180 | return; |
||||
181 | elseif ($path == self::LOCAL_DOC_PATH && $excludeLocal) |
||||
182 | throw new \InvalidArgumentException("Local document doesn't have attachments."); |
||||
183 | else |
||||
184 | throw new \InvalidArgumentException("Invalid document path."); |
||||
185 | } |
||||
186 | |||||
187 | |||||
188 | /** |
||||
189 | * @brief Encodes the document id. |
||||
190 | * @details This method is called by any other methods that interacts with CouchDB. You don't need to call, unless |
||||
191 | * you are making a not supported call to CouchDB. |
||||
192 | * @param string $docId Document id. |
||||
193 | */ |
||||
194 | public function validateAndEncodeDocId(&$docId) { |
||||
195 | if (!empty($docId)) |
||||
196 | $docId = rawurlencode($docId); |
||||
197 | else |
||||
198 | throw new \InvalidArgumentException("\$docId must be a non-empty string."); |
||||
199 | } |
||||
200 | |||||
201 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
202 | |||||
203 | |||||
204 | /** @name Miscellaneous Methods */ |
||||
205 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
206 | |||||
207 | /** |
||||
208 | * @brief Creates the admin user. |
||||
209 | * @todo Implement the method. |
||||
210 | */ |
||||
211 | public function createAdminUser() { |
||||
212 | throw new \BadMethodCallException("The method `createAdminUser()` is not available."); |
||||
213 | } |
||||
214 | |||||
215 | |||||
216 | /** |
||||
217 | * @brief Restarts the server. |
||||
218 | * @attention Requires admin privileges. |
||||
219 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#restart |
||||
220 | * @bug [COUCHDB-947](https://issues.apache.org/jira/browse/COUCHDB-947) |
||||
221 | */ |
||||
222 | public function restartServer() { |
||||
223 | $request = new Request(Request::POST_METHOD, "/_restart"); |
||||
224 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
225 | |||||
226 | // There is a bug in CouchDB, sometimes it doesn't return the 200 Status Code because it closes the connection |
||||
227 | // before the client has received the entire response. To avoid problems, we trap the exception and we go on. |
||||
228 | try { |
||||
229 | $this->send($request); |
||||
230 | } |
||||
231 | catch (\Exception $e) { |
||||
232 | if ($e->getCode() > 0) |
||||
233 | throw $e; |
||||
234 | } |
||||
235 | } |
||||
236 | |||||
237 | |||||
238 | /** |
||||
239 | * @brief Returns an object that contains MOTD, server and client and PHP versions. |
||||
240 | * @details The MOTD can be specified in CouchDB configuration files. This function returns more information |
||||
241 | * compared to the CouchDB standard REST call. |
||||
242 | * @return Info\ServerInfo |
||||
243 | */ |
||||
244 | public function getServerInfo() { |
||||
245 | $response = $this->send(new Request(Request::GET_METHOD, "/")); |
||||
246 | $info = $response->getBodyAsArray(); |
||||
247 | return new Info\ServerInfo($info["couchdb"], $info["version"]); |
||||
248 | } |
||||
249 | |||||
250 | |||||
251 | /** |
||||
252 | * @brief Returns information about the Elephant on Couch client. |
||||
253 | * @return Info\ClientInfo |
||||
254 | */ |
||||
255 | public function getClientInfo() { |
||||
256 | return new Info\ClientInfo(); |
||||
257 | } |
||||
258 | |||||
259 | |||||
260 | /** |
||||
261 | * @brief Returns the favicon.ico file. |
||||
262 | * @details The favicon is a part of the admin interface, but the handler for it is special as CouchDB tries to make |
||||
263 | * sure that the favicon is cached for one year. Returns a string that represents the icon. |
||||
264 | * @return string |
||||
265 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#favicon-ico |
||||
266 | */ |
||||
267 | public function getFavicon() { |
||||
268 | $response = $this->send(new Request(Request::GET_METHOD, "/favicon.ico")); |
||||
269 | |||||
270 | if ($response->getHeaderFieldValue(Request::CONTENT_TYPE_HF) == "image/x-icon") |
||||
271 | return $response->getBody(); |
||||
272 | else |
||||
273 | throw new \InvalidArgumentException("Content-Type must be image/x-icon."); |
||||
274 | } |
||||
275 | |||||
276 | |||||
277 | /** |
||||
278 | * @brief Returns server statistics. |
||||
279 | * @return array An associative array |
||||
280 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#stats |
||||
281 | */ |
||||
282 | public function getStats() { |
||||
283 | return $this->send(new Request(Request::GET_METHOD, "/_stats"))->getBodyAsArray(); |
||||
284 | } |
||||
285 | |||||
286 | |||||
287 | /** |
||||
288 | * @brief Returns a list of all databases on this server. |
||||
289 | * @return array of string |
||||
290 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#all-dbs |
||||
291 | */ |
||||
292 | public function getAllDbs() { |
||||
293 | return $this->send(new Request(Request::GET_METHOD, "/_all_dbs"))->getBodyAsArray(); |
||||
294 | } |
||||
295 | |||||
296 | |||||
297 | /** |
||||
298 | * @brief Returns a list of all database events in the CouchDB instance. |
||||
299 | * @param Opt\DbUpdatesFeedOpts $opts Additional options. |
||||
300 | * @return array An associative array. |
||||
301 | * @attention Requires admin privileges. |
||||
302 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#db-updates |
||||
303 | */ |
||||
304 | public function getDbUpdates(Opt\DbUpdatesFeedOpts $opts = NULL) { |
||||
305 | $request = new Request(Request::GET_METHOD, "/_db_updates"); |
||||
306 | |||||
307 | if (isset($opts)) |
||||
308 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
309 | |||||
310 | return $this->send($request)->getBodyAsArray(); |
||||
311 | } |
||||
312 | |||||
313 | |||||
314 | /** |
||||
315 | * @brief Returns a list of running tasks. |
||||
316 | * @attention Requires admin privileges. |
||||
317 | * @return array An associative array. |
||||
318 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#active-tasks |
||||
319 | */ |
||||
320 | public function getActiveTasks() { |
||||
321 | return $this->send(new Request(Request::GET_METHOD, "/_active_tasks"))->getBodyAsArray(); |
||||
322 | } |
||||
323 | |||||
324 | |||||
325 | /** |
||||
326 | * @brief Returns the tail of the server's log file. |
||||
327 | * @attention Requires admin privileges. |
||||
328 | * @param integer $bytes How many bytes to return from the end of the log file. |
||||
329 | * @return string |
||||
330 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#log |
||||
331 | */ |
||||
332 | public function getLogTail($bytes = 1000) { |
||||
333 | if (is_int($bytes) && ($bytes > 0)) { |
||||
334 | $request = new Request(Request::GET_METHOD, "/_log"); |
||||
335 | $request->setQueryParam("bytes", $bytes); |
||||
336 | return $this->send($request)->getBody(); |
||||
337 | } |
||||
338 | else |
||||
339 | throw new \InvalidArgumentException("\$bytes must be a positive integer."); |
||||
340 | } |
||||
341 | |||||
342 | |||||
343 | /** |
||||
344 | * @brief Returns a list of generated UUIDs. |
||||
345 | * @param integer $count Requested UUIDs number. |
||||
346 | * @return string|array If `$count == 1` (default) returns a string else returns an array of strings. |
||||
347 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#uuids |
||||
348 | */ |
||||
349 | public function getUuids($count = 1) { |
||||
350 | if (is_int($count) && ($count > 0)) { |
||||
351 | $request = new Request(Request::GET_METHOD, "/_uuids"); |
||||
352 | $request->setQueryParam("count", $count); |
||||
353 | |||||
354 | $response = $this->send($request); |
||||
355 | |||||
356 | if ($count == 1) // We don't need to use === operator because, just above, we made a type checking. |
||||
357 | return $response->getBodyAsArray()['uuids'][0]; |
||||
358 | else |
||||
359 | return $response->getBodyAsArray()['uuids']; |
||||
360 | } |
||||
361 | else |
||||
362 | throw new \InvalidArgumentException("\$count must be a positive integer."); |
||||
363 | } |
||||
364 | |||||
365 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
366 | |||||
367 | |||||
368 | /** @name Server Configuration Methods */ |
||||
369 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
370 | |||||
371 | /** |
||||
372 | * @brief Returns the entire server configuration or a single section or a single configuration value of a section. |
||||
373 | * @param string $section Requested section. |
||||
374 | * @param string $key Requested key. |
||||
375 | * @return string|array An array with the configuration keys or a simple string in case of a single key. |
||||
376 | * @see http://docs.couchdb.org/en/latest/api/server/configuration.html#get--_config |
||||
377 | * @see http://docs.couchdb.org/en/latest/api/server/configuration.html#get--_config-section |
||||
378 | * @see http://docs.couchdb.org/en/latest/api/server/configuration.html#config-section-key |
||||
379 | */ |
||||
380 | public function getConfig($section = "", $key = "") { |
||||
381 | $path = "/_config"; |
||||
382 | |||||
383 | if (!empty($section)) { |
||||
384 | $path .= "/".$section; |
||||
385 | |||||
386 | if (!empty($key)) |
||||
387 | $path .= "/".$key; |
||||
388 | } |
||||
389 | |||||
390 | return $this->send(new Request(Request::GET_METHOD, $path))->getBodyAsArray(); |
||||
391 | } |
||||
392 | |||||
393 | |||||
394 | /** |
||||
395 | * @brief Sets a single configuration value in a given section to server configuration. |
||||
396 | * @param string $section The configuration section. |
||||
397 | * @param string $key The key. |
||||
398 | * @param string $value The value for the key. |
||||
399 | * @see http://docs.couchdb.org/en/latest/api/server/configuration.html#put--_config-section-key |
||||
400 | */ |
||||
401 | public function setConfigKey($section, $key, $value) { |
||||
402 | if (!is_string($section) || empty($section)) |
||||
0 ignored issues
–
show
|
|||||
403 | throw new \InvalidArgumentException("\$section must be a not empty string."); |
||||
404 | |||||
405 | if (!is_string($key) || empty($key)) |
||||
0 ignored issues
–
show
|
|||||
406 | throw new \InvalidArgumentException("\$key must be a not empty string."); |
||||
407 | |||||
408 | if (is_null($value)) |
||||
0 ignored issues
–
show
|
|||||
409 | throw new \InvalidArgumentException("\$value cannot be null."); |
||||
410 | |||||
411 | $request = new Request(Request::PUT_METHOD, "/_config/".$section."/".$key); |
||||
412 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
413 | $request->setBody(json_encode(utf8_encode($value))); |
||||
414 | $this->send($request); |
||||
415 | } |
||||
416 | |||||
417 | |||||
418 | /** |
||||
419 | * @brief Deletes a single configuration value from a given section in server configuration. |
||||
420 | * @param string $section The configuration section. |
||||
421 | * @param string $key The key. |
||||
422 | * @see http://docs.couchdb.org/en/latest/api/configuration.html#delete-config-section-key |
||||
423 | */ |
||||
424 | public function deleteConfigKey($section, $key) { |
||||
425 | if (!is_string($section) || empty($section)) |
||||
0 ignored issues
–
show
|
|||||
426 | throw new \InvalidArgumentException("\$section must be a not empty string."); |
||||
427 | |||||
428 | if (!is_string($key) || empty($key)) |
||||
0 ignored issues
–
show
|
|||||
429 | throw new \InvalidArgumentException("\$key must be a not empty string."); |
||||
430 | |||||
431 | $this->send(new Request(Request::DELETE_METHOD, "/_config/".$section."/".$key)); |
||||
432 | } |
||||
433 | |||||
434 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
435 | |||||
436 | |||||
437 | /** @name Cookie Authentication */ |
||||
438 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
439 | |||||
440 | /** |
||||
441 | * @brief Returns cookie based login user information. |
||||
442 | * @return Response |
||||
443 | * @see http://docs.couchdb.org/en/latest/api/server/authn.html#get--_session |
||||
444 | */ |
||||
445 | public function getSession() { |
||||
446 | return $this->send(new Request(Request::GET_METHOD, "/_session")); |
||||
447 | } |
||||
448 | |||||
449 | |||||
450 | /** |
||||
451 | * @brief Makes cookie based user login. |
||||
452 | * @return Response |
||||
453 | * @see http://docs.couchdb.org/en/latest/api/server/authn.html#post--_session |
||||
454 | */ |
||||
455 | public function setSession($userName, $password) { |
||||
456 | if (!is_string($userName) || empty($userName)) |
||||
457 | throw new \InvalidArgumentException("\$userName must be a not empty string."); |
||||
458 | |||||
459 | if (!is_string($password) || empty($password)) |
||||
460 | throw new \InvalidArgumentException("\$password must be a not empty string."); |
||||
461 | |||||
462 | $request = new Request(Request::POST_METHOD, "/_session"); |
||||
463 | |||||
464 | $request->setHeaderField(Request::X_COUCHDB_WWW_AUTHENTICATE_HF, "Cookie"); |
||||
465 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/x-www-form-urlencoded"); |
||||
466 | |||||
467 | $request->setQueryParam("name", $userName); |
||||
468 | $request->setQueryParam("password", $password); |
||||
469 | |||||
470 | return $this->send($request); |
||||
471 | } |
||||
472 | |||||
473 | |||||
474 | /** |
||||
475 | * @brief Makes user logout. |
||||
476 | * @return Response |
||||
477 | * @see http://docs.couchdb.org/en/latest/api/server/authn.html#delete--_session |
||||
478 | */ |
||||
479 | public function deleteSession() { |
||||
480 | return $this->send(new Request(Request::DELETE_METHOD, "/_session")); |
||||
481 | } |
||||
482 | |||||
483 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
484 | |||||
485 | |||||
486 | /** @name OAuth Authentication */ |
||||
487 | //! @see http://docs.couchdb.org/en/latest/api/server/authn.html#oauth-authentication |
||||
488 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
489 | |||||
490 | /** |
||||
491 | * @brief |
||||
492 | * @todo To be implemented and documented. |
||||
493 | */ |
||||
494 | public function getAccessToken() { |
||||
495 | return $this->send(new Request(Request::GET_METHOD, "/_oauth/access_token")); |
||||
496 | } |
||||
497 | |||||
498 | |||||
499 | /** |
||||
500 | * @brief |
||||
501 | * @todo To be implemented and documented. |
||||
502 | */ |
||||
503 | public function getAuthorize() { |
||||
504 | return $this->send(new Request(Request::GET_METHOD, "/_oauth/authorize")); |
||||
505 | } |
||||
506 | |||||
507 | |||||
508 | /** |
||||
509 | * @brief |
||||
510 | * @todo To be implemented and documented. |
||||
511 | */ |
||||
512 | public function setAuthorize() { |
||||
513 | return $this->send(new Request(Request::POST_METHOD, "/_oauth/authorize")); |
||||
514 | } |
||||
515 | |||||
516 | |||||
517 | /** |
||||
518 | * @brief |
||||
519 | * @todo To be implemented and documented. |
||||
520 | */ |
||||
521 | public function requestToken() { |
||||
522 | return $this->send(new Request(Request::GET_METHOD, "/_oauth/request_token")); |
||||
523 | } |
||||
524 | |||||
525 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
526 | |||||
527 | |||||
528 | /** |
||||
529 | * @brief Creates a new database and selects it. |
||||
530 | * @param string $name The database name. A database must be named with all lowercase letters (a-z), |
||||
531 | * digits (0-9), or any of the _$()+-/ characters and must end with a slash in the URL. The name has to start with a |
||||
532 | * lowercase letter (a-z). |
||||
533 | * @see http://docs.couchdb.org/en/latest/api/database/common.html#put--db |
||||
534 | */ |
||||
535 | public function createDb($name) { |
||||
536 | # \A[a-z][a-z\d_$()+-/]++\z |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
46% 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. ![]() |
|||||
537 | # |
||||
538 | # Assert position at the beginning of the string «\A» |
||||
539 | # Match a single character in the range between “a” and “z” «[a-z]» |
||||
540 | # Match a single character present in the list below «[a-z\d_$()+-/]++» |
||||
541 | # Between one and unlimited times, as many times as possible, without giving back (possessive) «++» |
||||
542 | # A character in the range between “a” and “z” «a-z» |
||||
543 | # A single digit 0..9 «\d» |
||||
544 | # One of the characters “_$()” «_$()» |
||||
545 | # A character in the range between “+” and “/” «+-/» |
||||
546 | # Assert position at the very end of the string «\z» |
||||
547 | if (preg_match('%\A[a-z][a-z\d_$()+-/]++\z%', $name) === FALSE) |
||||
548 | throw new \InvalidArgumentException("Invalid database name."); |
||||
549 | |||||
550 | $this->send(new Request(Request::PUT_METHOD, "/".rawurlencode($this->prefix.$name)."/")); |
||||
551 | } |
||||
552 | |||||
553 | |||||
554 | /** |
||||
555 | * @brief Deletes an existing database. |
||||
556 | * @param string $name The database name. |
||||
557 | * @see http://docs.couchdb.org/en/latest/api/database/common.html#delete--db |
||||
558 | */ |
||||
559 | public function deleteDb($name) { |
||||
560 | $this->send(new Request(Request::DELETE_METHOD, "/".rawurlencode($this->prefix.$name))); |
||||
561 | } |
||||
562 | |||||
563 | |||||
564 | /** |
||||
565 | * @brief Returns information about the selected database. |
||||
566 | * @param string $name The database name. |
||||
567 | * @return Info\Dbinfo |
||||
568 | * @see http://docs.couchdb.org/en/latest/api/database/common.html#get--db |
||||
569 | */ |
||||
570 | public function getDbInfo($name) { |
||||
571 | return new Info\Dbinfo($this->send(new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$name)."/"))->getBodyAsArray()); |
||||
572 | } |
||||
573 | |||||
574 | |||||
575 | /** |
||||
576 | * @brief Obtains a list of the changes made to the database. This can be used to monitor for update and modifications |
||||
577 | * to the database for post processing or synchronization. |
||||
578 | * @param string $name The database name. |
||||
579 | * @param Opt\ChangesFeedOpts $opts Additional options. |
||||
580 | * @return Response |
||||
581 | * @see http://docs.couchdb.org/en/latest/api/database/changes.html |
||||
582 | */ |
||||
583 | public function getDbChanges($name, Opt\ChangesFeedOpts $opts = NULL) { |
||||
584 | $request = new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$name)."/_changes"); |
||||
585 | |||||
586 | if (isset($opts)) |
||||
587 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
588 | |||||
589 | return $this->send($request); |
||||
590 | } |
||||
591 | |||||
592 | |||||
593 | /** |
||||
594 | * @brief Starts a compaction for the current selected database. |
||||
595 | * @details Writes a new version of the database file, removing any unused sections from the new version during write. |
||||
596 | * Because a new file is temporary created for this purpose, you will need twice the current storage space of the |
||||
597 | * specified database in order for the compaction routine to complete.\n |
||||
598 | * Removes old revisions of documents from the database, up to the per-database limit specified by the `_revs_limit` |
||||
599 | * database setting.\n |
||||
600 | * Compaction can only be requested on an individual database; you cannot compact all the databases for a CouchDB |
||||
601 | * instance.\n |
||||
602 | * The compaction process runs as a background process. You can determine if the compaction process is operating on a |
||||
603 | * database by obtaining the database meta information, the `compact_running` value of the returned database |
||||
604 | * structure will be set to true. You can also obtain a list of running processes to determine whether compaction is |
||||
605 | * currently running, using getActiveTasks(). |
||||
606 | * @param string $name The database name. |
||||
607 | * @attention Requires admin privileges. |
||||
608 | * @see http://docs.couchdb.org/en/latest/api/database/compact.html |
||||
609 | */ |
||||
610 | public function compactDb($name) { |
||||
611 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$name)."/_compact"); |
||||
612 | |||||
613 | // A POST method requires Content-Type header. |
||||
614 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
615 | |||||
616 | $this->send($request); |
||||
617 | } |
||||
618 | |||||
619 | |||||
620 | /** |
||||
621 | * @brief Compacts the specified view. |
||||
622 | * @details If you have very large views or are tight on space, you might consider compaction as well. To run compact |
||||
623 | * for a particular view on a particular database, use this method. |
||||
624 | * @param string $dbName The database name. |
||||
625 | * @param string $designDocName Name of the design document where is stored the view. |
||||
626 | * @see http://docs.couchdb.org/en/latest/api/database/compact.html#db-compact-design-doc |
||||
627 | */ |
||||
628 | public function compactView($dbName, $designDocName) { |
||||
629 | $path = "/".rawurlencode($this->prefix.$dbName)."/_compact/".$designDocName; |
||||
630 | |||||
631 | $request = new Request(Request::POST_METHOD, $path); |
||||
632 | |||||
633 | // A POST method requires Content-Type header. |
||||
634 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
635 | |||||
636 | $this->send($request); |
||||
637 | } |
||||
638 | |||||
639 | |||||
640 | /** |
||||
641 | * @brief Removes all outdated view indexes. |
||||
642 | * @details Old views files remain on disk until you explicitly run cleanup. |
||||
643 | * @param string $dbName The database name. |
||||
644 | * @attention Requires admin privileges. |
||||
645 | * @see http://docs.couchdb.org/en/latest/api/database/compact.html#db-view-cleanup |
||||
646 | */ |
||||
647 | public function cleanupViews($dbName) { |
||||
648 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_view_cleanup"); |
||||
649 | |||||
650 | // A POST method requires Content-Type header. |
||||
651 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
652 | |||||
653 | $this->send($request); |
||||
654 | } |
||||
655 | |||||
656 | |||||
657 | /** |
||||
658 | * @brief Makes sure all uncommited database changes are written and synchronized to the disk. |
||||
659 | * @details Default CouchDB configuration use delayed commit to improve performances. So CouchDB allows operations to |
||||
660 | * be run against the disk without an explicit fsync after each operation. Synchronization takes time (the disk may |
||||
661 | * have to seek, on some platforms the hard disk cache buffer is flushed, etc.), so requiring an fsync for each update |
||||
662 | * deeply limits CouchDB's performance for non-bulk writers.\n |
||||
663 | * Delayed commit should be left set to true in the configuration settings. Anyway, you can still tell CouchDB to make |
||||
664 | * an fsync, calling the this method. |
||||
665 | * @param string $dbName The database name. |
||||
666 | * @return string The timestamp of the last time the database file was opened. |
||||
667 | * @see http://docs.couchdb.org/en/latest/api/database/compact.html#db-ensure-full-commit |
||||
668 | */ |
||||
669 | public function ensureFullCommit($dbName) { |
||||
670 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_ensure_full_commit"); |
||||
671 | |||||
672 | // A POST method requires Content-Type header. |
||||
673 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
674 | |||||
675 | return $this->send($request)->getBodyAsArray()["instance_start_time"]; |
||||
676 | } |
||||
677 | |||||
678 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
679 | |||||
680 | |||||
681 | /** |
||||
682 | * @name Security Methods |
||||
683 | * @details The security object consists of two compulsory elements, admins and members, which are used to specify |
||||
684 | * the list of users and/or roles that have admin and members rights to the database respectively: |
||||
685 | * - members: they can read all types of documents from the DB, and they can write (and edit) documents to the |
||||
686 | * database except for design documents. |
||||
687 | * - admins: they have all the privileges of members plus the privileges: write (and edit) design documents, add/remove |
||||
688 | * database admins and members, set the database revisions limit and execute temporary views against the database. |
||||
689 | * They can not create a database nor delete a database. |
||||
690 | * |
||||
691 | * Both members and admins objects are contains two array-typed fields: |
||||
692 | * - users: List of CouchDB user names |
||||
693 | * - roles: List of users roles |
||||
694 | * |
||||
695 | * Any other additional fields in the security object are optional. The entire security object is made available to |
||||
696 | * validation and other internal functions so that the database can control and limit functionality. |
||||
697 | * If both the names and roles fields of either the admins or members properties are empty arrays, it means the |
||||
698 | * database has no admins or members.\n |
||||
699 | * Having no admins, only server admins (with the reserved _admin role) are able to update design document and make |
||||
700 | * other admin level changes.\n |
||||
701 | * Having no members, any user can write regular documents (any non-design document) and read documents from the database. |
||||
702 | * If there are any member names or roles defined for a database, then only authenticated users having a matching name |
||||
703 | * or role are allowed to read documents from the database. |
||||
704 | */ |
||||
705 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
706 | |||||
707 | /** |
||||
708 | * @brief Returns the special security object for the database. |
||||
709 | * @param string $dbName The database name. |
||||
710 | * @return array An associative array. |
||||
711 | * @see http://docs.couchdb.org/en/latest/api/database/security.html#get--db-_security |
||||
712 | */ |
||||
713 | public function getSecurityObj($dbName) { |
||||
714 | return $this->send(new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_security"))->getBodyAsArray(); |
||||
715 | } |
||||
716 | |||||
717 | |||||
718 | /** |
||||
719 | * @brief Sets the special security object for the database. |
||||
720 | * @param string $dbName The database name. |
||||
721 | * @see http://docs.couchdb.org/en/latest/api/database/security.html#put--db-_security |
||||
722 | */ |
||||
723 | public function setSecurityObj($dbName) { |
||||
724 | return $this->send(new Request(Request::PUT_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_security")); |
||||
725 | } |
||||
726 | |||||
727 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
728 | |||||
729 | |||||
730 | /** |
||||
731 | * @name Database Replication Methods |
||||
732 | * @details The replication is an incremental one way process involving two databases (a source and a destination). |
||||
733 | * The aim of the replication is that at the end of the process, all active documents on the source database are also |
||||
734 | * in the destination database and all documents that were deleted in the source databases are also deleted (if |
||||
735 | * exists) on the destination database.\n |
||||
736 | * The replication process only copies the last revision of a document, so all previous revisions that were only on |
||||
737 | * the source database are not copied to the destination database.\n |
||||
738 | * Changes on the master will not automatically replicate to the slaves. To make replication continuous, you must set |
||||
739 | * `$continuous = true`. At this time, CouchDB does not remember continuous replications over a server restart. |
||||
740 | * Specifying a local source database and a remote target database is called push replication and a remote source and |
||||
741 | * local target is called pull replication. As of CouchDB 0.9, pull replication is a lot more efficient and resistant |
||||
742 | * to errors, and it is suggested that you use pull replication in most cases, especially if your documents are large |
||||
743 | * or you have large attachments. |
||||
744 | */ |
||||
745 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
746 | |||||
747 | /** |
||||
748 | * @brief Starts replication. |
||||
749 | @code |
||||
750 | startReplication("sourcedbname", "http://example.org/targetdbname", TRUE, TRUE); |
||||
751 | @endcode |
||||
752 | * @param string $sourceDbUrl Source database URL. |
||||
753 | * @param string $targetDbUrl Destination database URL. |
||||
754 | * @param string $proxy (optional) Specify the optional proxy used to perform the replication. |
||||
755 | * @param bool $createTargetDb (optional) The target database has to exist and is not implicitly created. You |
||||
756 | * can force the creation setting `$createTargetDb = true`. |
||||
757 | * @param bool $continuous (optional) When `true` CouchDB will not stop after replicating all missing documents |
||||
758 | * from the source to the target.\n |
||||
759 | * At the time of writing, CouchDB doesn't remember continuous replications over a server restart. For the time being, |
||||
760 | * you are required to trigger them again when you restart CouchDB. In the future, CouchDB will allow you to define |
||||
761 | * permanent continuous replications that survive a server restart without you having to do anything. |
||||
762 | * @param string|array $filter (optional) Name of a filter function that can choose which revisions get replicated. |
||||
763 | * You can also provide an array of document identifiers; if given, only these documents will be replicated. |
||||
764 | * @param Opt\ViewQueryOpts $opts (optional) Query options to get additional information, grouping results, include |
||||
765 | * docs, etc. |
||||
766 | * @return Response |
||||
767 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#post--_replicate |
||||
768 | */ |
||||
769 | public function startReplication($sourceDbUrl, $targetDbUrl, $proxy = NULL, $createTargetDb = TRUE, |
||||
770 | $continuous = FALSE, $filter = NULL, Opt\ViewQueryOpts $opts = NULL) { |
||||
771 | // Sets source and target databases. |
||||
772 | if (is_string($sourceDbUrl) && !empty($sourceDbUrl) && |
||||
773 | is_string($targetDbUrl) && !empty($targetDbUrl)) { |
||||
774 | $body["source"] = $sourceDbUrl; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
775 | $body["target"] = $targetDbUrl; |
||||
776 | } |
||||
777 | else |
||||
778 | throw new \InvalidArgumentException("\$source_db_url and \$target_db_url must be non-empty strings."); |
||||
779 | |||||
780 | if (!is_bool($continuous)) |
||||
0 ignored issues
–
show
|
|||||
781 | throw new \InvalidArgumentException("\$continuous must be a bool."); |
||||
782 | elseif ($continuous) |
||||
783 | $body["continuous"] = $continuous; |
||||
784 | |||||
785 | // Uses the specified proxy if any set. |
||||
786 | if (isset($proxy)) |
||||
787 | $body["proxy"] = $proxy; |
||||
788 | |||||
789 | // create_target option |
||||
790 | if (!is_bool($createTargetDb)) |
||||
0 ignored issues
–
show
|
|||||
791 | throw new \InvalidArgumentException("\$createTargetDb must be a bool."); |
||||
792 | elseif ($createTargetDb) |
||||
793 | $body["create_target"] = $createTargetDb; |
||||
794 | |||||
795 | if (!empty($filter)) { |
||||
796 | if (is_string($filter)) // filter option |
||||
797 | $body["filter"] = $filter; |
||||
798 | elseif (is_array($filter)) // doc_ids option |
||||
0 ignored issues
–
show
|
|||||
799 | $body["doc_ids"] = array_values($filter); |
||||
800 | else |
||||
801 | throw new \InvalidArgumentException("\$filter must be a string or an array."); |
||||
802 | } |
||||
803 | |||||
804 | // queryParams option |
||||
805 | if (!is_null($opts)) { |
||||
806 | if ($opts instanceof Opt\ViewQueryOpts) |
||||
0 ignored issues
–
show
|
|||||
807 | $body["query_params"] = get_object_vars($opts); |
||||
808 | else |
||||
809 | throw new \InvalidArgumentException("\$queryParams must be an instance of ViewQueryOpts class."); |
||||
810 | } |
||||
811 | |||||
812 | $request = new Request(Request::POST_METHOD, "/_replicate"); |
||||
813 | $request->setBody($body); |
||||
814 | |||||
815 | return $this->send($request); |
||||
816 | } |
||||
817 | |||||
818 | |||||
819 | /** |
||||
820 | * @brief Cancels replication. |
||||
821 | * @param string $replicationId The replication ID. |
||||
822 | * @return Response |
||||
823 | * @see http://docs.couchdb.org/en/latest/api/server/common.html#canceling-continuous-replication |
||||
824 | */ |
||||
825 | public function stopReplication($replicationId) { |
||||
826 | if (is_null($replicationId)) |
||||
0 ignored issues
–
show
|
|||||
827 | throw new \InvalidArgumentException("You must provide a replication id."); |
||||
828 | |||||
829 | $body["replication_id"] = $replicationId; |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
830 | $body["cancel"] = TRUE; |
||||
831 | |||||
832 | $request = new Request(Request::POST_METHOD, "/_replicate"); |
||||
833 | $request->setBody($body); |
||||
834 | |||||
835 | return $this->send($request); |
||||
836 | } |
||||
837 | |||||
838 | |||||
839 | /** |
||||
840 | * @brief |
||||
841 | * @details |
||||
842 | * @see http://wiki.apache.org/couchdb/Replication#Replicator_database |
||||
843 | * @see http://docs.couchbase.org/couchdb-release-1.1/index.html#couchb-release-1.1-replicatordb |
||||
844 | * @see https://gist.github.com/832610 |
||||
845 | * @todo To be implemented and documented. |
||||
846 | */ |
||||
847 | public function getReplicator() { |
||||
848 | throw new \BadMethodCallException("The method `getReplicator()` is not available."); |
||||
849 | } |
||||
850 | |||||
851 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
852 | |||||
853 | |||||
854 | /** @name Query Documents Methods |
||||
855 | * @details Queries are the primary mechanism for retrieving a result set from a view. The result of a query is an |
||||
856 | * instance of `QueryResult`, a class that implements the [IteratorAggregate](http://php.net/manual/en/class.iteratoraggregate.php), |
||||
857 | * [Countable](http://php.net/manual/en/class.countable.php) and [ArrayAccess](http://php.net/manual/en/class.arrayaccess.php) |
||||
858 | * interfaces, so you can use the result set as an array. |
||||
859 | */ |
||||
860 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
861 | |||||
862 | /** |
||||
863 | * @brief Returns a built-in view of all documents in this database. If keys are specified returns only certain rows. |
||||
864 | * @param string $dbName The database name. |
||||
865 | * @param array $keys (optional) Used to retrieve just the view rows matching that set of keys. Rows are returned |
||||
866 | * in the order of the specified keys. Combining this feature with Opt\ViewQueryOpts.includeDocs() results in the so-called |
||||
867 | * multi-document-fetch feature. |
||||
868 | * @param Opt\ViewQueryOpts $opts (optional) Query options to get additional information, grouping results, include |
||||
869 | * docs, etc. |
||||
870 | * @param IChunkHook $chunkHook (optional) A class instance that implements the IChunkHook interface. |
||||
871 | * @return Result\QueryResult The result of the query. |
||||
872 | * @see http://docs.couchdb.org/en/latest/api/database/bulk-api.html#get--db-_all_docs |
||||
873 | * @see http://docs.couchdb.org/en/latest/api/database/bulk-api.html#post--db-_all_docs |
||||
874 | */ |
||||
875 | public function queryAllDocs($dbName, array $keys = NULL, Opt\ViewQueryOpts $opts = NULL, IChunkHook $chunkHook = NULL) { |
||||
876 | if (is_null($keys)) |
||||
877 | $request = new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_all_docs"); |
||||
878 | else { |
||||
879 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_all_docs"); |
||||
880 | $request->setBody(json_encode(['keys' => $keys])); |
||||
881 | } |
||||
882 | |||||
883 | if (isset($opts)) |
||||
884 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
885 | |||||
886 | $result = $this->send($request, $chunkHook)->getBodyAsArray(); |
||||
887 | |||||
888 | return new Result\QueryResult($result); |
||||
889 | } |
||||
890 | |||||
891 | |||||
892 | /** |
||||
893 | * @brief Executes the given view and returns the result. |
||||
894 | * @param string $dbName The database name. |
||||
895 | * @param string $designDocName The design document's name. |
||||
896 | * @param string $viewName The view's name. |
||||
897 | * @param array $keys (optional) Used to retrieve just the view rows matching that set of keys. Rows are returned |
||||
898 | * in the order of the specified keys. Combining this feature with Opt\ViewQueryOpts.includeDocs() results in the so-called |
||||
899 | * multi-document-fetch feature. |
||||
900 | * @param Opt\ViewQueryOpts $opts (optional) Query options to get additional information, grouping results, include |
||||
901 | * docs, etc. |
||||
902 | * @param IChunkHook $chunkHook (optional) A class instance that implements the IChunkHook interface. |
||||
903 | * @return Result\QueryResult The result of the query. |
||||
904 | * @attention Multiple keys request to a reduce function only supports `group=true` (identical to `group-level=exact`, |
||||
905 | * but it doesn't support `group_level` > 0. |
||||
906 | * CouchDB raises "Multi-key fetchs for reduce view must include `group=true`" error, in case you use `group_level`. |
||||
907 | * @see http://docs.couchdb.org/en/latest/api/ddoc/views.html#get--db-_design-ddoc-_view-view |
||||
908 | * @see http://docs.couchdb.org/en/latest/api/ddoc/views.html#post--db-_design-ddoc-_view-view |
||||
909 | */ |
||||
910 | public function queryView($dbName, $designDocName, $viewName, array $keys = NULL, Opt\ViewQueryOpts $opts = NULL, IChunkHook $chunkHook = NULL) { |
||||
911 | $this->validateAndEncodeDocId($designDocName); |
||||
912 | |||||
913 | if (empty($viewName)) |
||||
914 | throw new \InvalidArgumentException("You must provide a valid \$viewName."); |
||||
915 | |||||
916 | if (empty($keys)) |
||||
917 | $request = new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_design/".$designDocName."/_view/".$viewName); |
||||
918 | else { |
||||
919 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_design/".$designDocName."/_view/".$viewName); |
||||
920 | $request->setBody(json_encode(['keys' => $keys])); |
||||
921 | } |
||||
922 | |||||
923 | // Required since CouchDB 2.0. |
||||
924 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
925 | |||||
926 | if (isset($opts)) { |
||||
927 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
928 | $includeMissingKeys = $opts->issetIncludeMissingKeys(); |
||||
929 | } |
||||
930 | else |
||||
931 | $includeMissingKeys = FALSE; |
||||
932 | |||||
933 | $result = $this->send($request, $chunkHook)->getBodyAsArray(); |
||||
934 | |||||
935 | if ($includeMissingKeys) |
||||
936 | $this->addMissingRows($keys, $result['rows']); |
||||
0 ignored issues
–
show
It seems like
$keys can also be of type null ; however, parameter $keys of EoC\Couch::addMissingRows() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
937 | |||||
938 | return new Result\QueryResult($result); |
||||
939 | } |
||||
940 | |||||
941 | |||||
942 | /** |
||||
943 | * @brief Executes the given view, both map and reduce functions, for all documents and returns the result. |
||||
944 | * @details Map and Reduce functions are provided by the programmer. |
||||
945 | * @attention Requires admin privileges. |
||||
946 | * @param string $dbName The database name. |
||||
947 | * @param string $mapFn The map function. |
||||
948 | * @param string $reduceFn The reduce function. |
||||
949 | * @param array $keys (optional) Used to retrieve just the view rows matching that set of keys. Rows are returned |
||||
950 | * in the order of the specified keys. Combining this feature with Opt\ViewQueryOpts.includeDocs() results in the so-called |
||||
951 | * multi-document-fetch feature. |
||||
952 | * @param Opt\ViewQueryOpts $opts (optional) Query options to get additional information, grouping results, include |
||||
953 | * docs, etc. |
||||
954 | * @param string $language The language used to implement the map and reduce functions. |
||||
955 | * @param IChunkHook $chunkHook (optional) A class instance that implements the IChunkHook interface. |
||||
956 | * @return Result\QueryResult The result of the query. |
||||
957 | * @see http://docs.couchdb.org/en/latest/api/database/temp-views.html#post--db-_temp_view |
||||
958 | */ |
||||
959 | public function queryTempView($dbName, $mapFn, $reduceFn = "", array $keys = NULL, Opt\ViewQueryOpts $opts = NULL, $language = 'php', IChunkHook $chunkHook = NULL) { |
||||
960 | $handler = new Handler\ViewHandler('temp'); |
||||
961 | $handler->language = $language; |
||||
962 | $handler->mapFn = $mapFn; |
||||
963 | if (!empty($reduce)) |
||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
|
|||||
964 | $handler->reduceFn = $reduceFn; |
||||
965 | |||||
966 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_temp_view"); |
||||
967 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
968 | |||||
969 | $array = $handler->asArray(); |
||||
970 | |||||
971 | if (!empty($keys)) |
||||
972 | $array['keys'] = $keys; |
||||
973 | |||||
974 | $request->setBody(json_encode($array)); |
||||
975 | |||||
976 | if (isset($opts)) { |
||||
977 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
978 | $includeMissingKeys = $opts->issetIncludeMissingKeys(); |
||||
979 | } |
||||
980 | else |
||||
981 | $includeMissingKeys = FALSE; |
||||
982 | |||||
983 | $result = $this->send($request, $chunkHook)->getBodyAsArray(); |
||||
984 | |||||
985 | if ($includeMissingKeys) |
||||
986 | $this->addMissingRows($keys, $result['rows']); |
||||
0 ignored issues
–
show
It seems like
$keys can also be of type null ; however, parameter $keys of EoC\Couch::addMissingRows() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
987 | |||||
988 | return new Result\QueryResult($result); |
||||
989 | } |
||||
990 | |||||
991 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
992 | |||||
993 | |||||
994 | /** @name Revisions Management Methods */ |
||||
995 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
996 | |||||
997 | /** |
||||
998 | * @brief Given a list of document revisions, returns the document revisions that do not exist in the database. |
||||
999 | * @param string $dbName The database name. |
||||
1000 | * @return Response |
||||
1001 | * @see http://docs.couchdb.org/en/latest/api/database/misc.html#db-missing-revs |
||||
1002 | */ |
||||
1003 | public function getMissingRevs($dbName) { |
||||
1004 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_missing_revs"); |
||||
1005 | |||||
1006 | return $this->send($request); |
||||
1007 | } |
||||
1008 | |||||
1009 | |||||
1010 | /** |
||||
1011 | * @brief Given a list of document revisions, returns differences between the given revisions and ones that are in |
||||
1012 | * the database. |
||||
1013 | * @param string $dbName The database name. |
||||
1014 | * @return Response |
||||
1015 | * @see http://docs.couchdb.org/en/latest/api/database/misc.html#db-revs-diff |
||||
1016 | */ |
||||
1017 | public function getRevsDiff($dbName) { |
||||
1018 | $request = new Request(Request::POST_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_missing_revs"); |
||||
1019 | |||||
1020 | return $this->send($request); |
||||
1021 | } |
||||
1022 | |||||
1023 | |||||
1024 | /** |
||||
1025 | * @brief Gets the limit of historical revisions to store for a single document in the database. |
||||
1026 | * @param string $dbName The database name. |
||||
1027 | * @return integer The maximum number of document revisions that will be tracked by CouchDB. |
||||
1028 | * @see http://docs.couchdb.org/en/latest/api/database/misc.html#get--db-_revs_limit |
||||
1029 | */ |
||||
1030 | public function getRevsLimit($dbName) { |
||||
1031 | $request = new Request(Request::GET_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_revs_limit"); |
||||
1032 | |||||
1033 | return (integer)$this->send($request)->getBody(); |
||||
1034 | } |
||||
1035 | |||||
1036 | |||||
1037 | /** |
||||
1038 | * @brief Sets the limit of historical revisions for a single document in the database. |
||||
1039 | * @param string $dbName The database name. |
||||
1040 | * @param integer $revsLimit (optional) Maximum number historical revisions for a single document in the database. |
||||
1041 | * Must be a positive integer. |
||||
1042 | * @see http://docs.couchdb.org/en/latest/api/database/misc.html#put--db-_revs_limit |
||||
1043 | */ |
||||
1044 | public function setRevsLimit($dbName, $revsLimit = self::REVS_LIMIT) { |
||||
1045 | if (!is_int($revsLimit) || ($revsLimit <= 0)) |
||||
0 ignored issues
–
show
|
|||||
1046 | throw new \InvalidArgumentException("\$revsLimit must be a positive integer."); |
||||
1047 | |||||
1048 | $request = new Request(Request::PUT_METHOD, "/".rawurlencode($this->prefix.$dbName)."/_revs_limit"); |
||||
1049 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
1050 | $request->setBody(json_encode($revsLimit)); |
||||
1051 | |||||
1052 | $this->send($request); |
||||
1053 | } |
||||
1054 | |||||
1055 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1056 | |||||
1057 | |||||
1058 | /** @name Documents Management Methods */ |
||||
1059 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1060 | |||||
1061 | /** |
||||
1062 | * @brief Returns the document's entity tag, that can be used for caching or optimistic concurrency control purposes. |
||||
1063 | * The ETag Header is simply the document's revision in quotes. |
||||
1064 | * @details This function is not available for special documents. To get information about a design document, use |
||||
1065 | * the special function getDesignDocInfo(). |
||||
1066 | * @param string $dbName The database name. |
||||
1067 | * @param string $docId The document's identifier. |
||||
1068 | * @return string The document's revision. |
||||
1069 | * @see http://docs.couchdb.org/en/latest/api/document/common.html#db-doc |
||||
1070 | * @bug CouchDB ETag is |
||||
1071 | */ |
||||
1072 | public function getDocEtag($dbName, $docId) { |
||||
1073 | $this->validateAndEncodeDocId($docId); |
||||
1074 | |||||
1075 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$docId; |
||||
1076 | |||||
1077 | $request = new Request(Request::HEAD_METHOD, $path); |
||||
1078 | |||||
1079 | // CouchDB ETag is included between quotation marks. |
||||
1080 | return trim($this->send($request)->getHeaderFieldValue(Response::ETAG_HF), '"'); |
||||
1081 | } |
||||
1082 | |||||
1083 | |||||
1084 | /** |
||||
1085 | * @brief Returns the latest revision of the document. |
||||
1086 | * @details Since CouchDB uses different paths to store special documents, you must provide the document type for |
||||
1087 | * design and local documents. |
||||
1088 | * @param string $dbName The database name. |
||||
1089 | * @param string $docId The document's identifier. |
||||
1090 | * @param string $path The document's path. |
||||
1091 | * @param string $rev (optional) The document's revision. |
||||
1092 | * @param Opt\DocOpts $opts Query options to get additional document information, like conflicts, attachments, etc. |
||||
1093 | * @return object|Response An instance of Doc, LocalDoc, DesignDoc or any subclass of Doc. |
||||
1094 | * @see http://docs.couchdb.org/en/latest/api/document/common.html#get--db-docid |
||||
1095 | */ |
||||
1096 | public function getDoc($dbName, $path, $docId, $rev = NULL, Opt\DocOpts $opts = NULL) { |
||||
1097 | $this->validateDocPath($path); |
||||
1098 | $this->validateAndEncodeDocId($docId); |
||||
1099 | |||||
1100 | $requestPath = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId; |
||||
1101 | |||||
1102 | $request = new Request(Request::GET_METHOD, $requestPath); |
||||
1103 | |||||
1104 | // Retrieves the specific revision of the document. |
||||
1105 | if (!empty($rev)) |
||||
1106 | $request->setQueryParam("rev", (string)$rev); |
||||
1107 | |||||
1108 | // If there are any options, add them to the request. |
||||
1109 | if (isset($opts)) { |
||||
1110 | $request->setMultipleQueryParamsAtOnce($opts->asArray()); |
||||
1111 | $ignoreClass = $opts->issetIgnoreClass(); |
||||
1112 | } |
||||
1113 | else |
||||
1114 | $ignoreClass = FALSE; |
||||
1115 | |||||
1116 | $response = $this->send($request); |
||||
1117 | $body = $response->getBodyAsArray(); |
||||
1118 | |||||
1119 | // We use `class` metadata to store an instance of a specialized document class. We can have Article and Book classes, |
||||
1120 | // both derived from Doc, with special properties and methods. Instead to convert them, we store the class name in a |
||||
1121 | // special attribute called 'class' within the others metadata. So, once we retrieve the document, the client creates |
||||
1122 | // an instance of the class we provided when we saved the document; we never need to convert it. |
||||
1123 | if (!$ignoreClass && isset($body['class'])) { // Special document class inherited from Doc or LocalDoc. |
||||
1124 | $class = "\\".$body['class']; |
||||
1125 | $doc = new $class; |
||||
1126 | } |
||||
1127 | elseif ($path == self::DESIGN_DOC_PATH) |
||||
1128 | $doc = new Doc\DesignDoc; |
||||
1129 | else |
||||
1130 | $doc = NULL; |
||||
1131 | |||||
1132 | if (is_object($doc)) { |
||||
1133 | $doc->assignArray($body); |
||||
1134 | return $doc; |
||||
1135 | } |
||||
1136 | else |
||||
1137 | return $response; |
||||
1138 | } |
||||
1139 | |||||
1140 | |||||
1141 | /** |
||||
1142 | * @brief Inserts or updates a document into the selected database. |
||||
1143 | * @details Whether the `$doc` has an id we use a different HTTP method. Using POST CouchDB generates an id for the doc, |
||||
1144 | * using PUT instead we need to specify one. We can still use the function getUuids() to ask CouchDB for some ids. |
||||
1145 | * This is an internal detail. You have only to know that CouchDB can generate the document id for you. |
||||
1146 | * @param string $dbName The database name. |
||||
1147 | * @param Doc\IDoc $doc The document you want insert or update. |
||||
1148 | * @param bool $batchMode (optional) You can write documents to the database at a higher rate by using the batch |
||||
1149 | * option. This collects document writes together in memory (on a user-by-user basis) before they are committed to |
||||
1150 | * disk. This increases the risk of the documents not being stored in the event of a failure, since the documents are |
||||
1151 | * not written to disk immediately. |
||||
1152 | * @see http://docs.couchdb.org/en/latest/api/document/common.html#put--db-docid |
||||
1153 | */ |
||||
1154 | public function saveDoc($dbName, Doc\IDoc $doc, $batchMode = FALSE) { |
||||
1155 | // Whether the document has an id we use a different HTTP method. Using POST CouchDB generates an id for the doc |
||||
1156 | // using PUT we need to specify one. We can still use the function getUuids() to ask CouchDB for some ids. |
||||
1157 | if (!$doc->issetId()) |
||||
1158 | $doc->setId(Generator\UUID::generate(Generator\UUID::UUID_RANDOM, Generator\UUID::FMT_STRING)); |
||||
1159 | |||||
1160 | $this->setDocInfo($doc); |
||||
1161 | |||||
1162 | // We never use the POST method. |
||||
1163 | $method = Request::PUT_METHOD; |
||||
1164 | |||||
1165 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$doc->getPath().$doc->getId(); |
||||
1166 | |||||
1167 | $request = new Request($method, $path); |
||||
1168 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
1169 | $request->setBody($doc->asJson()); |
||||
1170 | |||||
1171 | // Enables batch mode. |
||||
1172 | if ($batchMode) |
||||
1173 | $request->setQueryParam("batch", "ok"); |
||||
1174 | |||||
1175 | $this->send($request); |
||||
1176 | } |
||||
1177 | |||||
1178 | |||||
1179 | /** |
||||
1180 | * @brief Deletes the specified document. |
||||
1181 | * @details To delete a document you must provide the document identifier and the revision number. |
||||
1182 | * @param string $dbName The database name. |
||||
1183 | * @param string $docId The document's identifier you want delete. |
||||
1184 | * @param string $rev The document's revision number you want delete. |
||||
1185 | * @param string $path The document path. |
||||
1186 | * @see http://docs.couchdb.org/en/latest/api/document/common.html#delete--db-docid |
||||
1187 | */ |
||||
1188 | public function deleteDoc($dbName, $path, $docId, $rev) { |
||||
1189 | $this->validateDocPath($path); |
||||
1190 | $this->validateAndEncodeDocId($docId); |
||||
1191 | |||||
1192 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId; |
||||
1193 | |||||
1194 | $request = new Request(Request::DELETE_METHOD, $path); |
||||
1195 | $request->setQueryParam("rev", (string)$rev); |
||||
1196 | |||||
1197 | // We could use another technique to send the revision number. Here just for documentation. |
||||
1198 | // $request->setHeader(Request::IF_MATCH_HEADER, (string)$rev); |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
65% 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. ![]() |
|||||
1199 | |||||
1200 | $this->send($request); |
||||
1201 | } |
||||
1202 | |||||
1203 | |||||
1204 | /** |
||||
1205 | * @brief Makes a duplicate of the specified document. If you want to overwrite an existing document, you need to |
||||
1206 | * specify the target document's revision with a `$rev` parameter. |
||||
1207 | * @details If you want copy a special document you must specify his type. |
||||
1208 | * @param string $dbName The database name. |
||||
1209 | * @param string $sourceDocId The source document id. |
||||
1210 | * @param string $targetDocId The destination document id. |
||||
1211 | * @param string $rev Needed when you want override an existent document. |
||||
1212 | * @param string $path The document path. |
||||
1213 | * @see http://docs.couchdb.org/en/latest/api/document/common.html#copy--db-docid |
||||
1214 | */ |
||||
1215 | public function copyDoc($dbName, $path, $sourceDocId, $targetDocId, $rev = NULL) { |
||||
1216 | $this->validateDocPath($path); |
||||
1217 | |||||
1218 | $this->validateAndEncodeDocId($sourceDocId); |
||||
1219 | $this->validateAndEncodeDocId($targetDocId); |
||||
1220 | |||||
1221 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$sourceDocId; |
||||
1222 | |||||
1223 | // This request uses the special method COPY. |
||||
1224 | $request = new Request(Request::COPY_METHOD, $path); |
||||
1225 | |||||
1226 | if (empty($rev)) |
||||
1227 | $request->setHeaderField(Request::DESTINATION_HF, $targetDocId); |
||||
1228 | else |
||||
1229 | $request->setHeaderField(Request::DESTINATION_HF, $targetDocId."?rev=".(string)$rev); |
||||
1230 | |||||
1231 | $this->send($request); |
||||
1232 | } |
||||
1233 | |||||
1234 | |||||
1235 | /** |
||||
1236 | * @brief The purge operation removes the references to the deleted documents from the database. |
||||
1237 | * @details A database purge permanently removes the references to deleted documents from the database. Deleting a |
||||
1238 | * document within CouchDB does not actually remove the document from the database, instead, the document is marked |
||||
1239 | * as deleted (and a new revision is created). This is to ensure that deleted documents are replicated to other |
||||
1240 | * databases as having been deleted. This also means that you can check the status of a document and identify that |
||||
1241 | * the document has been deleted.\n |
||||
1242 | * The purging of old documents is not replicated to other databases. If you are replicating between databases and |
||||
1243 | * have deleted a large number of documents you should run purge on each database.\n |
||||
1244 | * Purging documents does not remove the space used by them on disk. To reclaim disk space, you should run compactDb().\n |
||||
1245 | * @param string $dbName The database name. |
||||
1246 | * @param array $refs An array of references used to identify documents and revisions to delete. The array must |
||||
1247 | * contains instances of the DocRef class. |
||||
1248 | * @return Response |
||||
1249 | * @see http://docs.couchdb.org/en/latest/api/database/misc.html#post--db-_purge |
||||
1250 | * @see http://wiki.apache.org/couchdb/Purge_Documents |
||||
1251 | */ |
||||
1252 | public function purgeDocs($dbName, array $refs) { |
||||
1253 | $path = "/".rawurlencode($this->prefix.$dbName)."/_purge"; |
||||
1254 | |||||
1255 | $request = new Request(Request::POST_METHOD, $path); |
||||
1256 | |||||
1257 | $purge = []; |
||||
1258 | foreach ($refs as $ref) |
||||
1259 | $purge[] = $ref->asArray(); |
||||
1260 | |||||
1261 | $request->setBody(json_encode($purge)); |
||||
1262 | |||||
1263 | return $this->send($request); |
||||
1264 | } |
||||
1265 | |||||
1266 | |||||
1267 | /** |
||||
1268 | * @brief Inserts, updates and deletes documents in a bulk. |
||||
1269 | * @details Documents that are updated or deleted must contain the `rev` number. To delete a document, you should |
||||
1270 | * call delete() method on your document. When creating new documents the document ID is optional. For updating existing |
||||
1271 | * documents, you must provide the document ID and revision. |
||||
1272 | * @param string $dbName The database name. |
||||
1273 | * @param array $docs An array of documents you want insert, delete or update. |
||||
1274 | * @param bool $fullCommit (optional) Makes sure all uncommited database changes are written and synchronized |
||||
1275 | * to the disk immediately. |
||||
1276 | * @param bool $allOrNothing (optional) In all-or-nothing mode, either all documents are written to the database, |
||||
1277 | * or no documents are written to the database, in the event of a system failure during commit.\n |
||||
1278 | * You can ask CouchDB to check that all the documents pass your validation functions. If even one fails, none of the |
||||
1279 | * documents are written. If all documents pass validation, then all documents will be updated, even if that introduces |
||||
1280 | * a conflict for some or all of the documents. |
||||
1281 | * @param bool $newEdits (optional) When `false` CouchDB pushes existing revisions instead of creating |
||||
1282 | * new ones. The response will not include entries for any of the successful revisions (since their rev IDs are |
||||
1283 | * already known to the sender), only for the ones that had errors. Also, the conflict error will never appear, |
||||
1284 | * since in this mode conflicts are allowed. |
||||
1285 | * @return Response |
||||
1286 | * @see http://docs.couchdb.org/en/latest/api/database/bulk-api.html#db-bulk-docs |
||||
1287 | * @see http://docs.couchdb.org/en/latest/json-structure.html#bulk-documents |
||||
1288 | * @see http://wiki.apache.org/couchdb/HTTP_Bulk_Document_API |
||||
1289 | */ |
||||
1290 | public function performBulkOperations($dbName, array $docs, $fullCommit = FALSE, $allOrNothing = FALSE, $newEdits = TRUE) { |
||||
1291 | if (count($docs) == 0) |
||||
1292 | throw new \InvalidArgumentException("The \$docs array cannot be empty."); |
||||
1293 | else |
||||
1294 | $operations = []; |
||||
1295 | |||||
1296 | $path = "/".rawurlencode($this->prefix.$dbName)."/_bulk_docs"; |
||||
1297 | |||||
1298 | $request = new Request(Request::POST_METHOD, $path); |
||||
1299 | $request->setHeaderField(Request::CONTENT_TYPE_HF, "application/json"); |
||||
1300 | |||||
1301 | if ($fullCommit) |
||||
1302 | $request->setHeaderField(Request::X_COUCHDB_FULL_COMMIT_HF, "full_commit"); |
||||
1303 | else |
||||
1304 | $request->setHeaderField(Request::X_COUCHDB_FULL_COMMIT_HF, "delay_commit"); |
||||
1305 | |||||
1306 | if ($allOrNothing) |
||||
1307 | $operations['all_or_nothing'] = 'true'; |
||||
1308 | |||||
1309 | if (!$newEdits) |
||||
1310 | $operations['new_edits'] = 'false'; |
||||
1311 | |||||
1312 | foreach ($docs as $doc) { |
||||
1313 | $this->setDocInfo($doc); |
||||
1314 | $operations['docs'][] = $doc->asArray(); |
||||
1315 | } |
||||
1316 | |||||
1317 | $request->setBody(json_encode($operations)); |
||||
1318 | |||||
1319 | return $this->send($request); |
||||
1320 | } |
||||
1321 | |||||
1322 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1323 | |||||
1324 | |||||
1325 | /** @name Attachments Management Methods */ |
||||
1326 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1327 | |||||
1328 | |||||
1329 | /** |
||||
1330 | * @brief Returns the attachment revision. |
||||
1331 | * @param string $dbName The database name. |
||||
1332 | * @param string $fileName The attachment's name. |
||||
1333 | * @param string $docId The document's identifier. |
||||
1334 | * @param string $path The document's path. |
||||
1335 | * @param string $rev (optional) The document's revision. |
||||
1336 | * @return array An associative array. |
||||
1337 | * @see http://docs.couchdb.org/en/latest/api/document/attachments.html#db-doc-attachment |
||||
1338 | */ |
||||
1339 | public function getAttachmentInfo($dbName, $fileName, $path, $docId, $rev = NULL) { |
||||
1340 | $this->validateDocPath($path, TRUE); |
||||
1341 | $this->validateAndEncodeDocId($docId); |
||||
1342 | |||||
1343 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId."/".$fileName; |
||||
1344 | |||||
1345 | $request = new Request(Request::HEAD_METHOD, $path); |
||||
1346 | |||||
1347 | // In case we want retrieve a specific document revision. |
||||
1348 | if (!empty($rev)) |
||||
1349 | $request->setQueryParam("rev", (string)$rev); |
||||
1350 | |||||
1351 | return $this->send($request)->getHeaderAsArray(); |
||||
1352 | } |
||||
1353 | |||||
1354 | |||||
1355 | /** |
||||
1356 | * @brief Retrieves the attachment from the specified document. |
||||
1357 | * @param string $dbName The database name. |
||||
1358 | * @param string $fileName The attachment's name. |
||||
1359 | * @param string $docId The document's identifier. |
||||
1360 | * @param string $path The document's path. |
||||
1361 | * @param string $rev (optional) The document's revision. |
||||
1362 | * @see http://docs.couchdb.org/en/latest/api/document/attachments.html#get--db-docid-attname |
||||
1363 | * @see http://docs.couchdb.org/en/latest/api/document/attachments.html#http-range-requests |
||||
1364 | * @todo Add support for Range request, using header "Range: bytes=0-12". |
||||
1365 | */ |
||||
1366 | public function getAttachment($dbName, $fileName, $path, $docId, $rev = NULL) { |
||||
1367 | $this->validateDocPath($path, TRUE); |
||||
1368 | $this->validateAndEncodeDocId($docId); |
||||
1369 | |||||
1370 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId."/".$fileName; |
||||
1371 | |||||
1372 | $request = new Request(Request::GET_METHOD, $path); |
||||
1373 | |||||
1374 | // In case we want retrieve a specific document revision. |
||||
1375 | if (!empty($rev)) |
||||
1376 | $request->setQueryParam("rev", (string)$rev); |
||||
1377 | |||||
1378 | return $this->send($request)->getBody(); |
||||
1379 | } |
||||
1380 | |||||
1381 | |||||
1382 | /** |
||||
1383 | * @brief Inserts or updates an attachment to the specified document. |
||||
1384 | * @param string $dbName The database name. |
||||
1385 | * @param string $fileName The attachment's name. |
||||
1386 | * @param string $docId The document's identifier. |
||||
1387 | * @param string $path The document's path. |
||||
1388 | * @param string $rev (optional) The document's revision. |
||||
1389 | * @see http://docs.couchdb.org/en/latest/api/document/attachments.html#put--db-docid-attname |
||||
1390 | */ |
||||
1391 | public function putAttachment($dbName, $fileName, $path, $docId, $rev = NULL) { |
||||
1392 | $this->validateDocPath($path, TRUE); |
||||
1393 | $this->validateAndEncodeDocId($docId); |
||||
1394 | |||||
1395 | $attachment = Doc\Attachment\Attachment::fromFile($fileName); |
||||
1396 | |||||
1397 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId."/".rawurlencode($attachment->getName()); |
||||
1398 | |||||
1399 | $request = new Request(Request::PUT_METHOD, $path); |
||||
1400 | $request->setHeaderField(Request::CONTENT_LENGTH_HF, $attachment->getContentLength()); |
||||
1401 | $request->setHeaderField(Request::CONTENT_TYPE_HF, $attachment->getContentType()); |
||||
1402 | $request->setBody(base64_encode($attachment->getData())); |
||||
1403 | |||||
1404 | // In case of adding or updating an existence document. |
||||
1405 | if (!empty($rev)) |
||||
1406 | $request->setQueryParam("rev", (string)$rev); |
||||
1407 | |||||
1408 | return $this->send($request); |
||||
1409 | } |
||||
1410 | |||||
1411 | |||||
1412 | /** |
||||
1413 | * @brief Deletes an attachment from the document. |
||||
1414 | * @param string $dbName The database name. |
||||
1415 | * @param string $fileName The attachment's name. |
||||
1416 | * @param string $docId The document's identifier. |
||||
1417 | * @param string $path The document's path. |
||||
1418 | * @param string $rev The document's revision. |
||||
1419 | * @see http://docs.couchdb.org/en/latest/api/document/attachments.html#delete--db-docid-attname |
||||
1420 | */ |
||||
1421 | public function deleteAttachment($dbName, $fileName, $path, $docId, $rev) { |
||||
1422 | $this->validateDocPath($path, TRUE); |
||||
1423 | $this->validateAndEncodeDocId($docId); |
||||
1424 | |||||
1425 | $path = "/".rawurlencode($this->prefix.$dbName)."/".$path.$docId."/".rawurlencode($fileName); |
||||
1426 | |||||
1427 | $request = new Request(Request::DELETE_METHOD, $path); |
||||
1428 | $request->setQueryParam("rev", (string)$rev); |
||||
1429 | |||||
1430 | return $this->send($request); |
||||
1431 | } |
||||
1432 | |||||
1433 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1434 | |||||
1435 | |||||
1436 | /** @name Special Design Documents Management Methods */ |
||||
1437 | //!@{ |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1438 | |||||
1439 | |||||
1440 | /** |
||||
1441 | * @brief Returns basic information about the design document and his views. |
||||
1442 | * @param string $dbName The database name. |
||||
1443 | * @param string $docName The design document's name. |
||||
1444 | * @return array An associative array |
||||
1445 | * @see http://docs.couchdb.org/en/latest/api/ddoc/common.html#get--db-_design-ddoc-_info |
||||
1446 | */ |
||||
1447 | public function getDesignDocInfo($dbName, $docName) { |
||||
1448 | $this->validateAndEncodeDocId($docName); |
||||
1449 | |||||
1450 | $path = "/".rawurlencode($this->prefix.$dbName)."/".self::DESIGN_DOC_PATH.$docName."/_info"; |
||||
1451 | |||||
1452 | $request = new Request(Request::GET_METHOD, $path); |
||||
1453 | |||||
1454 | return $this->send($request)->getBodyAsArray(); |
||||
1455 | } |
||||
1456 | |||||
1457 | //!@} |
||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
100% 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. ![]() |
|||||
1458 | |||||
1459 | } |
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.