Browse Source

build fix for #744

Maurits van der Schee 3 years ago
parent
commit
8ab4027d51
2 changed files with 302 additions and 100 deletions
  1. 151
    50
      api.include.php
  2. 151
    50
      api.php

+ 151
- 50
api.include.php View File

@@ -4525,18 +4525,58 @@ namespace Tqdev\PhpCrudApi\Controller {
4525 4525
 
4526 4526
     class JsonResponder implements Responder
4527 4527
     {
4528
+        private $debug;
4529
+
4530
+        public function __construct(bool $debug)
4531
+        {
4532
+            $this->debug = $debug;
4533
+        }
4534
+
4528 4535
         public function error(int $error, string $argument, $details = null): ResponseInterface
4529 4536
         {
4530
-            $errorCode = new ErrorCode($error);
4531
-            $status = $errorCode->getStatus();
4532
-            $document = new ErrorDocument($errorCode, $argument, $details);
4533
-            return ResponseFactory::fromObject($status, $document);
4537
+            $document = new ErrorDocument(new ErrorCode($error), $argument, $details);
4538
+            return ResponseFactory::fromObject($document->getStatus(), $document);
4534 4539
         }
4535 4540
 
4536 4541
         public function success($result): ResponseInterface
4537 4542
         {
4538 4543
             return ResponseFactory::fromObject(ResponseFactory::OK, $result);
4539 4544
         }
4545
+
4546
+        public function exception($exception): ResponseInterface
4547
+        {
4548
+            $document = ErrorDocument::fromException($exception);
4549
+            $response = ResponseFactory::fromObject($document->getStatus(), $document);
4550
+            if ($this->debug) {
4551
+                $response = ResponseUtils::addExceptionHeaders($response, $exception);
4552
+            }
4553
+            return $response;
4554
+        }
4555
+
4556
+        public function multi($results): ResponseInterface
4557
+        {
4558
+            $document = array();
4559
+            $success = true;
4560
+            foreach ($results as $i=>$result) {
4561
+                if ($result instanceof \Throwable) {
4562
+                    $document[$i] = ErrorDocument::fromException($result);
4563
+                    $success = false;
4564
+                } else {
4565
+                    $document[$i] = $result;
4566
+                }
4567
+            }
4568
+            $status = $success ? ResponseFactory::OK : ResponseFactory::FAILED_DEPENDENCY;
4569
+            $response = ResponseFactory::fromObject($status, $document);
4570
+            foreach ($results as $i=>$result) {
4571
+                if ($result instanceof \Throwable) {
4572
+                    if ($this->debug) {
4573
+                        $response = ResponseUtils::addExceptionHeaders($response, $result);
4574
+                    }
4575
+                }
4576
+            }
4577
+            return $response;
4578
+        }
4579
+
4540 4580
     }
4541 4581
 }
4542 4582
 
@@ -4614,11 +4654,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4614 4654
             $params = RequestUtils::getParams($request);
4615 4655
             if (strpos($id, ',') !== false) {
4616 4656
                 $ids = explode(',', $id);
4617
-                $result = [];
4657
+                $argumentLists = array();
4618 4658
                 for ($i = 0; $i < count($ids); $i++) {
4619
-                    array_push($result, $this->service->read($table, $ids[$i], $params));
4659
+                    $argumentLists[] = array($table, $ids[$i], $params);
4620 4660
                 }
4621
-                return $this->responder->success($result);
4661
+                return $this->responder->multi($this->multiCall([$this->service, 'read'], $argumentLists));
4622 4662
             } else {
4623 4663
                 $response = $this->service->read($table, $id, $params);
4624 4664
                 if ($response === null) {
@@ -4628,6 +4668,27 @@ namespace Tqdev\PhpCrudApi\Controller {
4628 4668
             }
4629 4669
         }
4630 4670
 
4671
+        private function multiCall(callable $method, array $argumentLists): array
4672
+        {
4673
+            $result = array();
4674
+            $success = true;
4675
+            $this->service->beginTransaction();
4676
+            foreach ($argumentLists as $arguments) {
4677
+                try {
4678
+                    $result[] = call_user_func_array($method, $arguments);
4679
+                } catch (\Throwable $e) {
4680
+                    $success = false;
4681
+                    $result[] = $e;
4682
+                }
4683
+            }
4684
+            if ($success) {
4685
+                $this->service->commitTransaction();
4686
+            } else {
4687
+                $this->service->rollBackTransaction();
4688
+            }
4689
+            return $result;
4690
+        }
4691
+
4631 4692
         public function create(ServerRequestInterface $request): ResponseInterface
4632 4693
         {
4633 4694
             $table = RequestUtils::getPathSegment($request, 2);
@@ -4643,11 +4704,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4643 4704
             }
4644 4705
             $params = RequestUtils::getParams($request);
4645 4706
             if (is_array($record)) {
4646
-                $result = array();
4707
+                $argumentLists = array();
4647 4708
                 foreach ($record as $r) {
4648
-                    $result[] = $this->service->create($table, $r, $params);
4709
+                    $argumentLists[] = array($table, $r, $params);
4649 4710
                 }
4650
-                return $this->responder->success($result);
4711
+                return $this->responder->multi($this->multiCall([$this->service, 'create'], $argumentLists));
4651 4712
             } else {
4652 4713
                 return $this->responder->success($this->service->create($table, $record, $params));
4653 4714
             }
@@ -4673,11 +4734,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4673 4734
                 if (count($ids) != count($record)) {
4674 4735
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
4675 4736
                 }
4676
-                $result = array();
4737
+                $argumentLists = array();
4677 4738
                 for ($i = 0; $i < count($ids); $i++) {
4678
-                    $result[] = $this->service->update($table, $ids[$i], $record[$i], $params);
4739
+                    $argumentLists[] = array($table, $ids[$i], $record[$i], $params);
4679 4740
                 }
4680
-                return $this->responder->success($result);
4741
+                return $this->responder->multi($this->multiCall([$this->service, 'update'], $argumentLists));
4681 4742
             } else {
4682 4743
                 if (count($ids) != 1) {
4683 4744
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
@@ -4699,11 +4760,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4699 4760
             $params = RequestUtils::getParams($request);
4700 4761
             $ids = explode(',', $id);
4701 4762
             if (count($ids) > 1) {
4702
-                $result = array();
4763
+                $argumentLists = array();
4703 4764
                 for ($i = 0; $i < count($ids); $i++) {
4704
-                    $result[] = $this->service->delete($table, $ids[$i], $params);
4765
+                    $argumentLists[] = array($table, $ids[$i], $params);
4705 4766
                 }
4706
-                return $this->responder->success($result);
4767
+                return $this->responder->multi($this->multiCall([$this->service, 'delete'], $argumentLists));
4707 4768
             } else {
4708 4769
                 return $this->responder->success($this->service->delete($table, $id, $params));
4709 4770
             }
@@ -4729,11 +4790,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4729 4790
                 if (count($ids) != count($record)) {
4730 4791
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
4731 4792
                 }
4732
-                $result = array();
4793
+                $argumentLists = array();
4733 4794
                 for ($i = 0; $i < count($ids); $i++) {
4734
-                    $result[] = $this->service->increment($table, $ids[$i], $record[$i], $params);
4795
+                    $argumentLists[] = array($table, $ids[$i], $record[$i], $params);
4735 4796
                 }
4736
-                return $this->responder->success($result);
4797
+                return $this->responder->multi($this->multiCall([$this->service, 'increment'], $argumentLists));
4737 4798
             } else {
4738 4799
                 if (count($ids) != 1) {
4739 4800
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
@@ -5435,6 +5496,21 @@ namespace Tqdev\PhpCrudApi\Database {
5435 5496
             return $this->definition;
5436 5497
         }
5437 5498
 
5499
+        public function beginTransaction() /*: void*/
5500
+        {
5501
+            $this->pdo->beginTransaction();
5502
+        }
5503
+
5504
+        public function commitTransaction() /*: void*/
5505
+        {
5506
+            $this->pdo->commit();
5507
+        }
5508
+
5509
+        public function rollBackTransaction() /*: void*/
5510
+        {
5511
+            $this->pdo->rollBack();
5512
+        }
5513
+
5438 5514
         private function addMiddlewareConditions(string $tableName, Condition $condition): Condition
5439 5515
         {
5440 5516
             $condition1 = VariableStore::get("authorization.conditions.$tableName");
@@ -5609,7 +5685,7 @@ namespace Tqdev\PhpCrudApi\Database {
5609 5685
                 $this->port,
5610 5686
                 $this->database,
5611 5687
                 $this->tables,
5612
-                $this->username
5688
+                $this->username,
5613 5689
             ]));
5614 5690
         }
5615 5691
     }
@@ -6979,19 +7055,17 @@ namespace Tqdev\PhpCrudApi\Middleware\Router {
6979 7055
         private $responder;
6980 7056
         private $cache;
6981 7057
         private $ttl;
6982
-        private $debug;
6983 7058
         private $registration;
6984 7059
         private $routes;
6985 7060
         private $routeHandlers;
6986 7061
         private $middlewares;
6987 7062
 
6988
-        public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl, bool $debug)
7063
+        public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl)
6989 7064
         {
6990 7065
             $this->basePath = rtrim($this->detectBasePath($basePath), '/');
6991 7066
             $this->responder = $responder;
6992 7067
             $this->cache = $cache;
6993 7068
             $this->ttl = $ttl;
6994
-            $this->debug = $debug;
6995 7069
             $this->registration = true;
6996 7070
             $this->routes = $this->loadPathTree();
6997 7071
             $this->routeHandlers = [];
@@ -7102,23 +7176,8 @@ namespace Tqdev\PhpCrudApi\Middleware\Router {
7102 7176
             }
7103 7177
             try {
7104 7178
                 $response = call_user_func($this->routeHandlers[$routeNumbers[0]], $request);
7105
-            } catch (\PDOException $e) {
7106
-                if (strpos(strtolower($e->getMessage()), 'duplicate') !== false) {
7107
-                    $response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
7108
-                } elseif (strpos(strtolower($e->getMessage()), 'unique constraint') !== false) {
7109
-                    $response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
7110
-                } elseif (strpos(strtolower($e->getMessage()), 'default value') !== false) {
7111
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7112
-                } elseif (strpos(strtolower($e->getMessage()), 'allow nulls') !== false) {
7113
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7114
-                } elseif (strpos(strtolower($e->getMessage()), 'constraint') !== false) {
7115
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7116
-                } else {
7117
-                    $response = $this->responder->error(ErrorCode::ERROR_NOT_FOUND, '');
7118
-                }
7119
-                if ($this->debug) {
7120
-                    $response = ResponseUtils::addExceptionHeaders($response, $e);
7121
-                }
7179
+            } catch (\Throwable $exception) {
7180
+                $response = $this->responder->exception($exception);
7122 7181
             }
7123 7182
             return $response;
7124 7183
         }
@@ -9790,32 +9849,37 @@ namespace Tqdev\PhpCrudApi\Record\Document {
9790 9849
 
9791 9850
     class ErrorDocument implements \JsonSerializable
9792 9851
     {
9793
-        public $code;
9794
-        public $message;
9852
+        public $errorCode;
9853
+        public $argument;
9795 9854
         public $details;
9796 9855
 
9797 9856
         public function __construct(ErrorCode $errorCode, string $argument, $details)
9798 9857
         {
9799
-            $this->code = $errorCode->getCode();
9800
-            $this->message = $errorCode->getMessage($argument);
9858
+            $this->errorCode = $errorCode;
9859
+            $this->argument = $argument;
9801 9860
             $this->details = $details;
9802 9861
         }
9803 9862
 
9863
+        public function getStatus(): int
9864
+        {
9865
+            return $this->errorCode->getStatus();
9866
+        }
9867
+
9804 9868
         public function getCode(): int
9805 9869
         {
9806
-            return $this->code;
9870
+            return $this->errorCode->getCode();
9807 9871
         }
9808 9872
 
9809 9873
         public function getMessage(): string
9810 9874
         {
9811
-            return $this->message;
9875
+            return $this->errorCode->getMessage($this->argument);
9812 9876
         }
9813 9877
 
9814 9878
         public function serialize()
9815 9879
         {
9816 9880
             return [
9817
-                'code' => $this->code,
9818
-                'message' => $this->message,
9881
+                'code' => $this->getCode(),
9882
+                'message' => $this->getMessage(),
9819 9883
                 'details' => $this->details,
9820 9884
             ];
9821 9885
         }
@@ -9824,6 +9888,27 @@ namespace Tqdev\PhpCrudApi\Record\Document {
9824 9888
         {
9825 9889
             return array_filter($this->serialize());
9826 9890
         }
9891
+
9892
+        public static function fromException(\Throwable $exception)
9893
+        {
9894
+            $document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), $exception->getMessage(), null);
9895
+            if ($exception instanceof \PDOException) {
9896
+                if (strpos(strtolower($exception->getMessage()), 'duplicate') !== false) {
9897
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
9898
+                } elseif (strpos(strtolower($exception->getMessage()), 'unique constraint') !== false) {
9899
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
9900
+                } elseif (strpos(strtolower($exception->getMessage()), 'default value') !== false) {
9901
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9902
+                } elseif (strpos(strtolower($exception->getMessage()), 'allow nulls') !== false) {
9903
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9904
+                } elseif (strpos(strtolower($exception->getMessage()), 'constraint') !== false) {
9905
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9906
+                } else {
9907
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), '', null);
9908
+                }
9909
+            }
9910
+            return $document;
9911
+        }
9827 9912
     }
9828 9913
 }
9829 9914
 
@@ -10349,6 +10434,21 @@ namespace Tqdev\PhpCrudApi\Record {
10349 10434
             return $this->reflection->getType($table);
10350 10435
         }
10351 10436
 
10437
+        public function beginTransaction() /*: void*/
10438
+        {
10439
+            $this->db->beginTransaction();
10440
+        }
10441
+
10442
+        public function commitTransaction() /*: void*/
10443
+        {
10444
+            $this->db->commitTransaction();
10445
+        }
10446
+
10447
+        public function rollBackTransaction() /*: void*/
10448
+        {
10449
+            $this->db->rollBackTransaction();
10450
+        }
10451
+
10352 10452
         public function create(string $tableName, /* object */ $record, array $params) /*: ?int*/
10353 10453
         {
10354 10454
             $this->sanitizeRecord($tableName, $record, '');
@@ -10773,8 +10873,8 @@ namespace Tqdev\PhpCrudApi {
10773 10873
             $prefix = sprintf('phpcrudapi-%s-', substr(md5(__FILE__), 0, 8));
10774 10874
             $cache = CacheFactory::create($config->getCacheType(), $prefix, $config->getCachePath());
10775 10875
             $reflection = new ReflectionService($db, $cache, $config->getCacheTime());
10776
-            $responder = new JsonResponder();
10777
-            $router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime(), $config->getDebug());
10876
+            $responder = new JsonResponder($config->getDebug());
10877
+            $router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime());
10778 10878
             foreach ($config->getMiddlewares() as $middleware => $properties) {
10779 10879
                 switch ($middleware) {
10780 10880
                     case 'sslRedirect':
@@ -11297,6 +11397,7 @@ namespace Tqdev\PhpCrudApi {
11297 11397
         const METHOD_NOT_ALLOWED = 405;
11298 11398
         const CONFLICT = 409;
11299 11399
         const UNPROCESSABLE_ENTITY = 422;
11400
+        const FAILED_DEPENDENCY = 424;
11300 11401
         const INTERNAL_SERVER_ERROR = 500;
11301 11402
 
11302 11403
         public static function fromXml(int $status, string $xml): ResponseInterface

+ 151
- 50
api.php View File

@@ -4525,18 +4525,58 @@ namespace Tqdev\PhpCrudApi\Controller {
4525 4525
 
4526 4526
     class JsonResponder implements Responder
4527 4527
     {
4528
+        private $debug;
4529
+
4530
+        public function __construct(bool $debug)
4531
+        {
4532
+            $this->debug = $debug;
4533
+        }
4534
+
4528 4535
         public function error(int $error, string $argument, $details = null): ResponseInterface
4529 4536
         {
4530
-            $errorCode = new ErrorCode($error);
4531
-            $status = $errorCode->getStatus();
4532
-            $document = new ErrorDocument($errorCode, $argument, $details);
4533
-            return ResponseFactory::fromObject($status, $document);
4537
+            $document = new ErrorDocument(new ErrorCode($error), $argument, $details);
4538
+            return ResponseFactory::fromObject($document->getStatus(), $document);
4534 4539
         }
4535 4540
 
4536 4541
         public function success($result): ResponseInterface
4537 4542
         {
4538 4543
             return ResponseFactory::fromObject(ResponseFactory::OK, $result);
4539 4544
         }
4545
+
4546
+        public function exception($exception): ResponseInterface
4547
+        {
4548
+            $document = ErrorDocument::fromException($exception);
4549
+            $response = ResponseFactory::fromObject($document->getStatus(), $document);
4550
+            if ($this->debug) {
4551
+                $response = ResponseUtils::addExceptionHeaders($response, $exception);
4552
+            }
4553
+            return $response;
4554
+        }
4555
+
4556
+        public function multi($results): ResponseInterface
4557
+        {
4558
+            $document = array();
4559
+            $success = true;
4560
+            foreach ($results as $i=>$result) {
4561
+                if ($result instanceof \Throwable) {
4562
+                    $document[$i] = ErrorDocument::fromException($result);
4563
+                    $success = false;
4564
+                } else {
4565
+                    $document[$i] = $result;
4566
+                }
4567
+            }
4568
+            $status = $success ? ResponseFactory::OK : ResponseFactory::FAILED_DEPENDENCY;
4569
+            $response = ResponseFactory::fromObject($status, $document);
4570
+            foreach ($results as $i=>$result) {
4571
+                if ($result instanceof \Throwable) {
4572
+                    if ($this->debug) {
4573
+                        $response = ResponseUtils::addExceptionHeaders($response, $result);
4574
+                    }
4575
+                }
4576
+            }
4577
+            return $response;
4578
+        }
4579
+
4540 4580
     }
4541 4581
 }
4542 4582
 
@@ -4614,11 +4654,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4614 4654
             $params = RequestUtils::getParams($request);
4615 4655
             if (strpos($id, ',') !== false) {
4616 4656
                 $ids = explode(',', $id);
4617
-                $result = [];
4657
+                $argumentLists = array();
4618 4658
                 for ($i = 0; $i < count($ids); $i++) {
4619
-                    array_push($result, $this->service->read($table, $ids[$i], $params));
4659
+                    $argumentLists[] = array($table, $ids[$i], $params);
4620 4660
                 }
4621
-                return $this->responder->success($result);
4661
+                return $this->responder->multi($this->multiCall([$this->service, 'read'], $argumentLists));
4622 4662
             } else {
4623 4663
                 $response = $this->service->read($table, $id, $params);
4624 4664
                 if ($response === null) {
@@ -4628,6 +4668,27 @@ namespace Tqdev\PhpCrudApi\Controller {
4628 4668
             }
4629 4669
         }
4630 4670
 
4671
+        private function multiCall(callable $method, array $argumentLists): array
4672
+        {
4673
+            $result = array();
4674
+            $success = true;
4675
+            $this->service->beginTransaction();
4676
+            foreach ($argumentLists as $arguments) {
4677
+                try {
4678
+                    $result[] = call_user_func_array($method, $arguments);
4679
+                } catch (\Throwable $e) {
4680
+                    $success = false;
4681
+                    $result[] = $e;
4682
+                }
4683
+            }
4684
+            if ($success) {
4685
+                $this->service->commitTransaction();
4686
+            } else {
4687
+                $this->service->rollBackTransaction();
4688
+            }
4689
+            return $result;
4690
+        }
4691
+
4631 4692
         public function create(ServerRequestInterface $request): ResponseInterface
4632 4693
         {
4633 4694
             $table = RequestUtils::getPathSegment($request, 2);
@@ -4643,11 +4704,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4643 4704
             }
4644 4705
             $params = RequestUtils::getParams($request);
4645 4706
             if (is_array($record)) {
4646
-                $result = array();
4707
+                $argumentLists = array();
4647 4708
                 foreach ($record as $r) {
4648
-                    $result[] = $this->service->create($table, $r, $params);
4709
+                    $argumentLists[] = array($table, $r, $params);
4649 4710
                 }
4650
-                return $this->responder->success($result);
4711
+                return $this->responder->multi($this->multiCall([$this->service, 'create'], $argumentLists));
4651 4712
             } else {
4652 4713
                 return $this->responder->success($this->service->create($table, $record, $params));
4653 4714
             }
@@ -4673,11 +4734,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4673 4734
                 if (count($ids) != count($record)) {
4674 4735
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
4675 4736
                 }
4676
-                $result = array();
4737
+                $argumentLists = array();
4677 4738
                 for ($i = 0; $i < count($ids); $i++) {
4678
-                    $result[] = $this->service->update($table, $ids[$i], $record[$i], $params);
4739
+                    $argumentLists[] = array($table, $ids[$i], $record[$i], $params);
4679 4740
                 }
4680
-                return $this->responder->success($result);
4741
+                return $this->responder->multi($this->multiCall([$this->service, 'update'], $argumentLists));
4681 4742
             } else {
4682 4743
                 if (count($ids) != 1) {
4683 4744
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
@@ -4699,11 +4760,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4699 4760
             $params = RequestUtils::getParams($request);
4700 4761
             $ids = explode(',', $id);
4701 4762
             if (count($ids) > 1) {
4702
-                $result = array();
4763
+                $argumentLists = array();
4703 4764
                 for ($i = 0; $i < count($ids); $i++) {
4704
-                    $result[] = $this->service->delete($table, $ids[$i], $params);
4765
+                    $argumentLists[] = array($table, $ids[$i], $params);
4705 4766
                 }
4706
-                return $this->responder->success($result);
4767
+                return $this->responder->multi($this->multiCall([$this->service, 'delete'], $argumentLists));
4707 4768
             } else {
4708 4769
                 return $this->responder->success($this->service->delete($table, $id, $params));
4709 4770
             }
@@ -4729,11 +4790,11 @@ namespace Tqdev\PhpCrudApi\Controller {
4729 4790
                 if (count($ids) != count($record)) {
4730 4791
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
4731 4792
                 }
4732
-                $result = array();
4793
+                $argumentLists = array();
4733 4794
                 for ($i = 0; $i < count($ids); $i++) {
4734
-                    $result[] = $this->service->increment($table, $ids[$i], $record[$i], $params);
4795
+                    $argumentLists[] = array($table, $ids[$i], $record[$i], $params);
4735 4796
                 }
4736
-                return $this->responder->success($result);
4797
+                return $this->responder->multi($this->multiCall([$this->service, 'increment'], $argumentLists));
4737 4798
             } else {
4738 4799
                 if (count($ids) != 1) {
4739 4800
                     return $this->responder->error(ErrorCode::ARGUMENT_COUNT_MISMATCH, $id);
@@ -5435,6 +5496,21 @@ namespace Tqdev\PhpCrudApi\Database {
5435 5496
             return $this->definition;
5436 5497
         }
5437 5498
 
5499
+        public function beginTransaction() /*: void*/
5500
+        {
5501
+            $this->pdo->beginTransaction();
5502
+        }
5503
+
5504
+        public function commitTransaction() /*: void*/
5505
+        {
5506
+            $this->pdo->commit();
5507
+        }
5508
+
5509
+        public function rollBackTransaction() /*: void*/
5510
+        {
5511
+            $this->pdo->rollBack();
5512
+        }
5513
+
5438 5514
         private function addMiddlewareConditions(string $tableName, Condition $condition): Condition
5439 5515
         {
5440 5516
             $condition1 = VariableStore::get("authorization.conditions.$tableName");
@@ -5609,7 +5685,7 @@ namespace Tqdev\PhpCrudApi\Database {
5609 5685
                 $this->port,
5610 5686
                 $this->database,
5611 5687
                 $this->tables,
5612
-                $this->username
5688
+                $this->username,
5613 5689
             ]));
5614 5690
         }
5615 5691
     }
@@ -6979,19 +7055,17 @@ namespace Tqdev\PhpCrudApi\Middleware\Router {
6979 7055
         private $responder;
6980 7056
         private $cache;
6981 7057
         private $ttl;
6982
-        private $debug;
6983 7058
         private $registration;
6984 7059
         private $routes;
6985 7060
         private $routeHandlers;
6986 7061
         private $middlewares;
6987 7062
 
6988
-        public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl, bool $debug)
7063
+        public function __construct(string $basePath, Responder $responder, Cache $cache, int $ttl)
6989 7064
         {
6990 7065
             $this->basePath = rtrim($this->detectBasePath($basePath), '/');
6991 7066
             $this->responder = $responder;
6992 7067
             $this->cache = $cache;
6993 7068
             $this->ttl = $ttl;
6994
-            $this->debug = $debug;
6995 7069
             $this->registration = true;
6996 7070
             $this->routes = $this->loadPathTree();
6997 7071
             $this->routeHandlers = [];
@@ -7102,23 +7176,8 @@ namespace Tqdev\PhpCrudApi\Middleware\Router {
7102 7176
             }
7103 7177
             try {
7104 7178
                 $response = call_user_func($this->routeHandlers[$routeNumbers[0]], $request);
7105
-            } catch (\PDOException $e) {
7106
-                if (strpos(strtolower($e->getMessage()), 'duplicate') !== false) {
7107
-                    $response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
7108
-                } elseif (strpos(strtolower($e->getMessage()), 'unique constraint') !== false) {
7109
-                    $response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
7110
-                } elseif (strpos(strtolower($e->getMessage()), 'default value') !== false) {
7111
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7112
-                } elseif (strpos(strtolower($e->getMessage()), 'allow nulls') !== false) {
7113
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7114
-                } elseif (strpos(strtolower($e->getMessage()), 'constraint') !== false) {
7115
-                    $response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
7116
-                } else {
7117
-                    $response = $this->responder->error(ErrorCode::ERROR_NOT_FOUND, '');
7118
-                }
7119
-                if ($this->debug) {
7120
-                    $response = ResponseUtils::addExceptionHeaders($response, $e);
7121
-                }
7179
+            } catch (\Throwable $exception) {
7180
+                $response = $this->responder->exception($exception);
7122 7181
             }
7123 7182
             return $response;
7124 7183
         }
@@ -9790,32 +9849,37 @@ namespace Tqdev\PhpCrudApi\Record\Document {
9790 9849
 
9791 9850
     class ErrorDocument implements \JsonSerializable
9792 9851
     {
9793
-        public $code;
9794
-        public $message;
9852
+        public $errorCode;
9853
+        public $argument;
9795 9854
         public $details;
9796 9855
 
9797 9856
         public function __construct(ErrorCode $errorCode, string $argument, $details)
9798 9857
         {
9799
-            $this->code = $errorCode->getCode();
9800
-            $this->message = $errorCode->getMessage($argument);
9858
+            $this->errorCode = $errorCode;
9859
+            $this->argument = $argument;
9801 9860
             $this->details = $details;
9802 9861
         }
9803 9862
 
9863
+        public function getStatus(): int
9864
+        {
9865
+            return $this->errorCode->getStatus();
9866
+        }
9867
+
9804 9868
         public function getCode(): int
9805 9869
         {
9806
-            return $this->code;
9870
+            return $this->errorCode->getCode();
9807 9871
         }
9808 9872
 
9809 9873
         public function getMessage(): string
9810 9874
         {
9811
-            return $this->message;
9875
+            return $this->errorCode->getMessage($this->argument);
9812 9876
         }
9813 9877
 
9814 9878
         public function serialize()
9815 9879
         {
9816 9880
             return [
9817
-                'code' => $this->code,
9818
-                'message' => $this->message,
9881
+                'code' => $this->getCode(),
9882
+                'message' => $this->getMessage(),
9819 9883
                 'details' => $this->details,
9820 9884
             ];
9821 9885
         }
@@ -9824,6 +9888,27 @@ namespace Tqdev\PhpCrudApi\Record\Document {
9824 9888
         {
9825 9889
             return array_filter($this->serialize());
9826 9890
         }
9891
+
9892
+        public static function fromException(\Throwable $exception)
9893
+        {
9894
+            $document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), $exception->getMessage(), null);
9895
+            if ($exception instanceof \PDOException) {
9896
+                if (strpos(strtolower($exception->getMessage()), 'duplicate') !== false) {
9897
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
9898
+                } elseif (strpos(strtolower($exception->getMessage()), 'unique constraint') !== false) {
9899
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DUPLICATE_KEY_EXCEPTION), '', null);
9900
+                } elseif (strpos(strtolower($exception->getMessage()), 'default value') !== false) {
9901
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9902
+                } elseif (strpos(strtolower($exception->getMessage()), 'allow nulls') !== false) {
9903
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9904
+                } elseif (strpos(strtolower($exception->getMessage()), 'constraint') !== false) {
9905
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::DATA_INTEGRITY_VIOLATION), '', null);
9906
+                } else {
9907
+                    $document = new ErrorDocument(new ErrorCode(ErrorCode::ERROR_NOT_FOUND), '', null);
9908
+                }
9909
+            }
9910
+            return $document;
9911
+        }
9827 9912
     }
9828 9913
 }
9829 9914
 
@@ -10349,6 +10434,21 @@ namespace Tqdev\PhpCrudApi\Record {
10349 10434
             return $this->reflection->getType($table);
10350 10435
         }
10351 10436
 
10437
+        public function beginTransaction() /*: void*/
10438
+        {
10439
+            $this->db->beginTransaction();
10440
+        }
10441
+
10442
+        public function commitTransaction() /*: void*/
10443
+        {
10444
+            $this->db->commitTransaction();
10445
+        }
10446
+
10447
+        public function rollBackTransaction() /*: void*/
10448
+        {
10449
+            $this->db->rollBackTransaction();
10450
+        }
10451
+
10352 10452
         public function create(string $tableName, /* object */ $record, array $params) /*: ?int*/
10353 10453
         {
10354 10454
             $this->sanitizeRecord($tableName, $record, '');
@@ -10773,8 +10873,8 @@ namespace Tqdev\PhpCrudApi {
10773 10873
             $prefix = sprintf('phpcrudapi-%s-', substr(md5(__FILE__), 0, 8));
10774 10874
             $cache = CacheFactory::create($config->getCacheType(), $prefix, $config->getCachePath());
10775 10875
             $reflection = new ReflectionService($db, $cache, $config->getCacheTime());
10776
-            $responder = new JsonResponder();
10777
-            $router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime(), $config->getDebug());
10876
+            $responder = new JsonResponder($config->getDebug());
10877
+            $router = new SimpleRouter($config->getBasePath(), $responder, $cache, $config->getCacheTime());
10778 10878
             foreach ($config->getMiddlewares() as $middleware => $properties) {
10779 10879
                 switch ($middleware) {
10780 10880
                     case 'sslRedirect':
@@ -11297,6 +11397,7 @@ namespace Tqdev\PhpCrudApi {
11297 11397
         const METHOD_NOT_ALLOWED = 405;
11298 11398
         const CONFLICT = 409;
11299 11399
         const UNPROCESSABLE_ENTITY = 422;
11400
+        const FAILED_DEPENDENCY = 424;
11300 11401
         const INTERNAL_SERVER_ERROR = 500;
11301 11402
 
11302 11403
         public static function fromXml(int $status, string $xml): ResponseInterface

Loading…
Cancel
Save