Skip to content

Commit ffebdd7

Browse files
committed
Create a database object, checking the database exists and optionally creating it
1 parent 022b782 commit ffebdd7

File tree

3 files changed

+168
-3
lines changed

3 files changed

+168
-3
lines changed

src/PHPCouchDB/Database.php

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
3+
/**
4+
* Functionality at the database level
5+
*/
6+
7+
namespace PHPCouchDB;
8+
9+
/**
10+
* Working with a particular database is all done here. Usually instantiated
11+
* by the Server object as it has the connection details we need to use.
12+
*/
13+
14+
15+
class Database
16+
{
17+
protected $client;
18+
protected $db_name;
19+
20+
21+
/**
22+
* Constructor for the Database object - this is usually called by
23+
* Server::useDb rather than directly
24+
*
25+
* @param array $options This should contain "client" (implementing
26+
* \GuzzleHTTP\ClientInterface) and "db_name" (a string)
27+
* @throws \PHPCouchDB\Exception\ServerException if we don't have the
28+
* expected constructor arguments
29+
*/
30+
31+
public function __construct($options)
32+
{
33+
if (empty($options) || !is_array($options)) {
34+
throw new \PHPCouchDB\Exception\ServerException(
35+
'$options is a required parameter, array must contain both the client and a db_name'
36+
);
37+
}
38+
39+
if (isset($options['client']) && $options['client'] instanceof \GuzzleHttp\ClientInterface) {
40+
$this->client = $options['client'];
41+
} else {
42+
throw new \PHPCouchDB\Exception\ServerException(
43+
"The options array must contain a 'client' element of type GuzzleHTTP\ClientInterface"
44+
);
45+
}
46+
47+
if (isset($options['db_name']) && is_string($options['db_name'])) {
48+
$this->db_name = $options['db_name'];
49+
} else {
50+
throw new \PHPCouchDB\Exception\ServerException(
51+
"The options array must contain a 'db_name' key with a value of type string"
52+
);
53+
}
54+
}
55+
}

src/PHPCouchDB/Server.php

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public function __construct(array $options)
5555
* Ask the CouchDB server what version it is running
5656
*
5757
* @return string Version, e.g. "2.0.1"
58+
* @throws \PHPCouchDB\Exception\ServerException if there's a problem with parsing arguments or creating the client
5859
*/
5960
public function getVersion() : string
6061
{
@@ -68,7 +69,7 @@ public function getVersion() : string
6869
return "unknown";
6970
}
7071
} else {
71-
throw new Exception('JSON response not received or not understood');
72+
throw new \PHPCouchDB\Exception\ServerException('JSON response not received or not understood');
7273
}
7374
}
7475
}
@@ -77,17 +78,67 @@ public function getVersion() : string
7778
* Get a list of databases
7879
*
7980
* @return array The database names
81+
* @throws \PHPCouchDB\Exception\ServerException if there's a problem with parsing arguments or creating the client
8082
*/
81-
public function getAllDbs()
83+
public function getAllDbs() : array
8284
{
8385
$response = $this->client->request("GET", "/_all_dbs");
8486
if ($response->getStatusCode() == 200) {
8587
// try to decode JSON
8688
if ($json_data = json_decode($response->getBody(), true)) {
8789
return $json_data;
8890
} else {
89-
throw new Exception('JSON response not received or not understood');
91+
throw new \PHPCouchDB\Exception\ServerException('JSON response not received or not understood');
9092
}
9193
}
9294
}
95+
96+
/**
97+
* Create and return a Database object to work with
98+
*
99+
* @param $options Supply the "name" (required) and an optional boolean
100+
* "create_if_not_exists" value (default is false)
101+
* @return \CouchDB\Database represents the named database
102+
* @throws \PHPCouchDB\Exception\ServerException if there's a problem
103+
* with parsing arguments or creating the database object (e.g. database
104+
* doesn't exist and shouldn't be created)
105+
*/
106+
public function useDb($options) : \PHPCouchDB\Database
107+
{
108+
// check the $options array is sane
109+
if (!isset($options['name'])) {
110+
throw new \PHPCouchDB\Exception\ServerException(
111+
'"name" is a required $options parameter'
112+
);
113+
} else {
114+
$db_name = $options['name'];
115+
}
116+
117+
$create_if_not_exists = isset($options['create_if_not_exists']) ? $options['create_if_not_exists'] : false;
118+
119+
// does this database exist?
120+
$exists = false;
121+
try {
122+
$response = $this->client->request("GET", "/" . $db_name);
123+
if ($response->getStatusCode() == 200) {
124+
$exists = true;
125+
}
126+
} catch (\GuzzleHttp\Exception\ClientException $e) {
127+
// it doesn't exist, should we create it?
128+
if ($create_if_not_exists) {
129+
$create_response = $this->client->request("PUT", "/" . $db_name);
130+
if ($create_response->getStatusCode() == 201) {
131+
$exists = true;
132+
}
133+
}
134+
}
135+
136+
if ($exists) {
137+
return new \PHPCouchDB\Database(["client" => $this->client, "db_name" => $db_name]);
138+
}
139+
140+
throw new \PHPCouchDB\Exception\ServerException(
141+
'Database doesn\'t exist, include "create_if_not_exists" parameter to create it'
142+
);
143+
}
93144
}

tests/PHPCouchDB/ServerTest.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,63 @@ public function testGetAllDbs() {
6060
$this->assertEquals($dbs, $server->getAllDbs());
6161

6262
}
63+
64+
public function testUseADbThatDoesExist() {
65+
$egdb1 = '{"db_name":"egdb","update_seq":"0-g1AAAABXeJzLYWBgYMpgTmEQTM4vTc5ISXLIyU9OzMnILy7JAUklMiTV____PyuRAY-iPBYgydAApP5D1GYBAJmvHGw","sizes":{"file":8488,"external":0,"active":0},"purge_seq":0,"other":{"data_size":0},"doc_del_count":0,"doc_count":0,"disk_size":8488,"disk_format_version":6,"data_size":0,"compact_running":false,"instance_start_time":"0"}';
66+
$response1 = new Response(200, [], $egdb1);
67+
68+
$mock = new MockHandler([ $response1 ]);
69+
$handler = HandlerStack::create($mock);
70+
$client = new Client(['handler' => $handler]);
71+
72+
// userland code starts
73+
$server = new \PHPCouchDB\Server(["client" => $client]);
74+
$this->assertInstanceOf("\PHPCouchDB\Database", $server->useDb(["name" => "egdb"]));
75+
}
76+
77+
public function testUseADbWithCreateThatDoesExist() {
78+
$egdb1 = '{"db_name":"egdb","update_seq":"0-g1AAAABXeJzLYWBgYMpgTmEQTM4vTc5ISXLIyU9OzMnILy7JAUklMiTV____PyuRAY-iPBYgydAApP5D1GYBAJmvHGw","sizes":{"file":8488,"external":0,"active":0},"purge_seq":0,"other":{"data_size":0},"doc_del_count":0,"doc_count":0,"disk_size":8488,"disk_format_version":6,"data_size":0,"compact_running":false,"instance_start_time":"0"}';
79+
$response1 = new Response(200, [], $egdb1);
80+
81+
$mock = new MockHandler([ $response1 ]);
82+
$handler = HandlerStack::create($mock);
83+
$client = new Client(['handler' => $handler]);
84+
85+
// userland code starts
86+
$server = new \PHPCouchDB\Server(["client" => $client]);
87+
$this->assertInstanceOf("\PHPCouchDB\Database", $server->useDb(["name" => "egdb", "create_if_not_exists" => false]));
88+
}
89+
90+
/**
91+
* @expectedException \PHPCouchDB\Exception\ServerException
92+
*/
93+
public function testUseADbThatDoesNotExist() {
94+
$egdb1 = '{"error":"not_found","reason":"Database does not exist."}';
95+
$response1 = new Response(404, [], $egdb1);
96+
97+
$mock = new MockHandler([ $response1 ]);
98+
$handler = HandlerStack::create($mock);
99+
$client = new Client(['handler' => $handler]);
100+
101+
// userland code starts
102+
$server = new \PHPCouchDB\Server(["client" => $client]);
103+
$server->useDb(["name" => "egdb"]);
104+
}
105+
106+
public function testUseADbWithCreateThatDoesNotExist() {
107+
$egdb1 = '{"error":"not_found","reason":"Database does not exist."}';
108+
$response1 = new Response(404, [], $egdb1);
109+
110+
$egdb2 = '{"ok":true}';
111+
$response2 = new Response(201, [], $egdb2);
112+
113+
$mock = new MockHandler([ $response1, $response2 ]);
114+
$handler = HandlerStack::create($mock);
115+
$client = new Client(['handler' => $handler]);
116+
117+
// userland code starts
118+
$server = new \PHPCouchDB\Server(["client" => $client]);
119+
$this->assertInstanceOf("\PHPCouchDB\Database", $server->useDb(["name" => "egdb", "create_if_not_exists" => true]));
120+
}
121+
63122
}

0 commit comments

Comments
 (0)