From 95b720fd5dd019383e3f16ffc67d0bfc84b54d8f Mon Sep 17 00:00:00 2001 From: Konstantin Date: Wed, 6 Jan 2016 17:30:59 +0200 Subject: [PATCH] 1. Refactored BaseApi class to avoid breakign of incapsulation. 2. Added support to AuthTokenProvider to cache access tokens #36 #37 --- src/AuthApi/AuthTokenProvider.php | 78 ++++++++++++++++++++-- src/BaseApiAbstract.php | 103 +++++++++++++++++++----------- src/File/FileApi.php | 22 +++---- src/Helpers/HttpVerbHelper.php | 18 ------ src/Project/ProjectApi.php | 3 +- 5 files changed, 148 insertions(+), 76 deletions(-) delete mode 100755 src/Helpers/HttpVerbHelper.php diff --git a/src/AuthApi/AuthTokenProvider.php b/src/AuthApi/AuthTokenProvider.php index 0461642..d0371c9 100755 --- a/src/AuthApi/AuthTokenProvider.php +++ b/src/AuthApi/AuthTokenProvider.php @@ -5,13 +5,14 @@ use GuzzleHttp\ClientInterface; use Psr\Log\LoggerInterface; use Smartling\BaseApiAbstract; -use Smartling\Helpers\HttpVerbHelper; class AuthTokenProvider extends BaseApiAbstract implements AuthApiInterface { const ENDPOINT_URL = 'https://api.smartling.com/auth-api/v2/'; + const TIME_TO_RESFRESH = 2; + /** * @var string */ @@ -27,6 +28,11 @@ class AuthTokenProvider extends BaseApiAbstract implements AuthApiInterface */ private $data; + /** + * @var int + */ + private $requestTime = 0; + /** * @return string */ @@ -86,7 +92,6 @@ public function __construct($userIdentifier, $secretKey, ClientInterface $client */ public static function create($userIdentifier, $secretKey, $logger = null) { - $client = self::initializeHttpClient(self::ENDPOINT_URL); return new self($userIdentifier, $secretKey, $client, $logger); @@ -98,7 +103,19 @@ public static function create($userIdentifier, $secretKey, $logger = null) */ public function getAccessToken() { - $this->data = $this->sendRequest('authenticate', [], HttpVerbHelper::HTTP_VERB_POST); + if ($this->isValidToken()) + { + return $this->data['accessToken']; + } + + if ($this->isValidRefreshToken()) + { + $this->data = $this->refreshToken(); + } + else + { + $this->data = $this->authenticate(); + } return $this->data['accessToken']; } @@ -111,6 +128,21 @@ public function getTokenType() return isset($this->data['tokenType']) ? $this->data['tokenType'] : ''; } + public function getRefreshToken() + { + return isset($this->data['refreshToken']) ? $this->data['refreshToken'] : ''; + } + + private function isValidToken() + { + return isset($this->data['expiresIn']) ? time() + self::TIME_TO_RESFRESH < $this->requestTime + $this->data['expiresIn'] : FALSE; + } + + private function isValidRefreshToken() + { + return isset($this->data['refreshExpiresIn']) ? time() + self::TIME_TO_RESFRESH < $this->requestTime + $this->data['refreshExpiresIn'] : FALSE; + } + /** * @inheritdoc */ @@ -119,11 +151,47 @@ public function resetToken() $this->data = []; } - protected function sendRequest($uri, array $requestData, $method) + /** + * @inheritdoc + */ + protected function prepareHeaders($doProcessResponseBody, $httpErrors = false) { + $options = [ + 'headers' => [ + 'Accept' => 'application/json', + ], + 'http_errors' => $httpErrors, + ]; + + return $options; + } + + /** + * @inheritdoc + */ + protected function mergeRequestData($options, $requestData, $method = self::HTTP_METHOD_GET) + { + $options['json'] = $requestData; + return $options; + } + + + protected function authenticate() { + $requestData = []; $requestData['userIdentifier'] = $this->getUserIdentifier(); $requestData['userSecret'] = $this->getSecretKey(); - return parent::sendRequest($uri, $requestData, $method, self::STRATEGY_AUTH); + $this->requestTime = time(); + + return $this->sendRequest('authenticate', $requestData, self::HTTP_METHOD_POST); + } + + protected function refreshToken() + { + $requestData['refreshToken'] = $this->getRefreshToken(); + + $this->requestTime = time(); + + return $this->sendRequest('authenticate/refresh', $requestData, self::HTTP_METHOD_POST); } } diff --git a/src/BaseApiAbstract.php b/src/BaseApiAbstract.php index b241dac..c797679 100755 --- a/src/BaseApiAbstract.php +++ b/src/BaseApiAbstract.php @@ -7,7 +7,6 @@ use Psr\Log\LoggerInterface; use Smartling\AuthApi\AuthApiInterface; use Smartling\Exceptions\SmartlingApiException; -use Smartling\Helpers\HttpVerbHelper; use Smartling\Logger\DevNullLogger; /** @@ -17,12 +16,9 @@ */ abstract class BaseApiAbstract { - - const STRATEGY_GENERAL = 'general'; - - const STRATEGY_DOWNLOAD = 'download'; - - const STRATEGY_AUTH = 'auth'; + const HTTP_METHOD_GET = 'GET'; + const HTTP_METHOD_POST = 'POST'; + const HTTP_METHOD_DELETE = 'DELETE'; /** @@ -201,12 +197,12 @@ protected function readFile($realPath) } /** - * @param string $strategy + * @param bool $doProcessResponseBody * @param bool $httpErrors * * @return array */ - private function prepareOptions($strategy, $httpErrors = false) + protected function prepareHeaders($doProcessResponseBody, $httpErrors = false) { $options = [ 'headers' => [ @@ -215,14 +211,13 @@ private function prepareOptions($strategy, $httpErrors = false) 'http_errors' => $httpErrors, ]; - if (self::STRATEGY_AUTH !== $strategy) { - $accessToken = $this->getAuth()->getAccessToken(); - $tokenType = $this->getAuth()->getTokenType(); - $options['headers']['Authorization'] = - vsprintf(' %s %s', [$tokenType, $accessToken]); - } - if (self::STRATEGY_DOWNLOAD === $strategy) { + $accessToken = $this->getAuth()->getAccessToken(); + $tokenType = $this->getAuth()->getTokenType(); + $options['headers']['Authorization'] = + vsprintf(' %s %s', [$tokenType, $accessToken]); + + if (!$doProcessResponseBody) { unset($options['headers']['Accept']); } @@ -332,43 +327,73 @@ function ($a) { } } - /** - * @param string $uri + * @param array $options * @param array $requestData * @param string $method - * @param string $strategy * - * @return bool true on SUCCESS and empty data - * string on $processResponseBody = false - * array otherwise - * @throws SmartlingApiException + * @return array */ - protected function sendRequest($uri, array $requestData, $method, $strategy = self::STRATEGY_GENERAL) + protected function mergeRequestData($options, $requestData, $method = self::HTTP_METHOD_GET) { + if (in_array($method, [self::HTTP_METHOD_GET, self::HTTP_METHOD_DELETE])) { + $options['query'] = $requestData; + return $options; + } - $options = $this->prepareOptions($strategy); + $options['multipart'] = []; - if (in_array($method, [HttpVerbHelper::HTTP_VERB_GET, HttpVerbHelper::HTTP_VERB_DELETE])) { - $options['query'] = $requestData; - } else { - if (self::STRATEGY_AUTH === $strategy) { - $options['json'] = $requestData; - } else { - $options['multipart'] = []; + // Remove file from params array and add it as a stream. + if (!empty($requestData['file'])) { + $options['multipart'][] = [ + 'name' => 'file', + 'contents' => $this->readFile($requestData['file']), + ]; + unset($requestData['file']); + } + + //$options = $this->addRequestDataToOptions($options, $requestData); + foreach ($requestData as $key => $value) { + // Hack to cast FALSE to '0' instead of empty string. + if (is_bool($value)) { + $value = (int)$value; + } - // Remove file from params array and add it as a stream. - if (!empty($requestData['file'])) { + if (is_array($value)) { + foreach ($value as $_item) { $options['multipart'][] = [ - 'name' => 'file', - 'contents' => $this->readFile($requestData['file']), + 'name' => $key . '[]', + 'contents' => (string)$_item, ]; - unset($requestData['file']); } - $options = $this->addRequestDataToOptions($options, $requestData); + } else { + $options['multipart'][] = [ + 'name' => $key, + 'contents' => (string)$value, + ]; } } + return $options; + } + + /** + * @param string $uri + * @param array $requestData + * @param string $method + * @param bool $doProcessResponseBody + * + * @return bool true on SUCCESS and empty data + * string on $doProcessResponseBody = false + * array otherwise + * @throws SmartlingApiException + */ + protected function sendRequest($uri, array $requestData, $method, $doProcessResponseBody = TRUE) + { + + $options = $this->prepareHeaders($doProcessResponseBody); + $options = $this->mergeRequestData($options, $requestData, $method); + $endpoint = $this->normalizeUri($uri); $guzzleResponse = $this->getHttpClient()->request($method, $endpoint, $options); @@ -399,7 +424,7 @@ protected function sendRequest($uri, array $requestData, $method, $strategy = se $this->processErrors($responseStatusCode, $responseBody); } - if (self::STRATEGY_DOWNLOAD === $strategy) { + if (!$doProcessResponseBody) { return $responseBody; } else { $response = json_decode($responseBody, true); diff --git a/src/File/FileApi.php b/src/File/FileApi.php index 743d0d2..6fe6bf5 100755 --- a/src/File/FileApi.php +++ b/src/File/FileApi.php @@ -10,7 +10,6 @@ use Smartling\File\Params\ListFilesParameters; use Smartling\File\Params\ParameterInterface; use Smartling\File\Params\UploadFileParameters; -use Smartling\Helpers\HttpVerbHelper; /** @@ -80,7 +79,7 @@ public function uploadFile($realPath, $file_name, $file_type, UploadFileParamete $params['fileUri'] = $file_name; $params['fileType'] = $file_type; - return $this->sendRequest('file', $params, HttpVerbHelper::HTTP_VERB_POST); + return $this->sendRequest('file', $params, self::HTTP_METHOD_POST); } /** @@ -118,8 +117,7 @@ public function downloadFile($fileUri, $locale = '', DownloadFileParameters $par $params = (is_null($params)) ? [] : $params->exportToArray(); $params['fileUri'] = $fileUri; - return $this->sendRequest("locales/{$locale}/file", $params, HttpVerbHelper::HTTP_VERB_GET, - self::STRATEGY_DOWNLOAD); + return $this->sendRequest("locales/{$locale}/file", $params, self::HTTP_METHOD_GET, FALSE); } /** @@ -142,7 +140,7 @@ public function getStatus($fileUri, $locale, ParameterInterface $params = null) $params = (is_null($params)) ? [] : $params->exportToArray(); $params['fileUri'] = $fileUri; - return $this->sendRequest("locales/$locale/file/status", $params, HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest("locales/$locale/file/status", $params, self::HTTP_METHOD_GET); } /** @@ -179,7 +177,7 @@ public function getList(ListFilesParameters $params = null) { $params = (is_null($params)) ? [] : $params->exportToArray(); - return $this->sendRequest('files/list', $params, HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest('files/list', $params, self::HTTP_METHOD_GET); } /** @@ -206,7 +204,7 @@ public function renameFile($fileUri, $newFileUri, ParameterInterface $params = n $params['fileUri'] = $fileUri; $params['newFileUri'] = $newFileUri; - return $this->sendRequest('file/rename', $params, HttpVerbHelper::HTTP_VERB_POST); + return $this->sendRequest('file/rename', $params, self::HTTP_METHOD_POST); } /** @@ -230,7 +228,7 @@ public function deleteFile($fileUri, ParameterInterface $params = null) $params['fileUri'] = $fileUri; - return $this->sendRequest('file/delete', $params, HttpVerbHelper::HTTP_VERB_POST); + return $this->sendRequest('file/delete', $params, self::HTTP_METHOD_POST); } /** @@ -271,7 +269,7 @@ public function import($locale, $fileUri, $fileType, $fileRealPath, $translation $params['translationState'] = $translationState; $params['overwrite'] = $overwrite; - return $this->sendRequest("/locales/$locale/file/import", $params, HttpVerbHelper::HTTP_VERB_POST); + return $this->sendRequest("/locales/$locale/file/import", $params, self::HTTP_METHOD_POST); } /** @@ -289,7 +287,7 @@ public function getAuthorizedLocales($fileUri, ParameterInterface $params = null $params['fileUri'] = $fileUri; - return $this->sendRequest('file/authorized-locales', $params, HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest('file/authorized-locales', $params, self::HTTP_METHOD_GET); } /** @@ -307,7 +305,7 @@ public function getStatusAllLocales($fileUri, ParameterInterface $params = null) $params['fileUri'] = $fileUri; - return $this->sendRequest('file/status', $params, HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest('file/status', $params, self::HTTP_METHOD_GET); } @@ -326,6 +324,6 @@ public function getLastModified($fileUri, ParameterInterface $params = null) $params['fileUri'] = $fileUri; - return $this->sendRequest('file/last-modified', $params, HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest('file/last-modified', $params, self::HTTP_METHOD_GET); } } \ No newline at end of file diff --git a/src/Helpers/HttpVerbHelper.php b/src/Helpers/HttpVerbHelper.php deleted file mode 100755 index 048de72..0000000 --- a/src/Helpers/HttpVerbHelper.php +++ /dev/null @@ -1,18 +0,0 @@ -sendRequest('', [], HttpVerbHelper::HTTP_VERB_GET); + return $this->sendRequest('', [], self::HTTP_METHOD_GET); } } \ No newline at end of file