lionbridge_translation_provider-8.x-2.4/tmgmt_contentapi/src/Services/JobHelper.php

tmgmt_contentapi/src/Services/JobHelper.php
<?php

namespace Drupal\tmgmt_contentapi\Services;

use Drupal\Component\Utility\Xss;
use Drupal\file\Entity\File;
use Drupal\file\FileInterface;
use Drupal\tmgmt\Entity\Job;
use Drupal\tmgmt\Entity\JobItem;
use Drupal\tmgmt\JobInterface;
use Drupal\tmgmt\TranslatorInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Mime\MimeTypeGuesserInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Component\Transliteration\TransliterationInterface;

/**
 * Provides general utility functions for the Job.
 */
class JobHelper {
  /**
   * The file system service.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected FileSystemInterface $fileSystem;

  /**
   * The current user service.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected AccountProxyInterface $currentUser;

  /**
   * The MIME type guesser service.
   *
   * @var \Symfony\Component\Mime\MimeTypeGuesserInterface
   */
  protected MimeTypeGuesserInterface $mimeTypeGuesser;

  /**
   * The entity type manager service.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The transliteration service.
   *
   * @var \Drupal\Component\Transliteration\TransliterationInterface
   */
  protected $transliteration;

  /**
   * Constructs a JobHelper object.
   *
   * @param \Drupal\Core\File\FileSystemInterface $fileSystem
   *   The file system service.
   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
   *   The current user service.
   * @param \Symfony\Component\Mime\MimeTypeGuesserInterface $mimeTypeGuesser
   *   The MIME type guesser service.
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity type manager service.
   * @param \Drupal\Component\Transliteration\TransliterationInterface $transliteration
   *   The transliteration service.
   */
  public function __construct(
    FileSystemInterface $fileSystem,
    AccountProxyInterface $currentUser,
    MimeTypeGuesserInterface $mimeTypeGuesser,
    EntityTypeManagerInterface $entityTypeManager,
    TransliterationInterface $transliteration
  ) {
    $this->fileSystem = $fileSystem;
    $this->currentUser = $currentUser;
    $this->mimeTypeGuesser = $mimeTypeGuesser;
    $this->entityTypeManager = $entityTypeManager;
    $this->transliteration = $transliteration;
  }

  /**
   * Creates an instance of the service using the container.
   *
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   *   The service container.
   *
   * @return static
   *   An instance of GeneralHelperService.
   */
  public static function create(ContainerInterface $container): self {
    return new static(
          $container->get('file_system'),
          $container->get('current_user'),
          $container->get('mime_type_guesser'),
          $container->get('entity_type.manager'),
          $container->get('transliteration'),
      );
  }

  /**
   * Retrieves the label of a job.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job entity.
   *
   * @return string
   *   The label of the job.
   */
  public function getJobLabel(JobInterface $job): string {
    return $job->get("label")->value ?? $job->label()->getArguments()["@title"];
  }

  /**
   * Retrieves a sanitized label of a job without special characters.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job entity.
   *
   * @return string
   *   The sanitized label.
   */
  public function getJobLabelNoSpeChars(JobInterface $job): string {
    return $this->getStringNoSpeChars($this->getJobLabel($job));
  }

  /**
   * Removes special characters from a string.
   *
   * @param string $arg
   *   The input string.
   *
   * @return string
   *   The sanitized string.
   */
  public function getStringNoSpeChars(string $arg): string {
    $toreturn = mb_ereg_replace("([^\w\s\d\-_~,;\[\]\(\).])", '', $arg);
    $toreturn = mb_ereg_replace("([\.]{2,})", '', $toreturn);
    return Xss::filter($toreturn);
  }

  /**
   * Creates a file entity from a URI.
   *
   * @param string $uri
   *   The file URI.
   *
   * @return \Drupal\file\FileInterface|object
   *   The file entity or an empty object if URI is invalid.
   */
  public function createFileObject($uri) {
    if (!$uri) {
      return (object) [];
    }
    $fileMime = $this->mimeTypeGuesser->guessMimeType($uri);
    $file = File::create([
      'uid' => $this->currentUser->id(),
      'filename' => $this->fileSystem->basename($uri),
      'uri' => $uri,
      'filemime' => $fileMime,
      'filesize' => filesize($uri),
      'status' => 1,
    ]);
    $file->save();
    return $file;
  }

  /**
   * Adds CPA settings to a job.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job entity.
   * @param string $cpsettings
   *   The CPA settings to add.
   */
  public function addCpaSettingsToJob(JobInterface $job, string $cpsettings): void {
    $settings = $job->get('settings')->getValue();
    $settings[0]['capi-remote'] = $cpsettings;
    $job->set('settings', $settings);
  }

  /**
   * Retrieves all active jobs for a translator.
   *
   * @param \Drupal\tmgmt\TranslatorInterface $translator
   *   The translator entity.
   *
   * @return array
   *   An array of job entities.
   */
  public function getAllJobsByTranslator(TranslatorInterface $translator): array {
    return $this->entityTypeManager->getStorage('tmgmt_job')->loadByProperties([
      'translator' => $translator->id(),
      'state' => Job::STATE_ACTIVE,
    ]);
  }

  /**
   * Retrieves the CPA job ID from a local job.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job entity.
   *
   * @return string
   *   The CPA job ID.
   *
   * @throws \Exception
   *   If the CPA job ID cannot be found.
   */
  public function getCpJobIdfromLocJob(JobInterface $job): string {
    // Check if the job is a CPA job.
    if ($job->getSetting('capi-remote')) {
      $jobSettings = unserialize($job->getSetting('capi-remote'));
      $task = $job->getSetting('capi-settings')['task'];
      if (isset($task)) {
        $first_key = !empty($jobSettings) ? array_key_first($jobSettings) : null;
        $firstRequest = $task === 'trans' ? $jobSettings[$first_key][0] : $jobSettings[$first_key];
      }
    }
    if (!isset($firstRequest)) {
      throw new \Exception('Job ID could not be found in local job!');
    }
    try {
      // Check if $firstRequest is an object.
      if (!is_object($firstRequest)) {
        throw new \Exception('Job ID could not be found in local job!');
      }
      return $firstRequest->getJobId();
    }
    catch (\Exception $e) {
      throw new \Exception('Job ID could not be found in local job!');
    }
  }

  /**
   * Resets a job and its items to the active state.
   *
   * @param \Drupal\tmgmt\JobInterface $job
   *   The job entity.
   * @param \Drupal\file\FileInterface $file
   *   The file entity containing the XLIFF data.
   *
   * @return array
   *   An array of item IDs.
   */
  public function resetJobandItemsToActive(JobInterface &$job, FileInterface $file) {
    $items = $job->getItems();
    $xmlPath = $this->fileSystem->realpath($file->getFileUri());
    $xml = simplexml_load_file($xmlPath);

    if ($xml === FALSE) {
      return [];
    }

    $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:1.2');

    $itemid_array = [];
    foreach ($items as $item) {
      $itemId = $item->id();
      $groups = $xml->xpath("//xliff:group[@id='{$itemId}']");

      if (count($groups) === 1) {
        $item->setState(Job::STATE_ACTIVE);
        $job->setState(JobItem::STATE_ACTIVE);
        $itemid_array[] = $itemId;
      }
    }
    return $itemid_array;
  }

  /**
   * Function to get jobs translator settings.
   *
   * @param int $tjid
   *   The job ID.
   *
   * @return array
   *   An array of settings.
   */
  public function getJobTranslatorSettings($tjid = '') {
    // If job not set then get default translators settings.
    // Else get the job translator settings.
    // Below if condition should only get used in case of cron.
    if ($tjid == '') {
      $translators = $this->entityTypeManager->getStorage('tmgmt_translator')->loadByProperties(['plugin' => 'contentapi']);
      // Check if cron is enabled in any translator.
      // If yes then return array with details.
      $is_cron_enable_for_any_translator = FALSE;
      foreach ($translators as $translator) {
        if ($translator->getSetting('cron-settings')['status']) {
          $is_cron_enable_for_any_translator = TRUE;
        }
      }
      // Return array with cron set to 1 if any translator has cron enabled.
      if ($is_cron_enable_for_any_translator) {
        return ['iscronset' => 1];
      }
      // If no translator has cron enabled then return empty array.
      return [];
    }
    else {
      $job = $this->entityTypeManager->getStorage('tmgmt_job')->load($tjid);
      $translator = $job->getTranslator();
      $iscronset = $translator->getSetting('cron-settings')['status'];
      // Check if quick import is enabled or fail safe.
      $is_process_method = $translator->getSetting('process_method');
      return ['iscronset' => $iscronset, 'process_method' => $is_process_method];
    }
  }

  /**
   * Cleans a string for safe directory/file creation and prevents DB errors.
   *
   * @param string $string
   *   The original label (job title or node title).
   * @param string $basePath
   *   The base path (e.g. "public://.../job-title/..."). Empty when cleaning for directories.
   *
   * @return string
   *   A safe, truncated string for file or directory creation.
   */
  public function getCleanStringForDirectoryAndFileCreation(string $string, string $basePath = ''): string {
    // Step 1: Transliterate (accents → ASCII).
    $title = $this->transliteration->transliterate($string, 'en');

    // Step 2: Replace unsupported characters with underscore.
    $title = preg_replace('/[^A-Za-z0-9._-]+/', '_', $title);

    // Step 3: Collapse multiple underscores.
    $title = preg_replace('/_+/', '_', $title);

    // Step 4: Trim leading/trailing underscores, dots, and spaces.
    $title = trim($title, ' ._');

    // Step 5: Prevent reserved Windows names.
    $reserved = [
      'CON','PRN','AUX','NUL',
      'COM1','COM2','COM3','COM4','COM5','COM6','COM7','COM8','COM9',
      'LPT1','LPT2','LPT3','LPT4','LPT5','LPT6','LPT7','LPT8','LPT9'
    ];
    if (in_array(strtoupper($title), $reserved, TRUE)) {
      $title = '_' . $title;
    }

    // Step 6: Handle max length based on total URI.
    // file_managed.uri column is VARCHAR(255).
    // We reserve 100 chars for $basePath and extra suffix (_id_id_lang_lang.xlf).
    $maxLength = 150;
    if (!empty($basePath)) {
      $available = 250 - strlen($basePath); // leave headroom
      $maxLength = max(50, $available);     // at least 50 chars
    }
    $title = substr($title, 0, $maxLength);

    return $title ?: 'untitled';
  }
}

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

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