From 34ce76b4a6f117c1b9c348fd7bfa134104a65b0c Mon Sep 17 00:00:00 2001 From: max-baranikov Date: Fri, 15 Oct 2021 11:20:18 +0300 Subject: [PATCH] Added exceptions handling for proxy --- retailcrm/lib/RetailcrmOrderBuilder.php | 16 +++- retailcrm/lib/api/RetailcrmApiClientV5.php | 55 +------------ retailcrm/lib/api/RetailcrmProxy.php | 24 +++--- .../RetailcrmExceptionMiddleware.php | 61 ++++++++++++++ .../middleware/RetailcrmLoggerMiddleware.php | 54 +++++++++++-- .../pipeline/RetailcrmMiddlewareInterface.php | 2 +- .../lib/api/pipeline/RetailcrmPipeline.php | 2 +- .../api/RetailcrmExceptionMiddlewareTest.php | 79 +++++++++++++++++++ 8 files changed, 218 insertions(+), 75 deletions(-) create mode 100644 retailcrm/lib/api/middleware/RetailcrmExceptionMiddleware.php create mode 100644 tests/lib/api/RetailcrmExceptionMiddlewareTest.php diff --git a/retailcrm/lib/RetailcrmOrderBuilder.php b/retailcrm/lib/RetailcrmOrderBuilder.php index 8b634dd..3aa1f77 100644 --- a/retailcrm/lib/RetailcrmOrderBuilder.php +++ b/retailcrm/lib/RetailcrmOrderBuilder.php @@ -190,10 +190,22 @@ class RetailcrmOrderBuilder protected function getApiSite() { if (empty($this->apiSite)) { - $this->apiSite = $this->api->getSingleSiteForKey(); + $response = $this->api->credentials(); + + if ( + $response->isSuccessful() + && $response->offsetExists('sitesAvailable') + && is_array($response['sitesAvailable']) + && !empty($response['sitesAvailable']) + && !empty($response['sitesAvailable'][0]) + ) { + $this->apiSite = $response['sitesAvailable'][0]; + } else { + $this->apiSite = null; + } } - return (empty($this->apiSite) || is_bool($this->apiSite)) ? null : $this->apiSite; + return $this->apiSite; } /** diff --git a/retailcrm/lib/api/RetailcrmApiClientV5.php b/retailcrm/lib/api/RetailcrmApiClientV5.php index a7906d6..eb67088 100644 --- a/retailcrm/lib/api/RetailcrmApiClientV5.php +++ b/retailcrm/lib/api/RetailcrmApiClientV5.php @@ -79,43 +79,14 @@ class RetailcrmApiClientV5 $this->siteCode = $site; } - /** - * getSingleSiteForKey - * - * @return string|bool - */ - public function getSingleSiteForKey() - { - $response = $this->credentials(); - - if ($response instanceof RetailcrmApiResponse - && isset($response['sitesAvailable']) - && is_array($response['sitesAvailable']) - && !empty($response['sitesAvailable']) - ) { - return $response['sitesAvailable'][0]; - } - - return false; - } - /** * /api/credentials response * - * @return RetailcrmApiResponse|bool + * @return RetailcrmApiResponse */ public function credentials() { - $response = $this->unversionedClient->makeRequest( - '/credentials', - RetailcrmHttpClient::METHOD_GET - ); - - if ($response instanceof RetailcrmApiResponse) { - return $response; - } - - return false; + return $this->unversionedClient->makeRequest('/credentials', RetailcrmHttpClient::METHOD_GET); } /** @@ -3003,28 +2974,6 @@ class RetailcrmApiClientV5 ); } - /** - * Return current site - * - * @return string - */ - public function getSite() - { - return $this->siteCode; - } - - /** - * Set site - * - * @param string $site site code - * - * @return void - */ - public function setSite($site) - { - $this->siteCode = $site; - } - /** * Check ID parameter * diff --git a/retailcrm/lib/api/RetailcrmProxy.php b/retailcrm/lib/api/RetailcrmProxy.php index 45db804..6c3116b 100755 --- a/retailcrm/lib/api/RetailcrmProxy.php +++ b/retailcrm/lib/api/RetailcrmProxy.php @@ -1,4 +1,6 @@ pipeline ->setMiddlewares( RetailcrmTools::filter( - 'RetailcrmFilterMiddlewares', - [ - RetailcrmLoggerMiddleware::class, - ]) + 'RetailcrmFilterMiddlewares', + [ + RetailcrmExceptionMiddleware::class, + RetailcrmLoggerMiddleware::class, + ] + ) ) ->setAction(function ($request) { return call_user_func_array([$this->client, $request->getMethod()], $request->getData()); }) - ->build() - ; + ->build(); } public function __call($method, $arguments) { $request = new RetailcrmApiRequest(); - $request->setApi($this->client); - $request->setMethod($method); - $request->setData($arguments); - $response = $this->pipeline->run($request); + $request->setApi($this->client) + ->setMethod($method) + ->setData($arguments); - return $response; + return $this->pipeline->run($request); } } diff --git a/retailcrm/lib/api/middleware/RetailcrmExceptionMiddleware.php b/retailcrm/lib/api/middleware/RetailcrmExceptionMiddleware.php new file mode 100644 index 0000000..7899e02 --- /dev/null +++ b/retailcrm/lib/api/middleware/RetailcrmExceptionMiddleware.php @@ -0,0 +1,61 @@ + + * @copyright 2021 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License + * + * Don't forget to prefix your containers with your own identifier + * to avoid any conflicts with others containers. + */ + + +class RetailcrmExceptionMiddleware implements RetailcrmMiddlewareInterface +{ + /** + * @inheritDoc + */ + public function __invoke(RetailcrmApiRequest $request, callable $next = null) + { + try { + $response = $next($request); + } catch (Exception $e) { + RetailcrmLogger::writeCaller($request->getMethod(), $e->getMessage()); + RetailcrmLogger::writeNoCaller($e->getTraceAsString()); + + $response = new RetailcrmApiResponse(500, json_encode([ + 'success' => false, + 'errorMsg' => sprintf('Internal error: %s', $e->getMessage()) + ])); + } + + return $response; + } +} diff --git a/retailcrm/lib/api/middleware/RetailcrmLoggerMiddleware.php b/retailcrm/lib/api/middleware/RetailcrmLoggerMiddleware.php index a03e630..39b5533 100644 --- a/retailcrm/lib/api/middleware/RetailcrmLoggerMiddleware.php +++ b/retailcrm/lib/api/middleware/RetailcrmLoggerMiddleware.php @@ -1,19 +1,57 @@ + * @copyright 2021 DIGITAL RETAIL TECHNOLOGIES SL + * @license https://opensource.org/licenses/MIT The MIT License + * + * Don't forget to prefix your containers with your own identifier + * to avoid any conflicts with others containers. + */ + + class RetailcrmLoggerMiddleware implements RetailcrmMiddlewareInterface { /** - * @param RetailcrmApiRequest $request - * @param callable|null $next - * @return RetailcrmApiResponse + * @inheritDoc */ public function __invoke(RetailcrmApiRequest $request, callable $next = null) { $method = $request->getMethod(); - if (!is_null($request->getMethod())) { + if (!is_null($method)) { RetailcrmLogger::writeDebug($method, print_r($request->getData(), true)); } + + /** @var RetailcrmApiResponse $response */ $response = $next($request); if ($response->isSuccessful()) { @@ -24,9 +62,11 @@ class RetailcrmLoggerMiddleware implements RetailcrmMiddlewareInterface RetailcrmLogger::writeDebug($method, $response->getRawResponse()); } } else { - RetailcrmLogger::writeCaller($method, $response->getErrorMsg()); + if ($response->offsetExists('errorMsg')) { + RetailcrmLogger::writeCaller($method, $response['errorMsg']); + } - if (isset($response['errors'])) { + if ($response->offsetExists('errors')) { RetailcrmApiErrors::set($response['errors'], $response->getStatusCode()); $error = RetailcrmLogger::reduceErrors($response['errors']); RetailcrmLogger::writeNoCaller($error); @@ -35,4 +75,4 @@ class RetailcrmLoggerMiddleware implements RetailcrmMiddlewareInterface return $response; } -} \ No newline at end of file +} diff --git a/retailcrm/lib/api/pipeline/RetailcrmMiddlewareInterface.php b/retailcrm/lib/api/pipeline/RetailcrmMiddlewareInterface.php index 229fda5..1521b29 100644 --- a/retailcrm/lib/api/pipeline/RetailcrmMiddlewareInterface.php +++ b/retailcrm/lib/api/pipeline/RetailcrmMiddlewareInterface.php @@ -8,4 +8,4 @@ interface RetailcrmMiddlewareInterface * @return RetailcrmApiResponse */ public function __invoke(RetailcrmApiRequest $request, callable $next = null); -} \ No newline at end of file +} diff --git a/retailcrm/lib/api/pipeline/RetailcrmPipeline.php b/retailcrm/lib/api/pipeline/RetailcrmPipeline.php index 7e22279..9ee77b6 100644 --- a/retailcrm/lib/api/pipeline/RetailcrmPipeline.php +++ b/retailcrm/lib/api/pipeline/RetailcrmPipeline.php @@ -69,4 +69,4 @@ class RetailcrmPipeline }; }; } -} \ No newline at end of file +} diff --git a/tests/lib/api/RetailcrmExceptionMiddlewareTest.php b/tests/lib/api/RetailcrmExceptionMiddlewareTest.php new file mode 100644 index 0000000..1238693 --- /dev/null +++ b/tests/lib/api/RetailcrmExceptionMiddlewareTest.php @@ -0,0 +1,79 @@ +api = RetailcrmTools::getApiClient(); + } + + public function getRequests() + { + return [ + [ + 'method' => 'ordersGet', + 'params' => [406, 'idd'], + 'errorMsg' => 'Value "idd" for "by" param is not valid. Allowed values are externalId, id.' + ], + [ + 'method' => 'ordersEdit', + 'params' => [['id' => 406], 'idd'], + 'errorMsg' => 'Value "idd" for "by" param is not valid. Allowed values are externalId, id.' + ], + [ + 'method' => 'ordersEdit', + 'params' => [['id' => 406], 'externalId'], + 'errorMsg' => 'Order array must contain the "externalId" parameter.' + ], + [ + 'method' => 'ordersFixExternalIds', + 'params' => [[]], + 'errorMsg' => 'Method parameter must contains at least one IDs pair' + ], + [ + 'method' => 'ordersCreate', + 'params' => [[]], + 'errorMsg' => 'Parameter `order` must contains a data' + ], + [ + 'method' => 'ordersUpload', + 'params' => [[]], + 'errorMsg' => 'Parameter `orders` must contains array of the orders' + ], + [ + 'method' => 'ordersPaymentCreate', + 'params' => [[]], + 'errorMsg' => 'Parameter `payment` must contains a data' + ], + [ + 'method' => 'ordersPaymentEdit', + 'params' => [['id' => 406], 'idd'], + 'errorMsg' => 'Value "idd" for "by" param is not valid. Allowed values are externalId, id.' + ], + [ + 'method' => 'ordersPaymentEdit', + 'params' => [['id' => 406], 'externalId'], + 'errorMsg' => 'Order array must contain the "externalId" parameter.' + ], + ]; + } + + /** + * @dataProvider getRequests + */ + public function testRequest($method, $params, $errorMsg) + { + /** @var RetailcrmApiResponse $response */ + $response = call_user_func_array([$this->api, $method], $params); + + $this->assertInstanceOf(RetailcrmApiResponse::class, $response); + $this->assertFalse($response->isSuccessful()); + $this->assertStringStartsWith('Internal error: ', $response['errorMsg']); + $this->assertStringEndsWith($errorMsg, $response['errorMsg']); + } +}