Skip to content
This repository was archived by the owner on Jun 18, 2020. It is now read-only.

Commit 75e010d

Browse files
authored
Merge pull request #40 from sandrokeil/feature/custom-exception-support
Add custom exception support
2 parents c8613d5 + 6632554 commit 75e010d

File tree

15 files changed

+208
-35
lines changed

15 files changed

+208
-35
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ endif()
3131
option(BuildVelocyPackExamples "Build examples" OFF)
3232
option(BuildTools "Build support programs and tools" OFF)
3333

34-
#include_directories(/usr/local/include/php /usr/local/include/php/TSRM /usr/local/include/php/main /usr/local/include/php/Zend)
34+
include_directories(/usr/local/include/php /usr/local/include/php/TSRM /usr/local/include/php/main /usr/local/include/php/Zend)
3535

3636
add_subdirectory(deps/fuerte)
3737
#add_subdirectory(deps/phpcpp)

Dockerfile.builder

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,7 @@ VOLUME ["/app"]
3030

3131
RUN apk add --update bash && rm -rf /tmp/*
3232

33+
RUN docker-php-source extract
34+
3335
ENTRYPOINT []
3436
CMD bash -c "cd /app/build && cmake .. -DPHPCPP_ARCH=x86_64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-fPIC && make"

src/connection.cpp

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ namespace arangodb { namespace fuerte { namespace php {
3636
int threadCount = params[0];
3737

3838
if(threadCount < 1) {
39-
throw Php::Exception("Invalid threadCount provided, must be >= 1");
39+
ARANGODB_THROW(InvalidArgumentException(), "Invalid threadCount provided, must be >= 1 in %s on line %d");
40+
return;
4041
}
4142

4243
this->threadCount = threadCount;
@@ -47,17 +48,18 @@ namespace arangodb { namespace fuerte { namespace php {
4748
int defaultTimeout = params[0];
4849

4950
if(defaultTimeout < 1) {
50-
throw Php::Exception("Invalid defaultTimeout provided, must be >= 1");
51+
ARANGODB_THROW(InvalidArgumentException(), "Invalid defaultTimeout provided, must be >= 1 in %s on line %d");
52+
return;
5153
}
5254

5355
this->defaultTimeout = defaultTimeout;
5456
}
5557

5658
fu::ConnectionBuilder Connection::createConnectionBuilder()
5759
{
58-
try {
59-
fu::ConnectionBuilder cbuilder{};
60+
fu::ConnectionBuilder cbuilder{};
6061

62+
try {
6163
for (const auto &p : this->options) {
6264
switch (connectionOptions.at(p.first)) {
6365
case ConnectionOptions::HOST:
@@ -80,12 +82,12 @@ namespace arangodb { namespace fuerte { namespace php {
8082
break;
8183
}
8284
}
83-
84-
return cbuilder;
8585
}
8686
catch (const std::exception &ex) {
87-
throw Php::Exception("Unknown option provided.");
87+
ARANGODB_THROW(InvalidOptionException(), "Unknown option provided in %s on line %d");
8888
}
89+
90+
return cbuilder;
8991
}
9092

9193
void Connection::connect()
@@ -128,8 +130,10 @@ namespace arangodb { namespace fuerte { namespace php {
128130

129131
Php::Value Connection::send(Php::Parameters &params)
130132
{
131-
if(!params[0].instanceOf("ArangoDb\\Request"))
132-
throw Php::Exception("Expected request to be of type Request");
133+
if(!params[0].instanceOf("ArangoDb\\Request")) {
134+
ARANGODB_THROW(InvalidArgumentException(), "Expected request to be of type Request in %s on line %d");
135+
return NULL;
136+
}
133137

134138
Request* request = (Request*)params[0].implementation();
135139

@@ -139,11 +143,15 @@ namespace arangodb { namespace fuerte { namespace php {
139143

140144
void Connection::sendAsync(Php::Parameters &params)
141145
{
142-
if(!params[0].instanceOf("ArangoDb\\Request"))
143-
throw Php::Exception("Expected request to be of type Request");
146+
if(!params[0].instanceOf("ArangoDb\\Request")) {
147+
ARANGODB_THROW(InvalidArgumentException(), "Expected request to be of type Request in %s on line %d");
148+
return;
149+
}
144150

145-
if(!params[1].isCallable())
146-
throw Php::Exception("Expected callback to be of type Callable");
151+
if(!params[1].isCallable()) {
152+
ARANGODB_THROW(InvalidArgumentException(), "Expected callback to be of type Callable in %s on line %d");
153+
return;
154+
}
147155

148156
Request* request = (Request*)params[0].implementation();
149157
this->sendRequestAsync(request, params[1]);
@@ -213,14 +221,17 @@ namespace arangodb { namespace fuerte { namespace php {
213221
this->asyncWaitGroup = new fu::WaitGroup();
214222

215223
if(!success) {
216-
throw Php::Exception("Sending request to ArangoDB failed");
224+
ARANGODB_THROW(RuntimeException(), "Sending request to ArangoDB failed in %s on line %d");
225+
return;
217226
}
218227
}
219228

220229
Php::Value Connection::query(Php::Parameters &params)
221230
{
222-
if(!params[0].instanceOf("ArangoDb\\Vpack"))
223-
throw Php::Exception("Expected vpack to be of type Vpack");
231+
if(!params[0].instanceOf("ArangoDb\\Vpack")) {
232+
ARANGODB_THROW(InvalidArgumentException(), "Expected vpack to be of type Vpack in %s on line %d");
233+
return NULL;
234+
}
224235

225236
Cursor* cursor = new Cursor(this, (Vpack*)params[0].implementation());
226237

src/connection.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "request.h"
77
#include "response.h"
8+
#include "exception.h"
89

910
namespace fu = ::arangodb::fuerte;
1011

src/cursor.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ namespace arangodb { namespace fuerte { namespace php {
99
void Cursor::setOption(int option, int value)
1010
{
1111
if(this->options.size() <= option) {
12-
throw Php::Exception("Invalid option provided for Cursor");
12+
ARANGODB_THROW(InvalidOptionException(), "Invalid option provided for Cursor in %s on line %d");
13+
return;
1314
}
1415

1516
this->options[option] = value;
@@ -24,10 +25,13 @@ namespace arangodb { namespace fuerte { namespace php {
2425
this->response = response;
2526

2627
if(this->response->getFuerteResponse()->slices().front().get("error").getBool()) {
27-
throw Php::Exception(
28-
"Error while executing query: " +
29-
this->response->getFuerteResponse()->slices().front().get("errorMessage").copyString()
28+
ARANGODB_THROW(
29+
RuntimeException(),
30+
("Error while executing query in %s on line %d: " +
31+
this->response->getFuerteResponse()->slices().front().get("errorMessage").copyString()).c_str()
3032
);
33+
34+
return;
3135
}
3236

3337
this->hasMore = this->response->getFuerteResponse()->slices().front().get("hasMore").getBool();
@@ -87,7 +91,8 @@ namespace arangodb { namespace fuerte { namespace php {
8791
vp::Dumper dumper(&sink, &dumperOptions);
8892
dumper.dump(slice);
8993
} catch(vp::Exception const& e) {
90-
throw Php::Exception(e.what());
94+
ARANGODB_THROW(RuntimeException(), e.what());
95+
return NULL;
9196
}
9297

9398
switch(this->options[Cursor::ENTRY_TYPE]) {

src/exception.h

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#pragma once
2+
3+
#include <cmath>
4+
using namespace std;
5+
6+
#include <Zend/zend.h>
7+
#include <Zend/zend_exceptions.h>
8+
#include <Zend/zend_API.h>
9+
10+
#define ARANGODB_THROW(ex, message) zend_throw_exception_ex(ex, 0, message, __FILE__, __LINE__);
11+
12+
13+
namespace arangodb { namespace fuerte { namespace php {
14+
15+
/*
16+
Exception hierarchy
17+
18+
\Exception
19+
\ArangoDb\Exception
20+
\ArangoDb\RuntimeException
21+
\ArangoDb\InvalidOptionException
22+
23+
\Arangodb\InvalidArgumentException
24+
*/
25+
26+
static zend_class_entry* _Exception;
27+
static zend_class_entry* _RuntimeException;
28+
static zend_class_entry* _InvalidOptionException;
29+
static zend_class_entry* _InvalidArgumentException;
30+
31+
32+
static zend_class_entry* Exception() {
33+
zend_string *exceptionClassName = zend_string_tolower(zend_string_init(ZEND_STRL("ArangoDb\\Exception"), 1));
34+
zend_class_entry *exceptionClass = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), exceptionClassName));
35+
zend_string_release(exceptionClassName);
36+
37+
return exceptionClass;
38+
}
39+
40+
static zend_class_entry* RuntimeException() {
41+
zend_string *exceptionClassName = zend_string_tolower(zend_string_init(ZEND_STRL("ArangoDb\\RuntimeException"), 1));
42+
zend_class_entry *exceptionClass = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), exceptionClassName));
43+
zend_string_release(exceptionClassName);
44+
45+
return exceptionClass;
46+
}
47+
48+
static zend_class_entry* InvalidOptionException() {
49+
zend_string *exceptionClassName = zend_string_tolower(zend_string_init(ZEND_STRL("ArangoDb\\InvalidOptionException"), 1));
50+
zend_class_entry *exceptionClass = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), exceptionClassName));
51+
zend_string_release(exceptionClassName);
52+
53+
return exceptionClass;
54+
}
55+
56+
static zend_class_entry* InvalidArgumentException() {
57+
zend_string *exceptionClassName = zend_string_tolower(zend_string_init(ZEND_STRL("ArangoDb\\InvalidArgumentException"), 1));
58+
zend_class_entry *exceptionClass = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), exceptionClassName));
59+
zend_string_release(exceptionClassName);
60+
61+
return exceptionClass;
62+
}
63+
64+
65+
static void registerException()
66+
{
67+
zend_class_entry ce;
68+
INIT_CLASS_ENTRY(ce, "ArangoDb\\Exception", NULL);
69+
_Exception = zend_register_internal_class_ex(&ce, zend_exception_get_default());
70+
}
71+
72+
static void registerRuntimeException()
73+
{
74+
zend_class_entry ce;
75+
INIT_CLASS_ENTRY(ce, "ArangoDb\\RuntimeException", NULL);
76+
_RuntimeException = zend_register_internal_class_ex(&ce, _Exception);
77+
}
78+
79+
static void registerInvalidOptionException()
80+
{
81+
zend_class_entry ce;
82+
INIT_CLASS_ENTRY(ce, "ArangoDb\\InvalidOptionException", NULL);
83+
_InvalidOptionException = zend_register_internal_class_ex(&ce, _RuntimeException);
84+
}
85+
86+
static void registerInvalidArgumentException()
87+
{
88+
zend_class_entry ce;
89+
INIT_CLASS_ENTRY(ce, "ArangoDb\\InvalidArgumentException", NULL);
90+
_RuntimeException = zend_register_internal_class_ex(&ce, _Exception);
91+
}
92+
93+
static void registerCustomExceptions()
94+
{
95+
registerException();
96+
registerRuntimeException();
97+
registerInvalidOptionException();
98+
registerInvalidArgumentException();
99+
}
100+
101+
}}}

src/main.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "response.h"
66
#include "vpack.h"
77
#include "cursor.h"
8+
#include "exception.h"
89

910
extern "C" {
1011

@@ -33,6 +34,10 @@ extern "C" {
3334
exportClassResponse(&extension);
3435
exportClassCursor(&extension);
3536

37+
extension.onStartup([]() {
38+
arangodb::fuerte::php::registerCustomExceptions();
39+
});
40+
3641
return extension;
3742
}
3843

src/request.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ namespace arangodb { namespace fuerte { namespace php {
1717
Request::Request(Php::Parameters params)
1818
{
1919
if(!params[1].instanceOf("ArangoDb\\Vpack")) {
20-
throw Php::Exception("Expected vpack to be of type Vpack");
20+
ARANGODB_THROW(InvalidArgumentException(), "Expected vpack to be of type Vpack in %s on line %d");
21+
return;
2122
}
2223

2324
if(params.size() == 3 && params[2].size() > 0) {
@@ -31,7 +32,8 @@ namespace arangodb { namespace fuerte { namespace php {
3132
void Request::__construct(Php::Parameters &params)
3233
{
3334
if(!params[2].instanceOf("ArangoDb\\Vpack")) {
34-
throw Php::Exception("Expected vpack to be of type Vpack");
35+
ARANGODB_THROW(InvalidArgumentException(), "Expected vpack to be of type Vpack in %s on line %d");
36+
return;
3537
}
3638

3739
if(params.size() == 4 && params[3].size() > 0) {

src/response.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ namespace arangodb { namespace fuerte { namespace php {
2323
vp::Dumper dumper(&sink, &dumperOptions);
2424
dumper.dump(slice);
2525
} catch(vp::Exception const& e) {
26-
throw Php::Exception(e.what());
26+
ARANGODB_THROW(InvalidArgumentException(), e.what());
27+
return NULL;
2728
}
2829

2930
return body;

src/response.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "velocypack/vpack.h"
99
#include "velocypack/velocypack-exception-macros.h"
1010

11+
#include "exception.h"
12+
1113
namespace vp = ::arangodb::velocypack;
1214
namespace fu = ::arangodb::fuerte;
1315

0 commit comments

Comments
 (0)