Skip to content

Commit fabc8e4

Browse files
committed
improved fix for #744
1 parent 79028e7 commit fabc8e4

File tree

8 files changed

+93
-43
lines changed

8 files changed

+93
-43
lines changed

src/Tqdev/PhpCrudApi/Api.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ public function __construct(Config $config)
5959
$prefix = sprintf('phpcrudapi-%s-', substr(md5(__FILE__), 0, 8));
6060
$cache = CacheFactory::create($config->getCacheType(), $prefix, $config->getCachePath());
6161
$reflection = new ReflectionService($db, $cache, $config->getCacheTime());
62-
$responder = new JsonResponder();
63-
$router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime(), $config->getDebug());
62+
$responder = new JsonResponder($config->getDebug());
63+
$router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime());
6464
foreach ($config->getMiddlewares() as $middleware => $properties) {
6565
switch ($middleware) {
6666
case 'sslRedirect':

src/Tqdev/PhpCrudApi/Controller/JsonResponder.php

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,56 @@
99

1010
class JsonResponder implements Responder
1111
{
12+
private $debug;
13+
14+
public function __construct(bool $debug)
15+
{
16+
$this->debug = $debug;
17+
}
18+
1219
public function error(int $error, string $argument, $details = null): ResponseInterface
1320
{
14-
$errorCode = new ErrorCode($error);
15-
$status = $errorCode->getStatus();
16-
$document = new ErrorDocument($errorCode, $argument, $details);
17-
return ResponseFactory::fromObject($status, $document);
21+
$document = new ErrorDocument(new ErrorCode($error), $argument, $details);
22+
return ResponseFactory::fromObject($document->getStatus(), $document);
1823
}
1924

2025
public function success($result): ResponseInterface
2126
{
2227
return ResponseFactory::fromObject(ResponseFactory::OK, $result);
2328
}
29+
30+
public function exception($exception): ResponseInterface
31+
{
32+
$document = ErrorDocument::fromException($exception);
33+
$response = ResponseFactory::fromObject($document->getStatus(), $document);
34+
if ($this->debug) {
35+
$response = ResponseUtils::addExceptionHeaders($response, $exception);
36+
}
37+
return $response;
38+
}
39+
40+
public function multi($results): ResponseInterface
41+
{
42+
$document = array();
43+
$success = true;
44+
foreach ($results as $i=>$result) {
45+
if ($result instanceof \Throwable) {
46+
$document[$i] = ErrorDocument::fromException($result);
47+
$success = false;
48+
} else {
49+
$document[$i] = $result;
50+
}
51+
}
52+
$status = $success ? ResponseFactory::OK : ResponseFactory::FAILED_DEPENDENCY;
53+
$response = ResponseFactory::fromObject($status, $document);
54+
foreach ($results as $i=>$result) {
55+
if ($result instanceof \Throwable) {
56+
if ($this->debug) {
57+
$response = ResponseUtils::addExceptionHeaders($response, $result);
58+
}
59+
}
60+
}
61+
return $response;
62+
}
63+
2464
}

src/Tqdev/PhpCrudApi/Controller/RecordController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private function multiCall(callable $method, array $argumentLists): array
7070
$result[] = call_user_func_array($method, $arguments);
7171
} catch (\Throwable $e) {
7272
$success = false;
73-
$result[] = null;
73+
$result[] = $e;
7474
}
7575
}
7676
if ($success) {
@@ -100,7 +100,7 @@ public function create(ServerRequestInterface $request): ResponseInterface
100100
foreach ($record as $r) {
101101
$argumentLists[] = array($table, $r, $params);
102102
}
103-
return $this->responder->success($this->multiCall([$this->service, 'create'], $argumentLists));
103+
return $this->responder->multi($this->multiCall([$this->service, 'create'], $argumentLists));
104104
} else {
105105
return $this->responder->success($this->service->create($table, $record, $params));
106106
}
@@ -130,7 +130,7 @@ public function update(ServerRequestInterface $request): ResponseInterface
130130
for ($i = 0; $i < count($ids); $i++) {
131131
$argumentLists[] = array($table, $ids[$i], $record[$i], $params);
132132
}
133-
return $this->responder->success($this->multiCall([$this->service, 'update'], $argumentLists));
133+
return $this->responder->multi($this->multiCall([$this->service, 'update'], $argumentLists));
134134
} else {
135135
if (count($ids) != 1) {
136136
return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);

src/Tqdev/PhpCrudApi/Middleware/Router/SimpleRouter.php

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,17 @@ class SimpleRouter implements Router
1818
private $responder;
1919
private $cache;
2020
private $ttl;
21-
private $debug;
2221
private $registration;
2322
private $routes;
2423
private $routeHandlers;
2524
private $middlewares;
2625

27-
public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl, bool $debug)
26+
public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl)
2827
{
2928
$this->basePath = rtrim($this->detectBasePath($basePath), '/');
3029
$this->responder = $responder;
3130
$this->cache = $cache;
3231
$this->ttl = $ttl;
33-
$this->debug = $debug;
3432
$this->registration = true;
3533
$this->routes = $this->loadPathTree();
3634
$this->routeHandlers = [];
@@ -141,23 +139,8 @@ public function handle(ServerRequestInterface $request): ResponseInterface
141139
}
142140
try {
143141
$response = call_user_func($this->routeHandlers[$routeNumbers[0]], $request);
144-
} catch (\PDOException $e) {
145-
if (strpos(strtolower($e->getMessage()), 'duplicate') !== false) {
146-
$response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
147-
} elseif (strpos(strtolower($e->getMessage()), 'unique constraint') !== false) {
148-
$response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
149-
} elseif (strpos(strtolower($e->getMessage()), 'default value') !== false) {
150-
$response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
151-
} elseif (strpos(strtolower($e->getMessage()), 'allow nulls') !== false) {
152-
$response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
153-
} elseif (strpos(strtolower($e->getMessage()), 'constraint') !== false) {
154-
$response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
155-
} else {
156-
$response = $this->responder->error(ErrorCode::ERROR_NOT_FOUND, '');
157-
}
158-
if ($this->debug) {
159-
$response = ResponseUtils::addExceptionHeaders($response, $e);
160-
}
142+
} catch (\Throwable $exception) {
143+
$response = $this->responder->exception($exception);
161144
}
162145
return $response;
163146
}

src/Tqdev/PhpCrudApi/Record/Document/ErrorDocument.php

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,37 @@
66

77
class ErrorDocument implements \JsonSerializable
88
{
9-
public $code;
10-
public $message;
9+
public $errorCode;
10+
public $argument;
1111
public $details;
1212

1313
public function __construct(ErrorCode $errorCode, string $argument, $details)
1414
{
15-
$this->code = $errorCode->getCode();
16-
$this->message = $errorCode->getMessage($argument);
15+
$this->errorCode = $errorCode;
16+
$this->argument = $argument;
1717
$this->details = $details;
1818
}
1919

20+
public function getStatus(): int
21+
{
22+
return $this->errorCode->getStatus();
23+
}
24+
2025
public function getCode(): int
2126
{
22-
return $this->code;
27+
return $this->errorCode->getCode();
2328
}
2429

2530
public function getMessage(): string
2631
{
27-
return $this->message;
32+
return $this->errorCode->getMessage($this->argument);
2833
}
2934

3035
public function serialize()
3136
{
3237
return [
33-
'code' => $this->code,
34-
'message' => $this->message,
38+
'code' => $this->getCode(),
39+
'message' => $this->getMessage(),
3540
'details' => $this->details,
3641
];
3742
}
@@ -40,4 +45,25 @@ public function jsonSerialize()
4045
{
4146
return array_filter($this->serialize());
4247
}
48+
49+
public static function fromException(\Throwable $exception)
50+
{
51+
$document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), $exception->getMessage(), null);
52+
if ($exception instanceof \PDOException) {
53+
if (strpos(strtolower($exception->getMessage()), 'duplicate') !== false) {
54+
$document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
55+
} elseif (strpos(strtolower($exception->getMessage()), 'unique constraint') !== false) {
56+
$document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
57+
} elseif (strpos(strtolower($exception->getMessage()), 'default value') !== false) {
58+
$document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
59+
} elseif (strpos(strtolower($exception->getMessage()), 'allow nulls') !== false) {
60+
$document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
61+
} elseif (strpos(strtolower($exception->getMessage()), 'constraint') !== false) {
62+
$document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
63+
} else {
64+
$document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), '', null);
65+
}
66+
}
67+
return $document;
68+
}
4369
}

src/Tqdev/PhpCrudApi/ResponseFactory.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class ResponseFactory
1616
const METHOD_NOT_ALLOWED = 405;
1717
const CONFLICT = 409;
1818
const UNPROCESSABLE_ENTITY = 422;
19+
const FAILED_DEPENDENCY = 424;
1920
const INTERNAL_SERVER_ERROR = 500;
2021

2122
public static function fromXml(int $status, string $xml): ResponseInterface

tests/functional/001_records/090_add_multiple_comments.log

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ POST /records/comments
2121

2222
[{"user_id":1,"post_id":6,"message":"multi 3","category_id":3},{"user_id":1,"post_id":0,"message":"multi 4","category_id":3}]
2323
===
24-
200
24+
424
2525
Content-Type: application/json; charset=utf-8
26-
Content-Length: 8
26+
Content-Length: 54
2727

28-
[9,null]
28+
[9,{"code":1010,"message":"Data integrity violation"}]
2929
===
3030
GET /records/comments?include=id&filter=post_id,eq,6
3131
===

tests/functional/001_records/091_edit_multiple_comments.log

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ PUT /records/comments/7,8
2121

2222
[{"user_id":1,"post_id":6,"message":"multi 3","category_id":3},{"user_id":1,"post_id":0,"message":"multi 4","category_id":3}]
2323
===
24-
200
24+
424
2525
Content-Type: application/json; charset=utf-8
26-
Content-Length: 8
26+
Content-Length: 54
2727

28-
[1,null]
28+
[1,{"code":1010,"message":"Data integrity violation"}]
2929
===
3030
GET /records/comments?include=message&filter=post_id,eq,6
3131
===

0 commit comments

Comments
 (0)