Skip to content

Commit db931dc

Browse files
authored
Merge pull request #27 from JulianVennen/exceptions
Throw specific exceptions with common parent class
2 parents 630a129 + 952092d commit db931dc

15 files changed

+228
-129
lines changed

src/Driver/Cassandra/Cassandra.php

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,22 +121,26 @@ protected function connect(): void
121121
*
122122
* @param string $query
123123
* @return Rows
124-
* @throws Exception
124+
* @throws CassandraModelException if an error occurs while executing the query
125125
*/
126126
protected function rawQuery(string $query): Rows
127127
{
128128
$this->connect();
129129

130130
$statement = new SimpleStatement($query);
131-
return $this->connection->execute($statement, null);
131+
try {
132+
return $this->connection->execute($statement, null);
133+
} catch (Exception $e) {
134+
throw CassandraModelException::wrapping($e);
135+
}
132136
}
133137

134138
/**
135139
* Save the model
136140
*
137141
* @param ModelInterface $model
138142
* @return bool
139-
* @throws Exception
143+
* @throws CassandraModelException if an error occurs while executing the query
140144
*/
141145
public function save(ModelInterface $model): bool
142146
{
@@ -158,7 +162,7 @@ public function save(ModelInterface $model): bool
158162
* @param mixed $id
159163
* @param ModelInterface|null $model
160164
* @return ModelInterface|null
161-
* @throws Exception
165+
* @throws CassandraModelException if an error occurs while executing the query
162166
*/
163167
public function get(string $modelClass, mixed $id, ?ModelInterface $model = null): ?ModelInterface
164168
{
@@ -183,7 +187,7 @@ public function get(string $modelClass, mixed $id, ?ModelInterface $model = null
183187
*
184188
* @param ModelInterface $model
185189
* @return bool
186-
* @throws Exception
190+
* @throws CassandraModelException if an error occurs while executing the query
187191
*/
188192
public function delete(ModelInterface $model): bool
189193
{
@@ -200,7 +204,7 @@ public function delete(ModelInterface $model): bool
200204
*
201205
* @param Query $query
202206
* @return QueryResult
203-
* @throws Exception
207+
* @throws CassandraModelException if an error occurs while executing the query
204208
*/
205209
public function query(Query $query): QueryResult
206210
{
@@ -278,4 +282,4 @@ public function setKeyspace(string $keyspace): Cassandra
278282
$this->keyspace = $keyspace;
279283
return $this;
280284
}
281-
}
285+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php /** @noinspection PhpComposerExtensionStubsInspection */
2+
3+
namespace Aternos\Model\Driver\Cassandra;
4+
5+
use Aternos\Model\WrappingModelException;
6+
use Throwable;
7+
8+
class CassandraModelException extends WrappingModelException
9+
{
10+
/**
11+
* Wrap an existing exception into a CassandraModelException
12+
* This is used to adapt exceptions from the cassandra extension to a ModelException
13+
* @param Throwable $exception
14+
* @return static
15+
*/
16+
static function wrapping(Throwable $exception): static
17+
{
18+
return new self($exception->getMessage(), $exception->getCode(), $exception);
19+
}
20+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Aternos\Model\Driver\Mysqli;
4+
5+
use Throwable;
6+
7+
class MysqlConnectionFailedException extends MysqlException
8+
{
9+
public function __construct(Throwable $previous)
10+
{
11+
parent::__construct("Could not connect to Mysqli database", $previous?->getCode(), $previous);
12+
}
13+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php /** @noinspection PhpComposerExtensionStubsInspection */
2+
3+
namespace Aternos\Model\Driver\Mysqli;
4+
5+
use Aternos\Model\ModelException;
6+
use mysqli;
7+
use Throwable;
8+
9+
class MysqlException extends ModelException
10+
{
11+
/**
12+
* Check if a MySQLi connection has an error and throw an exception if it has
13+
* @param mysqli $connection
14+
* @return void
15+
* @throws MysqlException if the connection has an error
16+
*/
17+
static function checkConnection(mysqli $connection): void
18+
{
19+
if (mysqli_error($connection)) {
20+
throw static::fromConnection($connection);
21+
}
22+
}
23+
24+
/**
25+
* Create an exception from a MySQLi connection with an error
26+
* @param mysqli $connection
27+
* @return static
28+
*/
29+
static function fromConnection(mysqli $connection): static
30+
{
31+
return new self("MySQLi Error #" . mysqli_errno($connection) . ": " . mysqli_error($connection));
32+
}
33+
34+
public function __construct(string $message, int $code = 0, ?Throwable $previous = null)
35+
{
36+
parent::__construct($message, $code, $previous);
37+
}
38+
}

src/Driver/Mysqli/Mysqli.php

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
Query\Generator\SQL,
1111
Query\Query,
1212
Query\QueryResult,
13-
Query\UpdateQuery
14-
};
15-
use Exception;
13+
Query\UpdateQuery};
1614
use mysqli_result;
1715

1816
/**
@@ -99,15 +97,14 @@ public function __construct(?string $host = null, ?int $port = null, ?string $us
9997

10098
/**
10199
* Connect to database
102-
*
103-
* @throws Exception
100+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
104101
*/
105102
protected function connect(): void
106103
{
107104
if (!$this->connection || !@mysqli_ping($this->connection)) {
108105
$this->connection = mysqli_connect($this->host, $this->username, $this->password, $this->database, $this->port, $this->socket);
109106
if (!$this->connection) {
110-
throw new Exception("Could not connect to Mysqli database. Error: " . mysqli_error($this->connection));
107+
throw new MysqlConnectionFailedException(new MysqlException($this->connection));
111108
}
112109
}
113110
}
@@ -117,17 +114,14 @@ protected function connect(): void
117114
*
118115
* @param string $query
119116
* @return bool|mysqli_result
120-
* @throws Exception
117+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
118+
* @throws MysqlException if a mysql error occurs while executing the query
121119
*/
122120
protected function rawQuery(string $query): mysqli_result|bool
123121
{
124122
$this->connect();
125123
$result = mysqli_query($this->connection, $query);
126-
127-
if (mysqli_error($this->connection)) {
128-
throw new Exception("MySQLi Error #" . mysqli_errno($this->connection) . ": " . mysqli_error($this->connection));
129-
}
130-
124+
MysqlException::checkConnection($this->connection);
131125
return $result;
132126
}
133127

@@ -136,7 +130,8 @@ protected function rawQuery(string $query): mysqli_result|bool
136130
*
137131
* @param ModelInterface $model
138132
* @return bool
139-
* @throws Exception
133+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
134+
* @throws MysqlException if a mysql error occurs while executing the query
140135
*/
141136
public function save(ModelInterface $model): bool
142137
{
@@ -182,7 +177,8 @@ public function save(ModelInterface $model): bool
182177
* @param mixed $id
183178
* @param ModelInterface|null $model
184179
* @return ModelInterface|null
185-
* @throws Exception
180+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
181+
* @throws MysqlException if a mysql error occurs while executing the query
186182
*/
187183
public function get(string $modelClass, mixed $id, ?ModelInterface $model = null): ?ModelInterface
188184
{
@@ -208,7 +204,8 @@ public function get(string $modelClass, mixed $id, ?ModelInterface $model = null
208204
*
209205
* @param ModelInterface $model
210206
* @return bool
211-
* @throws Exception
207+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
208+
* @throws MysqlException if a mysql error occurs while executing the query
212209
*/
213210
public function delete(ModelInterface $model): bool
214211
{
@@ -227,7 +224,8 @@ public function delete(ModelInterface $model): bool
227224
*
228225
* @param Query $query
229226
* @return QueryResult
230-
* @throws Exception
227+
* @throws MysqlConnectionFailedException if connecting to the mysql database fails
228+
* @throws MysqlException if a mysql error occurs while executing the query
231229
*/
232230
public function query(Query $query): QueryResult
233231
{
@@ -323,4 +321,4 @@ public function setDatabase(string $database): Mysqli
323321
$this->database = $database;
324322
return $this;
325323
}
326-
}
324+
}

src/Driver/OpenSearch/Exception/OpenSearchException.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace Aternos\Model\Driver\OpenSearch\Exception;
44

5-
use Exception;
5+
use Aternos\Model\ModelException;
66

7-
class OpenSearchException extends Exception
7+
class OpenSearchException extends ModelException
88
{
99

1010
}

src/Driver/OpenSearch/OpenSearch.php

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,9 @@ public function __construct(
7272
* @param string $uri
7373
* @param mixed|null $body
7474
* @return stdClass
75-
* @throws HttpErrorResponseException
76-
* @throws HttpTransportException
77-
* @throws SerializeException
78-
* @throws OpenSearchException
75+
* @throws HttpErrorResponseException If the response status code is not 2xx
76+
* @throws HttpTransportException If an error happens while the http client processes the request
77+
* @throws SerializeException If an error happens during (de-)serialization
7978
*/
8079
protected function request(string $method, string $uri, mixed $body = null): stdClass
8180
{
@@ -96,6 +95,7 @@ protected function request(string $method, string $uri, mixed $body = null): std
9695
throw $e;
9796
}
9897
}
98+
/** @var OpenSearchException $lastError */
9999
throw $lastError;
100100
}
101101

@@ -113,7 +113,9 @@ protected function buildUrl(string ...$path): string
113113
*
114114
* @param ModelInterface $model
115115
* @return bool
116-
* @throws OpenSearchException
116+
* @throws HttpErrorResponseException If the response status code is not 2xx
117+
* @throws HttpTransportException If an error happens while the http client processes the request
118+
* @throws SerializeException If an error happens during (de-)serialization
117119
*/
118120
public function save(ModelInterface $model): bool
119121
{
@@ -132,10 +134,9 @@ public function save(ModelInterface $model): bool
132134
* @param mixed $id
133135
* @param ModelInterface|null $model
134136
* @return ModelInterface|null
135-
* @throws HttpErrorResponseException
136-
* @throws HttpTransportException
137-
* @throws OpenSearchException
138-
* @throws SerializeException
137+
* @throws HttpErrorResponseException If the response status code is not 2xx
138+
* @throws HttpTransportException If an error happens while the http client processes the request
139+
* @throws SerializeException If an error happens during (de-)serialization
139140
*/
140141
public function get(string $modelClass, mixed $id, ?ModelInterface $model = null): ?ModelInterface
141142
{
@@ -151,17 +152,7 @@ public function get(string $modelClass, mixed $id, ?ModelInterface $model = null
151152
throw $e;
152153
}
153154

154-
if (!isset($response->_id) || !is_string($response->_id)) {
155-
throw new SerializeException("Received invalid document _id from OpenSearch");
156-
}
157-
158-
if (isset($response->_source) && is_object($response->_source)) {
159-
$data = get_object_vars($response->_source);
160-
} else {
161-
$data = [];
162-
}
163-
164-
$data[$modelClass::getIdField()] = $response->_id;
155+
$data = $this->getModelData($response, $modelClass);
165156

166157
if ($model) {
167158
return $model->applyData($data);
@@ -174,7 +165,9 @@ public function get(string $modelClass, mixed $id, ?ModelInterface $model = null
174165
*
175166
* @param ModelInterface $model
176167
* @return bool
177-
* @throws OpenSearchException
168+
* @throws HttpErrorResponseException If the response status code is not 2xx
169+
* @throws HttpTransportException If an error happens while the http client processes the request
170+
* @throws SerializeException If an error happens during (de-)serialization
178171
*/
179172
public function delete(ModelInterface $model): bool
180173
{
@@ -208,10 +201,9 @@ protected function getHitCountRelation(string $name): ?CountRelation
208201
/**
209202
* @param Search $search
210203
* @return SearchResult
211-
* @throws HttpErrorResponseException
212-
* @throws HttpTransportException
213-
* @throws OpenSearchException
214-
* @throws SerializeException
204+
* @throws HttpErrorResponseException If the response status code is not 2xx
205+
* @throws HttpTransportException If an error happens while the http client processes the request
206+
* @throws SerializeException If an error happens during (de-)serialization
215207
*/
216208
public function search(Search $search): SearchResult
217209
{
@@ -242,23 +234,32 @@ public function search(Search $search): SearchResult
242234
}
243235

244236
foreach ($response->hits->hits as $resultDocument) {
245-
if (!isset($resultDocument->_id) || !is_string($resultDocument->_id)) {
246-
throw new SerializeException("Received invalid document _id from OpenSearch");
247-
}
248-
249-
if (isset($resultDocument->_source) && is_object($resultDocument->_source)) {
250-
$data = get_object_vars($resultDocument->_source);
251-
} else {
252-
$data = [];
253-
}
254-
255-
$data[$modelClassName::getIdField()] = $resultDocument->_id;
256-
257237
/** @var ModelInterface $model */
258238
$model = new $modelClassName();
259-
$model->applyData($data);
239+
$model->applyData($this->getModelData($resultDocument, $modelClassName));
260240
$result->add($model);
261241
}
262242
return $result;
263243
}
244+
245+
/**
246+
* @param stdClass $response
247+
* @param class-string<ModelInterface> $modelClass $modelClass
248+
* @return array
249+
*/
250+
public function getModelData(stdClass $response, string $modelClass): array
251+
{
252+
if (!isset($response->_id) || !is_string($response->_id)) {
253+
throw new SerializeException("Received invalid document _id from OpenSearch");
254+
}
255+
256+
if (isset($response->_source) && is_object($response->_source)) {
257+
$data = get_object_vars($response->_source);
258+
} else {
259+
$data = [];
260+
}
261+
262+
$data[$modelClass::getIdField()] = $response->_id;
263+
return $data;
264+
}
264265
}

0 commit comments

Comments
 (0)