You are here

class RequestTranslationApproveForm in TMGMT Extension Suite 8

Hierarchy

Expanded class hierarchy of RequestTranslationApproveForm

1 string reference to 'RequestTranslationApproveForm'
tmgmt_extension_suit.routing.yml in ./tmgmt_extension_suit.routing.yml
tmgmt_extension_suit.routing.yml

File

src/Form/RequestTranslationApproveForm.php, line 19

Namespace

Drupal\tmgmt_extension_suit\Form
View source
class RequestTranslationApproveForm extends FormBase {

  /**
   * @var \Drupal\user\PrivateTempStore
   */
  private $tempStore;

  /**
   * @var \Drupal\tmgmt\TranslatorManager
   */
  private $translatorManager;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('user.private_tempstore'), $container
      ->get('plugin.manager.tmgmt.translator'));
  }

  /**
   * RequestTranslationApproveForm constructor.
   *
   * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
   * @param \Drupal\tmgmt\TranslatorManager $translator_manager
   */
  public function __construct(PrivateTempStoreFactory $temp_store_factory, TranslatorManager $translator_manager) {
    $this->tempStore = $temp_store_factory
      ->get('tmgmt_extension_suit');
    $this->translatorManager = $translator_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'tmgmt_extension_suit_request_translation_approve_form';
  }

  /**
   * Recreates services.
   */
  private function refreshServices() {
    if (empty($this->tempStore)) {
      $this->tempStore = Drupal::service('user.private_tempstore')
        ->get('tmgmt_extension_suit');
    }
    if (empty($this->translatorManager)) {
      $this->translatorManager = Drupal::service('plugin.manager.tmgmt.translator');
    }
  }

  /**
   * Returns job item ids that conflicts with a given node.
   *
   * @param array $data
   * @param $target_language
   *
   * @return array
   */
  protected function getConflictingItem(array $data, $target_language) {
    return Drupal::entityQuery('tmgmt_job_item')
      ->condition('state', [
      JobItemInterface::STATE_ACTIVE,
      JobItemInterface::STATE_REVIEW,
    ], 'IN')
      ->condition('plugin', $data['plugin'])
      ->condition('item_type', $data['item_type'])
      ->condition('item_id', $data['item'])
      ->condition('tjid.entity.source_language', $data['source_language'])
      ->condition('tjid.entity.target_language', $target_language)
      ->execute();
  }

  /**
   * Returns conflicting items message.
   *
   * @param array $conflicting_items
   *
   * @return string
   */
  private function getConflictMessage(array $conflicting_items) {
    $list_render_array = [
      '#theme' => 'item_list',
      '#items' => $conflicting_items,
      '#type' => 'ul',
      '#attributes' => [
        'class' => 'dropped-job-item-list',
      ],
    ];
    $rendered_list = Drupal::service('renderer')
      ->render($list_render_array);
    $message = Drupal::translation()
      ->formatPlural(count($conflicting_items), '1 item conflicted with pending item and was skipped. Existing job item: @rendered_list', '@count items conflicted with pending items and were skipped. Existing job items: @rendered_list', [
      '@rendered_list' => $rendered_list,
    ]);
    return Markup::create($message);
  }
  public function buildForm(array $form, FormStateInterface $form_state) {

    // TODO: if form uses ajax for refreshing itself on 3rd ajax request
    // it loses $this->tempStore and $this->translatorManager properties.
    // Investigate and fix this.
    $this
      ->refreshServices();
    $data = $this->tempStore
      ->get('request_translation_batch');

    // Empty private storage - nothing to translate.
    if (empty($data)) {
      return $form;
    }
    $form['translator_wrapper'] = [
      '#type' => 'details',
      '#title' => t('Configure provider'),
      '#weight' => 20,
      '#prefix' => '<div id="tmgmt-ui-translator-wrapper">',
      '#suffix' => '</div>',
      '#open' => TRUE,
    ];
    if (!($translators = tmgmt_translator_labels_flagged())) {
      drupal_set_message(t('There are no providers available. Before you can checkout you need to @configure at least one provider.', [
        '@configure' => Link::fromTextAndUrl(t('configure'), Url::fromRoute('entity.tmgmt_translator.collection'))
          ->toString(),
      ]), 'warning');
    }

    // Fake job object. It's only needed for generating checkout settings form.
    // Function tmgmt_job_create just instantiates an object of a given type.
    // We don't want ot save this object to database.
    $job = tmgmt_job_create('en', 'fr', Drupal::currentUser()
      ->id());
    $preselected_translator = $form_state
      ->getValue('translator') ?: key($translators);
    $job->translator = $preselected_translator;
    $form_state
      ->set('job', $job);
    $form['translator_wrapper']['translator'] = [
      '#type' => 'select',
      '#title' => t('Provider'),
      '#description' => t('The configured provider that will process the translation.'),
      '#options' => $translators,
      '#access' => !empty($translators),
      '#default_value' => $preselected_translator,
      '#required' => TRUE,
      '#ajax' => [
        'callback' => [
          $this,
          'ajaxTranslatorSelect',
        ],
        'wrapper' => 'tmgmt-ui-translator-wrapper',
      ],
    ];
    try {
      $settings = $this
        ->checkoutSettingsForm($form_state, $job);
    } catch (TMGMTException $e) {
      watchdog_exception('tmgmt_extension_suit', $e);
      $settings = [];
    }
    if (!is_array($settings)) {
      $settings = [];
    }
    $form['translator_wrapper']['settings'] = [
      '#type' => 'details',
      '#title' => t('Checkout settings'),
      '#prefix' => '<div id="tmgmt-ui-translator-settings">',
      '#suffix' => '</div>',
      '#tree' => TRUE,
      '#open' => TRUE,
    ] + $settings;
    $available_languages = tmgmt_available_languages();
    unset($available_languages[$data['source_language']]);
    $form['target_language'] = [
      '#title' => t('Target language'),
      '#type' => 'checkboxes',
      '#options' => $available_languages,
      '#default_value' => array_filter($data['default_target_languages']),
      '#prefix' => '<div id="edit-clone-lang-options">',
      '#suffix' => '<div class="check-controls"><span class="check-all">' . t('Check All') . '</span><span class="uncheck-all">' . t('Uncheck All') . '</span></div></div>',
      '#required' => TRUE,
    ];
    $form['request_translation'] = [
      '#weight' => 20,
      '#type' => 'submit',
      '#button_type' => 'primary',
      '#value' => $this
        ->t('Request translation'),
    ];
    $form['#attached']['library'][] = 'tmgmt_extension_suit/check_uncheck_all';
    return $form;
  }

  /**
   * Ajax callback to fetch the options provided by a translator.
   */
  public function ajaxTranslatorSelect(array $form, FormStateInterface $form_state) {
    return $form['translator_wrapper'];
  }

  /**
   * Helper function for retrieving the job settings form.
   */
  private function checkoutSettingsForm(FormStateInterface $form_state, JobInterface $job) {
    $form = [];
    if (!$job
      ->hasTranslator()) {
      return $form;
    }
    $translator = $job
      ->getTranslator();
    $result = $translator
      ->checkAvailable();
    if (!$result
      ->getSuccess()) {
      $form['#description'] = $result
        ->getReason();
      return $form;
    }
    $result = $translator
      ->checkTranslatable($job);
    if ($job
      ->getTargetLangcode() && !$result
      ->getSuccess()) {
      $form['#description'] = $result
        ->getReason();
      return $form;
    }
    $plugin_ui = $this->translatorManager
      ->createUIInstance($translator
      ->getPluginId());
    $form = $plugin_ui
      ->checkoutSettingsForm($form, $form_state, $job);
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this
      ->refreshServices();

    // Pass data from private storage appended by form data to batch.
    $data = $this->tempStore
      ->get('request_translation_batch');
    $data['target_language'] = array_filter($form_state
      ->getValue('target_language'));
    $data['translator'] = $form_state
      ->getValue('translator');
    $data['settings'] = $form_state
      ->getValue('settings');
    $conflicting_items = [];
    $operations = [];
    foreach ($data['items'] as $item) {
      $operation_data = $data;
      $operation_data['item'] = $item;
      unset($operation_data['items']);
      foreach ($operation_data['target_language'] as $language) {
        $operation_data['target_language'] = $language;
        $result = $this
          ->getConflictingItem($operation_data, $language);
        if (!empty($result)) {
          $job_item_id = key($result);
          $conflicting_items[$job_item_id] = $this
            ->t('@job_item_link with source language = "@source_language" and target language = "@target_language" for entity "@entity_type" with id = "@id".', [
            '@job_item_link' => Link::fromTextAndUrl(t('Job item'), Url::fromRoute('entity.tmgmt_job_item.canonical', [
              'tmgmt_job_item' => $job_item_id,
            ], [
              'attributes' => [
                'target' => '_blank',
              ],
            ]))
              ->toString(),
            '@entity_type' => $operation_data['item_type'],
            '@id' => $operation_data['item'],
            '@source_language' => $operation_data['source_language'],
            '@target_language' => $language,
          ]);
        }
        else {
          $operations[] = [
            [
              get_class($this),
              'processBatch',
            ],
            [
              $operation_data,
            ],
          ];
        }
      }
    }
    if (!empty($conflicting_items)) {
      drupal_set_message($this
        ->getConflictMessage($conflicting_items), 'warning');
    }
    $this->tempStore
      ->set('request_translation_batch', []);
    if (!empty($operations)) {

      // Set up batch.
      $batch = [
        'title' => t('Requesting translations...'),
        'operations' => $operations,
        'finished' => [
          get_class($this),
          'finishBatch',
        ],
      ];
      batch_set($batch);
    }
    else {
      drupal_set_message(Link::fromTextAndUrl(t('Return to "Sources" page'), Url::fromRoute('tmgmt.source_overview_default'))
        ->toString());
    }
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $job = $form_state
      ->get('job');
    try {
      if (!$job
        ->hasTranslator()) {
        $form_state
          ->setError($form, t('Error. Please contact site administrator.'));
      }
      $translator = $job
        ->getTranslator();
      $result = $translator
        ->checkAvailable();
      if (!$result
        ->getSuccess()) {
        $form_state
          ->setError($form['translator_wrapper']['translator'], $result
          ->getReason());
      }
    } catch (TMGMTException $e) {
      watchdog_exception('tmgmt_extension_suit', $e);
      $form_state
        ->setError($form, t('Error. Please contact site administrator.'));
    }
  }

  /**
   * Process batch method.
   *
   * @param $data
   * @param $context
   */
  public static function processBatch($data, &$context) {
    $message = 'Requesting translations...';
    $source_language = 'en';
    switch ($data['plugin']) {
      case 'content':
        $entity_manager = Drupal::entityTypeManager();
        $entity = $entity_manager
          ->getStorage($data['item_type'])
          ->load($data['item']);
        $source_language = $entity
          ->language()
          ->getId();
        break;
      case 'config':
        $config_factory = Drupal::configFactory()
          ->get($data['item']);
        $source_language = $config_factory
          ->get('langcode');
        break;
    }
    $job = tmgmt_job_create($source_language, $data['target_language'], Drupal::currentUser()
      ->id(), [
      'settings' => $data['settings'],
    ]);
    $job
      ->addItem($data['plugin'], $data['item_type'], $data['item']);
    $job->translator = $data['translator'];
    $job
      ->setState(JobInterface::STATE_ACTIVE);
    Drupal::service('tmgmt_extension_suit.utils.queue_unique_item')
      ->addItem('tmgmt_extension_suit_upload', [
      'id' => (int) $job
        ->id(),
    ]);
    $translator_plugin = $job
      ->getTranslatorPlugin();
    if ($translator_plugin instanceof ExtendedTranslatorPluginInterface) {
      Drupal::getContainer()
        ->get('logger.channel.tmgmt_extension_suit')
        ->info(t('File upload queued (request translation in a batch). Job id: @job_id, file name: @name.', [
        '@name' => $translator_plugin
          ->getFileName($job),
        '@job_id' => $job
          ->id(),
      ]));
    }
    $context['message'] = $message;
    $context['results'][] = $job
      ->id();
  }

  /**
   * Finish batch method.
   *
   * @param $success
   * @param $results
   * @param $operations
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse
   */
  public static function finishBatch($success, $results, $operations) {
    $type = 'status';
    if ($success) {
      $message = Drupal::translation()
        ->formatPlural(count($results), 'Translation request queued for one job. @return.', 'Translation request queued for @count jobs. @return.', [
        '@return' => Link::fromTextAndUrl(t('Return to "Sources" page'), Url::fromRoute('tmgmt.source_overview_default'))
          ->toString(),
      ]);
    }
    else {
      $type = 'error';
      $message = t('Finished with an error. @return', [
        '@return' => Link::fromTextAndUrl(t('Return to "Sources" page'), Url::fromRoute('tmgmt.source_overview_default'))
          ->toString(),
      ]);
    }
    drupal_set_message($message, $type);
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
FormBase::$configFactory protected property The config factory. 1
FormBase::$requestStack protected property The request stack. 1
FormBase::$routeMatch protected property The route match.
FormBase::config protected function Retrieves a configuration object.
FormBase::configFactory protected function Gets the config factory for this form. 1
FormBase::container private function Returns the service container.
FormBase::currentUser protected function Gets the current user.
FormBase::getRequest protected function Gets the request object.
FormBase::getRouteMatch protected function Gets the route match.
FormBase::logger protected function Gets the logger for a specific channel.
FormBase::redirect protected function Returns a redirect response object for the specified route. Overrides UrlGeneratorTrait::redirect
FormBase::resetConfigFactory public function Resets the configuration factory.
FormBase::setConfigFactory public function Sets the config factory for this form.
FormBase::setRequestStack public function Sets the request stack object to use.
LinkGeneratorTrait::$linkGenerator protected property The link generator. 1
LinkGeneratorTrait::getLinkGenerator Deprecated protected function Returns the link generator.
LinkGeneratorTrait::l Deprecated protected function Renders a link to a route given a route name and its parameters.
LinkGeneratorTrait::setLinkGenerator Deprecated public function Sets the link generator service.
LoggerChannelTrait::$loggerFactory protected property The logger channel factory service.
LoggerChannelTrait::getLogger protected function Gets the logger for a specific channel.
LoggerChannelTrait::setLoggerFactory public function Injects the logger channel factory.
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
RedirectDestinationTrait::$redirectDestination protected property The redirect destination service. 1
RedirectDestinationTrait::getDestinationArray protected function Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url.
RedirectDestinationTrait::getRedirectDestination protected function Returns the redirect destination service.
RedirectDestinationTrait::setRedirectDestination public function Sets the redirect destination service.
RequestTranslationApproveForm::$tempStore private property
RequestTranslationApproveForm::$translatorManager private property
RequestTranslationApproveForm::ajaxTranslatorSelect public function Ajax callback to fetch the options provided by a translator.
RequestTranslationApproveForm::buildForm public function Form constructor. Overrides FormInterface::buildForm
RequestTranslationApproveForm::checkoutSettingsForm private function Helper function for retrieving the job settings form.
RequestTranslationApproveForm::create public static function Instantiates a new instance of this class. Overrides FormBase::create
RequestTranslationApproveForm::finishBatch public static function Finish batch method.
RequestTranslationApproveForm::getConflictingItem protected function Returns job item ids that conflicts with a given node.
RequestTranslationApproveForm::getConflictMessage private function Returns conflicting items message.
RequestTranslationApproveForm::getFormId public function Returns a unique string identifying the form. Overrides FormInterface::getFormId
RequestTranslationApproveForm::processBatch public static function Process batch method.
RequestTranslationApproveForm::refreshServices private function Recreates services.
RequestTranslationApproveForm::submitForm public function Form submission handler. Overrides FormInterface::submitForm
RequestTranslationApproveForm::validateForm public function Form validation handler. Overrides FormBase::validateForm
RequestTranslationApproveForm::__construct public function RequestTranslationApproveForm constructor.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
UrlGeneratorTrait::$urlGenerator protected property The url generator.
UrlGeneratorTrait::getUrlGenerator Deprecated protected function Returns the URL generator service.
UrlGeneratorTrait::setUrlGenerator Deprecated public function Sets the URL generator service.
UrlGeneratorTrait::url Deprecated protected function Generates a URL or path for a specific route based on the given parameters.