diff --git a/config/install/tmgmt.translator.smartling.yml b/config/install/tmgmt.translator.smartling.yml index 5a144f1..10ace6f 100644 --- a/config/install/tmgmt.translator.smartling.yml +++ b/config/install/tmgmt.translator.smartling.yml @@ -13,8 +13,6 @@ settings: project_id: '' user_id: '' token_secret: '' - key: '' - orgID: '' contextUsername: '' context_silent_user_switching: false context_skip_host_verifying: false diff --git a/config/schema/tmgmt_smartling.schema.yml b/config/schema/tmgmt_smartling.schema.yml index 889ab57..cd0845f 100644 --- a/config/schema/tmgmt_smartling.schema.yml +++ b/config/schema/tmgmt_smartling.schema.yml @@ -10,9 +10,6 @@ tmgmt.translator.settings.smartling: token_secret: type: string label: 'Token Secret' - key: - type: string - label: 'Key' export_format: type: string label: Default export format @@ -31,9 +28,6 @@ tmgmt.translator.settings.smartling: scheme: type: string label: 'Schema to store translation files in' - orgID: - type: string - label: 'orgID identifier from the API page in Smartling Dashboard' contextUsername: type: string label: 'Username for context retrieval' diff --git a/modules/tmgmt_smartling_context_debug/src/Form/TmgmtSmartlingContextDebugForm.php b/modules/tmgmt_smartling_context_debug/src/Form/TmgmtSmartlingContextDebugForm.php index 8357b4e..f1e0cf9 100644 --- a/modules/tmgmt_smartling_context_debug/src/Form/TmgmtSmartlingContextDebugForm.php +++ b/modules/tmgmt_smartling_context_debug/src/Form/TmgmtSmartlingContextDebugForm.php @@ -66,8 +66,6 @@ class TmgmtSmartlingContextDebugForm extends FormBase { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { - - // \Drupal::config('tmgmt.translator.smartling')->get('settings.orgID'); $settings = \Drupal::config('tmgmt.translator.smartling')->get('settings'); $filename = $form_state->getValue('filename'); diff --git a/src/Context/ContextUploader.php b/src/Context/ContextUploader.php index 8910c34..2bc3d8f 100644 --- a/src/Context/ContextUploader.php +++ b/src/Context/ContextUploader.php @@ -4,10 +4,10 @@ namespace Drupal\tmgmt_smartling\Context; use Drupal; use Drupal\tmgmt_smartling\Exceptions\EmptyContextParameterException; -use Drupal\tmgmt_smartling\Smartling\SmartlingContextApi; use Exception; use Psr\Log\LoggerInterface; use Drupal\tmgmt_smartling\Exceptions\SmartlingBaseException; +use Smartling\Context\Params\UploadContextParameters; use Smartling\Exceptions\SmartlingApiException; class ContextUploader { @@ -82,6 +82,8 @@ class ContextUploader { * @throws EmptyContextParameterException */ public function upload($url, $filename = '', $proj_settings = []) { + $response = []; + if (empty($url)) { throw new EmptyContextParameterException('Context url must be a non-empty field.'); } @@ -89,12 +91,19 @@ class ContextUploader { try { $html = $this->getContextualizedPage($url, $proj_settings); - $response = $this->uploadContextBody($url, $html, $filename, $proj_settings); + // Save context file. + $path = $proj_settings['scheme'] . '://tmgmt_smartling_context/' . $filename . '.html'; + $dirname = dirname($path); + + if (file_prepare_directory($dirname, FILE_CREATE_DIRECTORY) && ($file = file_save_data($html, $path, FILE_EXISTS_REPLACE))) { + $response = $this->uploadContextBody($file, $proj_settings); - if (!empty($response['items'])) { - foreach($response['items'] as $resource) { - $this->uploadAsset($resource['url'], $resource['resourceId'], $proj_settings); - } + $this->logger->info('Context upload for file @filename completed successfully.', ['@filename' => $filename]); + } + else { + $this->logger->error("Can't save context file: @path", [ + '@path' => $path, + ]); } } catch (SmartlingApiException $e) { $this->logger->error($e->getMessage()); @@ -104,7 +113,7 @@ class ContextUploader { $this->logger->error($e->getMessage()); return []; } - $this->logger->info('Context upload for file @filename completed successfully.', ['@filename' => $filename]); + return $response; } @@ -121,47 +130,23 @@ class ContextUploader { } /** - * @param $url - * @param $html - * @param $filename + * @param $file + * @param $proj_settings * @return array - * @throws EmptyContextParameterException */ - protected function uploadContextBody($url, $html, $filename, $proj_settings) { - $orgId = $proj_settings['orgID']; + protected function uploadContextBody($file, $proj_settings) { $response = []; - if (empty($orgId)) { - throw new EmptyContextParameterException('OrgId is a mandatory field. Please, fill it in.'); - } - try { - $api = $this->getApi($proj_settings, 'context'); + $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager')->getViaUri($file->getFileUri()); + $params = new UploadContextParameters(); + $params->setContextFileUri($stream_wrapper_manager->realpath()); + $params->setName($file->getFileName()); - if (!empty($filename)) { - $response = $api->uploadContext(array( - 'url' => $url, - 'html' => $html, - 'fileUri' => $filename, - 'orgId' => $orgId - ), [ - 'html' => [ - 'name' => 'context.html', - 'content_type' => 'text/html' - ], - ]); - } - $response2 = $api->uploadContext(array( - 'url' => $url, - 'html' => $html, - 'orgId' => $orgId - ), ['html' => ['name' => 'context.html', 'content_type' => 'text/html']]); - - if (empty($response)) { - $response = $response2; - } - } - catch (Exception $e) { + $api = $this->getApi($proj_settings, 'context'); + $response = $api->uploadContext($params); + $response = $api->matchContext($response['contextUid']); + } catch (Exception $e) { watchdog_exception('tmgmt_smartling', $e); } @@ -169,47 +154,6 @@ class ContextUploader { } /** - * @param string $url - * @param string $resourceId - */ - protected function uploadAsset($url, $resourceId, $proj_settings) { - $orgId = $proj_settings['orgID']; - - $resource['url'] = $url; - $resource['resource'] = @file_get_contents($url); - - if ($resource['resource'] !== FALSE) { - $contet_type = get_headers($resource['url'], 1)["Content-Type"]; - //$resource['resource'] = @fopen($resource['url'], 'r');//$content; - $resource['orgId'] = $orgId; - $resource['resourceId'] = $resourceId; - - $res_fil = basename($resource['url']); - $res_fil = (strpos($res_fil, '?') === FALSE) ? $res_fil : strstr($res_fil, '?', TRUE); - - if (empty($res_fil)) { - $this->logger->warning('Asset "@url" can not be uploaded. Bad filename.', ['@url' => $resource['url']]); - return; - } - - try { - $res = $this->getApi($proj_settings, 'context')->putResource($resource, [ - 'resource' => [ - 'name' => $res_fil, - 'content_type' => $contet_type - ], - ]); - } - catch (Exception $e) { - watchdog_exception('tmgmt_smartling', $e); - } - } - else { - $this->logger->warning('File "@url" can not be downloaded. Probably it does not exist or server returned 403 status code for a given resource.', ['@url' => $resource['url']]); - } - } - - /** * @param $filename * @return bool */ diff --git a/src/Plugin/tmgmt/Translator/SmartlingTranslator.php b/src/Plugin/tmgmt/Translator/SmartlingTranslator.php index a399d1d..fde1b32 100755 --- a/src/Plugin/tmgmt/Translator/SmartlingTranslator.php +++ b/src/Plugin/tmgmt/Translator/SmartlingTranslator.php @@ -107,8 +107,7 @@ class SmartlingTranslator extends TranslatorPluginBase implements ExtendedTransl public function checkAvailable(TranslatorInterface $translator) { if ($translator->getSetting('user_id') && $translator->getSetting('token_secret') && - $translator->getSetting('project_id') && - $translator->getSetting('key') + $translator->getSetting('project_id') ) { return AvailableResult::yes(); } diff --git a/src/Smartling/SmartlingApiFactory.php b/src/Smartling/SmartlingApiFactory.php index 56d9c1e..af0387c 100644 --- a/src/Smartling/SmartlingApiFactory.php +++ b/src/Smartling/SmartlingApiFactory.php @@ -7,10 +7,10 @@ namespace Drupal\tmgmt_smartling\Smartling; -use Drupal; use Exception; use Smartling\BaseApiAbstract; use Smartling\AuthApi\AuthTokenProvider; +use Smartling\Context\ContextApi; use Smartling\Exceptions\SmartlingApiException; use Smartling\File\FileApi; use Smartling\Project\ProjectApi; @@ -52,11 +52,8 @@ class SmartlingApiFactory { break; - // TODO: for now Smartling API doesn't have Context API so we need - // to deal with it somehow.. I think we need to add Context API class - // to Smartling SDK in a future. case 'context': - $api = new SmartlingContextApi($settings['key'], $settings['project_id'], Drupal::getContainer()->get('http_client')); + $api = ContextApi::create($auth_provider, $settings['project_id']); break; diff --git a/src/Smartling/SmartlingContextApi.php b/src/Smartling/SmartlingContextApi.php deleted file mode 100644 index 5bc029e..0000000 --- a/src/Smartling/SmartlingContextApi.php +++ /dev/null @@ -1,180 +0,0 @@ -apiKey = $apiKey; - $this->projectId = $projectId; - $this->httpClient = $http_client; - $this->baseUrl = rtrim($base_service_url ?: self::DEFAULT_SERVICE_URL , '/'); - } - - /** - * Sends request to Smartling Service via Guzzle Client. - * - * @param string $uri - * Resource uri. - * @param array $requestData - * Parameters to be send as query or multipart form elements. - * @param string $method - * Http method uppercased. - * - * @param array $filenames - * @return array Decoded JSON answer. - * Decoded JSON answer. - * @throws \Smartling\Exceptions\SmartlingApiException - */ - protected function sendRequest($uri, $requestData, $method, $filenames = []) - { - // Set api key and product id as required arguments. - $requestData['apiKey'] = $this->apiKey; - $requestData['projectId'] = $this->projectId; - - // Ask for JSON and disable Guzzle exceptions. - $options = [ - 'headers' => [ - 'Accept' => 'application/json', - ], - 'http_errors' => FALSE, - ]; - - // For GET and DELETE http methods use just query parameter builder. - if (in_array($method, ['GET', 'DELETE'])) { - $options['query'] = $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']); - } - foreach ($requestData as $key => $value) { - // Hack to cast FALSE to '0' instead of empty string. - if (is_bool($value)) { - $value = (int)$value; - } - - $val = [ - 'name' => $key, - // Typecast everything to string to avoid curl notices. - 'contents' => (string) $value, - ]; - if (isset($filenames[$key])) { - $val['filename'] = $filenames[$key]['name']; - $val['Content-Type'] = $filenames[$key]['content_type']; - } - - $options['multipart'][] = $val; - } - } - - // Avoid double slashes in final URL. - $uri = ltrim($uri, "/"); - - $guzzle_response = $this->httpClient->request($method, $this->baseUrl . '/' . $uri, $options); - $response_body = (string) $guzzle_response->getBody(); - - // Catch all errors from Smartling and throw appropriate exception. - if ($guzzle_response->getStatusCode() >= 400) { - $error_response = json_decode($response_body, TRUE); - - $error_messages = []; - if (!empty($error_response['response']['errors'])) { - $error_messages = $error_response['response']['errors']; - } elseif (!empty($error_response['response']['messages'])) { - $error_messages = $error_response['response']['messages']; - } - if (!$error_response || empty($error_messages)) { - throw new SmartlingApiException('Bad response format from Smartling'); - } - - throw new SmartlingApiException(print_r($error_messages, TRUE), $guzzle_response->getStatusCode()); - } - - // "Download file" method return translated file directly. - if ('file/get' == $uri) { - return $response_body; - } - $response = json_decode($response_body, TRUE); - // Throw exception if json is not valid. - if (!$response || !isset($response['response']['data'])) { - throw new SmartlingApiException('Bad response format from Smartling'); - } - - return $response['response']['data']; - } - - /** - * upload context to Smartling - * - * @param array $data - * @return string - */ - public function uploadContext($data, $filenames) - { - $orgID = $data['orgId']; - unset($data['orgId']); - - return $this->sendRequest('js/' . $orgID . '/html', $data, 'POST', $filenames); - } - - public function putResource($data, $filenames) { - $orgID = $data['orgId']; - unset($data['orgId']); - - return $this->sendRequest('js/projects/' . $orgID . '/resources/' . $data['resourceId'], $data, 'PUT', $filenames); - } - -} diff --git a/src/SmartlingTranslatorUi.php b/src/SmartlingTranslatorUi.php index 43216d9..226c344 100755 --- a/src/SmartlingTranslatorUi.php +++ b/src/SmartlingTranslatorUi.php @@ -31,7 +31,7 @@ class SmartlingTranslatorUi extends TranslatorPluginUiBase { '#type' => 'textfield', '#title' => t('Project Id'), '#default_value' => $translator->getSetting('project_id'), - '#size' => 25, + '#size' => 63, '#maxlength' => 25, '#required' => TRUE, ]; @@ -40,7 +40,7 @@ class SmartlingTranslatorUi extends TranslatorPluginUiBase { '#type' => 'textfield', '#title' => t('User Id'), '#default_value' => $translator->getSetting('user_id'), - '#size' => 30, + '#size' => 63, '#maxlength' => 40, '#required' => TRUE, ]; @@ -49,33 +49,15 @@ class SmartlingTranslatorUi extends TranslatorPluginUiBase { '#type' => 'textfield', '#title' => t('Token Secret'), '#default_value' => $translator->getSetting('token_secret'), - '#size' => 55, + '#size' => 63, '#maxlength' => 65, '#required' => TRUE, ]; - $form['key'] = [ - '#type' => 'textfield', - '#title' => t('Key'), - '#default_value' => $translator->getSetting('key'), - '#size' => 40, - '#maxlength' => 40, - '#required' => TRUE, - ]; - - $form['orgID'] = [ - '#type' => 'textfield', - '#title' => t('orgID'), - '#size' => 40, - '#maxlength' => 40, - '#default_value' => $translator->getSetting('orgID'), - '#required' => FALSE, - ]; - $form['contextUsername'] = [ '#type' => 'textfield', '#title' => t('Username for context retrieval'), - '#size' => 40, + '#size' => 63, '#maxlength' => 40, '#default_value' => $translator->getSetting('contextUsername'), '#required' => FALSE, @@ -146,7 +128,7 @@ class SmartlingTranslatorUi extends TranslatorPluginUiBase { '#type' => 'textfield', '#title' => t('Custom placeholder (regular expression)'), '#description' => t('The content matching this regular expression will not be editable by translators in Smartling.'), - '#size' => 40, + '#size' => 63, '#maxlength' => 80, '#default_value' => $translator->getSetting('custom_regexp_placeholder'), '#required' => FALSE, diff --git a/src/Tests/SmartlingTest.php b/src/Tests/SmartlingTest.php index 96980c0..67059cd 100644 --- a/src/Tests/SmartlingTest.php +++ b/src/Tests/SmartlingTest.php @@ -134,10 +134,8 @@ class SmartlingTest extends TMGMTTestBase { 'auto_accept' => $providerSettings['auto_accept'], 'settings' => [ 'project_id' => $providerSettings['settings[project_id]'], - 'key' => $providerSettings['settings[key]'], 'user_id' => $providerSettings['settings[user_id]'], 'token_secret' => $providerSettings['settings[token_secret]'], - 'orgID' => $providerSettings['settings[orgID]'], 'contextUsername' => $providerSettings['settings[contextUsername]'], 'context_silent_user_switching' => $providerSettings['settings[context_silent_user_switching]'], 'retrieval_type' => $providerSettings['settings[retrieval_type]'], diff --git a/tmgmt_smartling.simpletest.settings.php b/tmgmt_smartling.simpletest.settings.php index 561cbae..2dfc2ec 100644 --- a/tmgmt_smartling.simpletest.settings.php +++ b/tmgmt_smartling.simpletest.settings.php @@ -7,10 +7,8 @@ $settings = [ 'auto_accept' => TRUE, 'settings[project_id]' => 'PROJECT_ID', - 'settings[key]' => 'API_KEY', 'settings[user_id]' => 'USER_ID', 'settings[token_secret]' => 'TOKEN_SECRET', - 'settings[orgID]' => 'ORG_ID', 'settings[contextUsername]' => 'DRUPAL_ADMIN_USER_NAME', 'settings[context_silent_user_switching]' => FALSE, 'settings[context_skip_host_verifying]' => FALSE,