tmgmt_xtm-8.x-5.x-dev/src/Plugin/tmgmt/Translator/MultipleTargetLanguageConnector.php
src/Plugin/tmgmt/Translator/MultipleTargetLanguageConnector.php
<?php
namespace Drupal\tmgmt_xtm\Plugin\tmgmt\Translator;
use Drupal\Component\Serialization\Json;
use Drupal\tmgmt\Entity\Job;
use Drupal\tmgmt\Entity\Translator;
use Drupal\tmgmt_xtm\Exception\TMGMTXtmException;
use GuzzleHttp\Utils;
use SimpleXMLElement;
/**
* Class MultipleTargetLanguageConnector.
*
* Handles the connection for multiple target languages in translation jobs.
*
* @package Drupal\tmgmt_xtm\Plugin\tmgmt\Translator
*/
class MultipleTargetLanguageConnector extends Connector {
/**
* Requests translation for multiple jobs and handles the response.
*
* @param \Drupal\tmgmt\Entity\Job[] $jobs
* The array of job entities to be processed.
*
* @throws \SoapFault
* Throws if the SOAP request fails.
* @throws \Drupal\tmgmt_xtm\Exception\TMGMTXtmException
* Throws if there is an XTM-specific error.
*/
public function xtmRequestTranslation($jobs, array $jobItems = NULL) {
if (empty($jobs)) {
return;
}
/** @var \Drupal\tmgmt\Entity\Job $jobEntity */
$jobEntity = end($jobs);
$ids = array_map(static fn(Job $job) => $job->id(), $jobs);
$translator = $jobEntity->getTranslator();
$projectMTOM = $this->createOneProjectMTOM($jobs, $translator);
$callbackUrl = $this->getCallbackUrl(implode(',', $ids));
$projectMTOM['projectCallback'][$jobEntity->getSetting(self::API_PROJECT_MODE) == 2
? 'projectFinishedCallback' : 'jobFinishedCallback'] = $callbackUrl;
if ($jobEntity->getSetting(self::API_TEMPLATE_ID)) {
$projectMTOM['template'] = ['id' => $jobEntity->getSetting(self::API_TEMPLATE_ID)];
}
$input = [
'project' => $projectMTOM,
'options' => ['autopopulate' => TRUE],
];
$mtomRequestService = \Drupal::service('tmgmt_xtm.mtom_request_service');
$request = $mtomRequestService->prepareTranslationFilesRequest(
$translator,
self::CREATE_PROJECT_FOR_PMMTOM,
$input
);
try {
$response = $mtomRequestService->sendTranslationFilesRequest($request);
if ($response->getStatusCode() !== 200) {
throw new \Exception('HTTP error: ' . $response->getStatusCode() . 'for Job ID/s: ' . implode(', ' , $ids));
}
$responseBody = $response->getBody()->getContents();
if (empty($responseBody)) {
throw new \Exception('Empty response body for Job ID/s: ' . implode(', ' , $ids));
}
$xml = new SimpleXMLElement($responseBody);
// Register the namespace
$xml->registerXPathNamespace('ns1', 'http://pm.v2.webservice.projectmanagergui.xmlintl.com/');
$parsedResponse = json_decode(json_encode($xml->xpath('//ns1:createProjectForPMMTOMResponse/return')[0]));
if (isset($parsedResponse->project)) {
$this->updatedJobs($jobs, $parsedResponse);
}
} catch (\Exception $e) {
\Drupal::logger(self::XTM_LOGGER)->notice('Rejected job ID/s:' . implode(', ' , $ids) . '. ' . $e->getMessage());
$jobEntity->rejected(
'Job has been rejected with following error: @error',
['@error' => $e->getMessage()],
);
}
}
/**
* Creates a single project MTOM array for multiple jobs.
*
* @param \Drupal\tmgmt\Entity\Job[] $jobs
* The array of job entities.
* @param \Drupal\tmgmt\Entity\Translator $translator
* The translator entity.
*
* @return array
* The MTOM array for the project.
*/
private function createOneProjectMTOM($jobs, Translator $translator) {
$helper = new MultipleTargetLanguageHelper();
$targetLanguages = $jobIds = $jobItemsByTargetLanguage = [];
/** @var \Drupal\tmgmt\Entity\Job $job */
foreach ($jobs as $job) {
$jobEntity = $job;
$targetLanguage = $helper->mapLanguageToXTMFormat($jobEntity->getRemoteTargetLanguage(), $translator);;
$targetLanguages[] = $targetLanguage;
$jobIds[] = $jobEntity->id();
$jobItemsByTargetLanguage[$targetLanguage] = $jobEntity->getItems();
}
$prefix = $translator->getSetting(self::PROJECT_NAME_PREFIX);
$projectName = ($prefix ? "[$prefix] " : '') . $helper->clearLabel($job->label());
$projectData = [
'name' => $helper->cutProjectName($projectName),
'sourceLanguage' => $helper->mapLanguageToXTMFormat($jobEntity->getRemoteSourceLanguage(), $translator),
'targetLanguages' => $targetLanguages,
'translationFiles' => array_map(
static fn (array $xmlFile) => [
'fileName' => $xmlFile['fileName'],
'fileMTOM' => $xmlFile['fileMTOM'],
'targetLanguages' => $targetLanguages,
'externalDescriptors' => $xmlFile['externalDescriptors'],
'contentType' => 'application/xml',
],
($jobEntity->getSetting(self::API_PROJECT_MODE) == 0)
? $helper->createSingleXMLFile($jobs)
: $helper->createMultipleXMLFiles($jobs)
),
'referenceId' => implode(",", $jobIds),
'customer' => ['id' => $translator->getSetting(self::XTM_PROJECT_CUSTOMER_ID)],
];
/** @var \Drupal\tmgmt\Data $dataService */
$dataService = \Drupal::service('tmgmt.data');
if (method_exists($dataService, 'getTranslatableFiles')) {
foreach ($jobItemsByTargetLanguage as $targetLanguage => $jobItems) {
foreach ($jobItems as $jobItem) {
foreach ($dataService->getTranslatableFiles($jobItem->getData()) as $key => $file) {
$fileInfo = pathinfo($file->getFilename());
$filename = sprintf(
'[%s][%s][%s]%s.%s',
$jobItem->id(),
$file->id(),
$key,
$helper->clearFileName($fileInfo['filename']),
$fileInfo['extension']
);
$projectData['translationFiles'][] = [
'fileName' => $filename,
'fileMTOM' => file_get_contents($file->getFileUri()),
'targetLanguages' => [$targetLanguage],
'externalDescriptors' => [],
'contentType' => mime_content_type($file->getFileUri()),
];
}
}
}
}
return $projectData;
}
/**
* Updates job references with the project ID and saves the job entities.
*
* @param \Drupal\tmgmt\Entity\Job[] $jobs
* The array of job entities to be updated.
* @param object $response
* The response object containing the project ID.
*
* @return \Drupal\tmgmt\Entity\Job
* The last job entity processed.
*/
private function updatedJobs($jobs, $response) {
$jobEntity = NULL;
/** @var \Drupal\tmgmt\Entity\Job $job */
foreach ($jobs as $job) {
$jobEntity = $job;
$projectId = $response->project->projectDescriptor->id;
$jobEntity->reference = $projectId;
$jobEntity->save();
$jobEntity->submitted(
'The project has been successfully submitted
for translation. Project ID: @project_id.',
['@project_id' => $projectId]
);
}
return $jobEntity;
}
}
