tmgmt_xtm-8.x-5.x-dev/src/Plugin/tmgmt/Translator/XtmTranslator.php

src/Plugin/tmgmt/Translator/XtmTranslator.php
<?php

namespace Drupal\tmgmt_xtm\Plugin\tmgmt\Translator;

use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\tmgmt\ContinuousTranslatorInterface;
use Drupal\tmgmt\Entity\Translator;
use Drupal\tmgmt\JobInterface;
use Drupal\tmgmt\TMGMTException;
use Drupal\tmgmt\Translator\AvailableResult;
use Drupal\tmgmt\Translator\TranslatableResult;
use Drupal\tmgmt\TranslatorInterface;
use Drupal\tmgmt\TranslatorPluginBase;
use GuzzleHttp\ClientInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Xtm translator plugin.
 *
 * @TranslatorPlugin(
 *   id = "xtm",
 *   label = @Translation("XTM"),
 *   description = @Translation("Xtm Translator service."),
 *   ui = "Drupal\tmgmt_xtm\XtmTranslatorUi",
 *   logo = "icons/xtm.jpg",
 *   map_remote_languages = false,
 *   files = true,
 * )
 */
class XtmTranslator extends TranslatorPluginBase implements
  ContainerFactoryPluginInterface,
  ContinuousTranslatorInterface {

  /**
   * Name of parameter that contains source string to be translated.
   *
   * @var string
   */
  protected $qParamName = 'q';

  /**
   * Maximum supported characters.
   *
   * @var int
   */
  protected $maxCharacters = 100000;

  /**
   * Guzzle HTTP client.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $client;

  /**
   * Constructs a LocalActionBase object.
   *
   * @param \GuzzleHttp\ClientInterface $client
   *   The Guzzle HTTP client.
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param array $plugin_definition
   *   The plugin implementation definition.
   */
  public function __construct(
    ClientInterface $client,
    array $configuration,
    $plugin_id,
    array $plugin_definition,
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->client = $client;
  }

  /**
   * Aborts the translation job and updates the project activity in XTM.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job to be aborted.
   *
   * @return bool
   *   Returns TRUE if the job was successfully aborted.
   */
  public function abortTranslation(JobInterface $job) {

    $connector = new Connector();
    if ($connector->updateProjectActivity($job)) {
      $job->aborted();

      // Also look for existing jobs that reference the same XTM Project ID
      // (as part of the same multilingual XTM Project) and set them as aborted.
      $xtm_reference_id = $job->getReference();
      $same_xtm_project_jobs = $this->getXtmReferenceIdJobs($xtm_reference_id);
      foreach ($same_xtm_project_jobs as $aborting_job) {
        $aborting_job->aborted();
      }
    }
    else {
      $message = $this->t('The job was aborted, but the project activity has not been updated in XTM. Please check settings and/or update the project manually.');
      $job->aborted($message, [], 'warning');
      $this->messenger()->addWarning($message);
    }
    return TRUE;
  }

  /**
   * Gets all the jobs that reference a specific XTM Project ID.
   *
   * @param int $xtm_reference_id
   *   The XTM Project reference ID.
   *
   * @return array
   *   An array of job entities that reference the given XTM Project ID.
   */
  protected function getXtmReferenceIdJobs($xtm_reference_id) {
    $job_ids = \Drupal::entityQuery('tmgmt_job')
      ->condition('reference', $xtm_reference_id)
      ->accessCheck(FALSE)
      ->execute();
    return \Drupal::entityTypeManager()
      ->getStorage('tmgmt_job')
      ->loadMultiple(array_keys($job_ids));
  }

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition,
  ) {
    return new static(
          $container->get('http_client'),
          $configuration,
          $plugin_id,
          $plugin_definition
      );
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::checkAvailable().
   *
   * Checks whether the specified translator is available for use.
   *
   * @param \Drupal\tmgmt\TranslatorInterface $translator
   *   The translator entity to check for availability.
   *
   * @return \Drupal\tmgmt\Translator\AvailableResult
   *   An AvailableResult object indicating whether the translator is available.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   *   Thrown if the translator entity is malformed or has invalid data.
   */
  public function checkAvailable(TranslatorInterface $translator) {
    if ($translator->getSetting('xtm_api_url')) {
      return AvailableResult::yes();
    }

    return AvailableResult::no(
      t(
        '@translator is not available. Make sure it is properly <a href=:configured>configured</a>.',
        [
          '@translator' => $translator->label(),
          ':configured' => $translator->toUrl()->toString(),
        ]
      )
    );
  }

  /**
   * Checks if the job can be translated by the specified translator.
   *
   * @param \Drupal\tmgmt\TranslatorInterface $translator
   *   The translator entity that will handle the job.
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job to be checked for translatability.
   *
   * @return \Drupal\tmgmt\Translator\TranslatableResult
   *   A TranslatableResult object indicating whether the job is translatable.
   *
   * @throws \Drupal\Core\Entity\EntityMalformedException
   *   Thrown if the translator or job entity is malformed or has invalid data.
   */
  public function checkTranslatable(TranslatorInterface $translator, JobInterface $job) {
    foreach (\Drupal::service('tmgmt.data')->filterTranslatable($job->getData()) as $value) {
      if (mb_strlen($value['#text']) > $this->maxCharacters) {
        return TranslatableResult::no(t(
          'The length of the job exceeded the max character count (@count).',
          ['@count' => $this->maxCharacters]
        ));
      }
    }

    if ($this->checkAvailable($translator)->getSuccess()) {
      $helper = new Helper();
      $supportedXTMLanguages = $helper->getXtmLanguage();
      $mapTargetLanguage = $helper->mapLanguageToXTMFormat($job->getTargetLangcode(), $translator);
      $mapSourceLanguage = $helper->mapLanguageToXTMFormat($job->getSourceLangcode(), $translator);

      if ($this->isLanguageOnXtmLanguageList($supportedXTMLanguages, $mapTargetLanguage) &&
        $this->isLanguageOnXtmLanguageList($supportedXTMLanguages, $mapSourceLanguage)) {
        return TranslatableResult::yes();
      }
    }

    return TranslatableResult::no(t(
      'Please go to your <a href=":settings_url">@translator Provider settings</a>, ensure the language mapping is correct and save the settings to translate from @source to @target.',
      [
        '@translator' => $translator->label(),
        ':settings_url' => $translator->toUrl()->toString(),
        '@source' => $job->getSourceLanguage()->getName(),
        '@target' => $job->getTargetLanguage()->getName(),
      ]
    ));
  }

  /**
   * Implements TMGMTTranslatorPluginControllerInterface::requestTranslation().
   *
   * Requests the translation for the specified job.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job for which the translation is requested.
   */
  public function requestTranslation(JobInterface $job) {
    $this->requestJobItemsTranslation($job->getItems());
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::getSupportedRemoteLanguages().
   *
   * Returns an empty array,
   * as this translator does not support remote languages.
   *
   * @param \Drupal\tmgmt\TranslatorInterface $translator
   *   The translator entity.
   *
   * @return array
   *   An empty array indicating no supported remote languages.
   */
  public function getSupportedRemoteLanguages(TranslatorInterface $translator) {
    return [];
  }

  /**
   * Overrides TMGMTDefaultTranslatorPluginController::getDefaultRemoteLanguagesMappings().
   */
  public function getDefaultRemoteLanguagesMappings() {
    parent::getDefaultRemoteLanguagesMappings();
    return [
      'zh-hans' => 'zh-CHS',
      'zh-hant' => 'zh-CHT',
    ];
  }

  /**
   * Retrieves the supported target languages for a given source language.
   *
   * @param \Drupal\tmgmt\TranslatorInterface $translator
   *   The translator entity.
   * @param string $source_language
   *   The source language code.
   *
   * @return array
   *   An array of supported target languages.
   *   If the source language is not found, an empty array is returned.
   */
  public function getSupportedTargetLanguages(TranslatorInterface $translator, $source_language) {
    $helper = new Helper();
    $languages = $helper->getXtmLanguage();

    if (array_key_exists($source_language, $languages)) {
      return $languages[$source_language];
    }

    return [];
  }

  /**
   * Determines if the job has checkout settings configured.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The translation job entity.
   *
   * @return bool
   *   TRUE if the job has checkout settings, otherwise FALSE.
   */
  public function hasCheckoutSettings(JobInterface $job) {
    parent::hasCheckoutSettings($job);
    return TRUE;
  }

  /**
   * Finds a customer based on the provided translator and optional ID.
   *
   * @param \Drupal\tmgmt\Entity\Translator $translator
   *   The translator entity used for the customer search.
   * @param string|null $id
   *   (Optional) The customer ID to search for.
   *   If NULL, all customers are retrieved.
   *
   * @return array
   *   An array of customers matching the search criteria.
   *   Returns an empty array if no customers are found or if an error occurs.
   */
  public function findCustomer(Translator $translator, $id = NULL) {
    $connector = new Connector();
    try {
      $response = $connector->findCustomer($translator, $id);
    }
    catch (\Exception $exception) {
      return [];
    }

    if (empty($response->customers)) {
      return [];
    }

    return $this->parseToArray($response->customers);
  }

  /**
   * Overrides the 'q' name to avoid collision with Drupal's 'q' parameter.
   *
   * This is necessary for Drupal testing where 'q' is used internally.
   *
   * @param string $name
   *   The new name for the 'q' parameter.
   */
  final public function setQueryParamName($name) {
    $this->qParamName = $name;
  }

  /**
   * {@inheritdoc}
   */
  public function requestJobItemsTranslation(array $jobItems) {
    if (empty($jobItems)) {
      \Drupal::logger('xtm-wpml-connector')->notice('No job items provided for translation.');
      return;
    };
    /** @var \Drupal\tmgmt\Entity\Job $job */
    $job = reset($jobItems)->getJob();
    $connector = new Connector();
    foreach ($jobItems as $jobItem) {
      if ($job->isContinuous()) {
        $translatable = $job->canRequestTranslation();

        if (!$translatable->getSuccess()) {
          \Drupal::logger($connector::XTM_LOGGER)->notice('Rejected Job ID: #' . $job->id() . '. ' . $translatable->getReason());
          return;
        }
        $jobItem->active();
      }
    }
    try {
      $connector->xtmRequestTranslation($job, $jobItems);
    }
    catch (TMGMTException $e) {
      \Drupal::logger($connector::XTM_LOGGER)->notice('Rejected Job ID: #' . $job->id() . '. ' . $e->getMessage());
      $job->rejected(
        'Translation has been rejected with following error: @error',
        ['@error' => $e->getMessage()],
      );
    }
  }

  /**
   * Converts an item to an array if it is not already an array.
   *
   * @param mixed $item
   *   The item to be converted to an array.
   *
   * @return array
   *   An array containing the item. If the item is already an array,
   *   it is returned as is.
   */
  private function parseToArray($item) {
    if (is_array($item)) {
      return $item;
    }
    else {
      return [$item];
    }
  }

  /**
   * Checks if a language key exists in the list of supported XTM languages.
   *
   * @param array $supportedXtmLanguages
   *   An array of supported XTM languages.
   * @param string $languageKey
   *   The language key to check in the XTM languages list.
   *
   * @return bool
   *   TRUE if the language key is found in the supported XTM languages,
   *   FALSE otherwise.
   */
  private function isLanguageOnXtmLanguageList(array $supportedXtmLanguages, $languageKey) {
    foreach ($supportedXtmLanguages as $spl) {
      if (array_key_exists($languageKey, $spl)) {
        return TRUE;
      }

      if (count($spl) > 1) {
        // More than one language.
        foreach ($spl as $lang) {
          if (array_key_exists($languageKey, $lang)) {
            return TRUE;
          }
        }
      }
    }
    return FALSE;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc