From cc2cc6a2fda63e8727defee9742ce9ea30d79a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D0=B0=D0=B2=D0=B5=D0=BB?= Date: Mon, 5 Oct 2020 10:23:10 +0300 Subject: [PATCH] component for product schema retrieving and refreshing --- .../Storage/ProductSchemaStorage.php | 112 +++++++++++++++++- 1 file changed, 110 insertions(+), 2 deletions(-) diff --git a/src/Component/Storage/ProductSchemaStorage.php b/src/Component/Storage/ProductSchemaStorage.php index 1817a97..c1853ae 100644 --- a/src/Component/Storage/ProductSchemaStorage.php +++ b/src/Component/Storage/ProductSchemaStorage.php @@ -12,8 +12,17 @@ namespace RetailCrm\Component\Storage; +use JsonException; +use Cache\Adapter\Common\CacheItem; use Psr\Cache\CacheItemPoolInterface; +use Psr\Cache\InvalidArgumentException; +use RetailCrm\Component\Exception\FactoryException; +use RetailCrm\Component\Exception\TopApiException; +use RetailCrm\Component\Exception\TopClientException; +use RetailCrm\Component\Exception\ValidationException; use RetailCrm\Interfaces\TopClientInterface; +use RetailCrm\Model\Request\AliExpress\SolutionProductSchemaGet; +use RetailCrm\Model\Response\ErrorResponseBody; /** * Class ProductSchemaStorage @@ -48,12 +57,111 @@ class ProductSchemaStorage /** * Returns product schema (updates it automatically if it's TTL has expired) * + * @param int $categoryId * @param int $ttl in seconds * * @return string + * @throws \RetailCrm\Component\Exception\TopClientException + * @throws \RetailCrm\Component\Exception\TopApiException */ - public function getProductSchema(int $ttl = 86400): string + public function getProductSchema(int $categoryId, int $ttl = 86400): string { - // TODO: Implement product schema fetching and refreshing. + $cacheId = self::getCacheItemId($categoryId); + $item = $this->getFromCache($cacheId); + + if (!empty($item) && null === self::validateJson($item)) { + return $item; + } + + $request = new SolutionProductSchemaGet(); + $request->aliexpressCategoryId = $categoryId; + + try { + /** @var \RetailCrm\Model\Response\AliExpress\SolutionProductSchemaGetResponse $response */ + $response = $this->client->sendAuthenticatedRequest($request); + } catch (FactoryException | TopApiException | TopClientException | ValidationException $exception) { + throw new TopClientException('Failed to obtain product schema', 0, $exception); + } + + if ($response->responseData->result->success && !empty($response->responseData->result->schema)) { + $error = self::validateJson($response->responseData->result->schema); + + if (null !== $error) { + throw new TopClientException('Failed to obtain product schema', 0, $error); + } + + $this->saveToCache($cacheId, $response->responseData->result->schema); + + return $response->responseData->result->schema; + } + + $error = new ErrorResponseBody(); + $error->msg = $response->responseData->result->errorMessage; + $error->code = (int) $response->responseData->result->errorCode; + + throw new TopApiException($error, $response->requestId); + } + + /** + * @param string $cacheId + * + * @return string + */ + private function getFromCache(string $cacheId): string + { + try { + if ($this->cache->hasItem($cacheId)) { + $item = $this->cache->getItem($cacheId)->get(); + + if (!is_string($item) || empty($item)) { + return ''; + } + + return $item; + } + } catch (InvalidArgumentException $e) { + } + + return ''; + } + + /** + * @param string $cacheId + * @param string $contents + * + * @return bool + */ + private function saveToCache(string $cacheId, string $contents): bool + { + $item = new CacheItem($cacheId, false, $contents); + $item->expiresAfter(86400); + + return $this->cache->save($item); + } + + /** + * @param string $json + * + * @return \JsonException|null + */ + private static function validateJson(string $json): ?JsonException + { + try { + json_decode($json, false, 512, JSON_THROW_ON_ERROR); + } catch (JsonException $exception) { + return $exception; + } + + return null; + } + + /** + * @param int $categoryId + * + * @return string + */ + private static function getCacheItemId(int $categoryId): string + { + return sprintf('aliexpressProductSchemaEntry_%d', $categoryId); } }