You are here

lingotek.module in Lingotek Translation 3.1.x

Implements Drupal-related hooks for the Lingotek Translation module.

File

lingotek.module
View source
<?php

/**
 * @file
 * Implements Drupal-related hooks for the Lingotek Translation module.
 */
use Drupal\Core\Language\LanguageInterface;
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Entity\ContentEntityFormInterface;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\lingotek\Entity\LingotekContentMetadata;
use Drupal\lingotek\Entity\LingotekProfile;
use Drupal\lingotek\Exception\LingotekApiException;
use Drupal\lingotek\Exception\LingotekDocumentArchivedException;
use Drupal\lingotek\Exception\LingotekDocumentLockedException;
use Drupal\lingotek\Exception\LingotekPaymentRequiredException;
use Drupal\lingotek\Lingotek;

/**
 * Implements hook_toolbar().
 */
function lingotek_toolbar() {
  $items = [];
  $items['translation'] = [
    '#type' => 'toolbar_item',
    '#attached' => [
      'library' => [
        'lingotek/lingotek.icons',
      ],
    ],
  ];
  return $items;
}

/**
 * Implements hook_module_implements_alter().
 */
function lingotek_module_implements_alter(&$implementations, $hook) {

  // Make sure lingotek_entity_presave() comes last.
  switch ($hook) {

    // Move our hook_entity_type_alter() implementation to the end of the list.
    case 'entity_presave':
    case 'entity_insert':
      $group = $implementations['lingotek'];
      unset($implementations['lingotek']);
      $implementations['lingotek'] = $group;
      break;
  }
}

/**
 * Implements hook_entity_presave().
 */
function lingotek_entity_presave(EntityInterface $entity) {
  $configuration_service = \Drupal::service('lingotek.configuration');
  if ($entity instanceof ContentEntityInterface && $configuration_service
    ->isEnabled($entity
    ->getEntityTypeId(), $entity
    ->bundle())) {
    if ($entity
      ->language() === $entity
      ->getUntranslated()
      ->language()) {
      if ($entity->lingotek_metadata->entity === NULL) {
        $metadata = LingotekContentMetadata::create();
        $metadata
          ->save();
        $entity->lingotek_metadata = $metadata;
      }
      $translation_service = \Drupal::service('lingotek.content_translation');
      $translation_service
        ->updateEntityHash($entity);
    }
  }
}

/**
 * Implements hook_entity_insert().
 */
function lingotek_entity_insert(EntityInterface $entity) {

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $configuration_service */
  $configuration_service = \Drupal::service('lingotek.configuration');
  if ($entity instanceof ConfigEntityInterface) {
    if (\Drupal::isConfigSyncing()) {

      // We don't want to react to configuration imports.
      return;
    }

    /** @var \Drupal\lingotek\LingotekConfigTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('lingotek.config_translation');
    $entity_type_id = $entity
      ->getEntityTypeId();
    if ($entity instanceof FieldConfig) {
      $entity_type_id = $entity
        ->getTargetEntityTypeId() . '_fields';
    }
    if ($translation_service
      ->isEnabled($entity_type_id) && !in_array($entity
      ->language()
      ->getId(), [
      LanguageInterface::LANGCODE_NOT_SPECIFIED,
      LanguageInterface::LANGCODE_NOT_APPLICABLE,
    ])) {
      $profile = $configuration_service
        ->getConfigEntityProfile($entity);
      if ($profile === NULL) {

        // If for whatever reason there is no profile, we better be cautious and
        // do nothing. This can happen e.g. if there are modules implementing
        // hook_lingotek_content_entity_get_profile().
        return;
      }
      if ($profile
        ->id() === Lingotek::PROFILE_DISABLED) {
        $translation_service
          ->setSourceStatus($entity, Lingotek::STATUS_DISABLED);
        $translation_service
          ->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
        return;
      }
      elseif ($translation_service
        ->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
        return;
      }
      elseif ($translation_service
        ->getSourceStatus($entity) === Lingotek::STATUS_DISABLED) {
        if ($translation_service
          ->getDocumentId($entity) !== NULL) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        else {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        $translation_service
          ->checkTargetStatuses($entity);
        return;
      }
      $has_autoupload = $profile
        ->hasAutomaticUpload();
      $source_status = $translation_service
        ->getSourceStatus($entity);
      $entity_has_changed = $translation_service
        ->hasEntityChanged($entity);
      if ($has_autoupload) {

        // New entity with auto-upload
        if ($source_status == NULL || $source_status == Lingotek::STATUS_UNTRACKED) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
          try {
            $document_id = $translation_service
              ->uploadDocument($entity);
            $translation_service
              ->setTargetStatuses($entity, Lingotek::STATUS_REQUEST);
          } catch (LingotekPaymentRequiredException $exception) {
            \Drupal::messenger()
              ->addError(t('Community has been disabled. Please contact support@lingotek.com to re-enable your community.'));
          } catch (LingotekApiException $exception) {
            \Drupal::messenger()
              ->addError(t('The upload for @entity_type %title failed. Please try again.', [
              '@entity_type' => $entity
                ->getEntityTypeId(),
              '%title' => $entity
                ->label(),
            ]));
          }
        }
      }
      elseif (!$has_autoupload) {
        if ($entity_has_changed) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
          $translation_service
            ->markTranslationsAsDirty($entity);
          $translation_service
            ->setTargetStatuses($entity, Lingotek::STATUS_REQUEST);
        }
        if ($profile
          ->id() == "disabled") {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_DISABLED);
          $translation_service
            ->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
        }
      }
    }
  }
  elseif ($entity instanceof ContentEntityInterface) {
    if ($configuration_service
      ->isEnabled($entity
      ->getEntityTypeId(), $entity
      ->bundle())) {
      if ($entity instanceof ContentEntityInterface && $configuration_service
        ->isEnabled($entity
        ->getEntityTypeId(), $entity
        ->bundle())) {
        if ($entity->lingotek_metadata->entity !== NULL) {
          if (!$entity->lingotek_metadata->entity
            ->getContentEntityId()) {
            $entity->lingotek_metadata->entity
              ->setEntity($entity);
            $entity->lingotek_metadata->entity
              ->save();
          }
        }
      }

      // If workbench moderation is enabled, we need to prevent that content is
      // processed if not the right state.

      /** @var \Drupal\lingotek\Moderation\LingotekModerationFactoryInterface $moderation_factory */
      $moderation_factory = \Drupal::service('lingotek.moderation_factory');
      $moderation_handler = $moderation_factory
        ->getModerationHandler();
      $prevent = $moderation_handler
        ->shouldModerationPreventUpload($entity);
      if ($prevent) {
        return;
      }
      $profile = $configuration_service
        ->getEntityProfile($entity);
      if ($profile === NULL) {

        // If for whatever reason there is no profile, we better be cautious and
        // do nothing. This can happen e.g. if there are modules implementing
        // hook_lingotek_content_entity_get_profile().
        return;
      }
      $has_autoupload = $profile
        ->hasAutomaticUpload();

      /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
      $translation_service = \Drupal::service('lingotek.content_translation');
      $source_status = $translation_service
        ->getSourceStatus($entity);
      if ($profile
        ->id() == "disabled") {
        $translation_service
          ->setSourceStatus($entity, Lingotek::STATUS_DISABLED);
        $translation_service
          ->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
      }
      elseif ($source_status === Lingotek::STATUS_DISABLED) {
        if ($translation_service
          ->getDocumentId($entity) !== NULL) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        else {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        $translation_service
          ->checkTargetStatuses($entity);
      }

      // Entity inserts are always changes.
      $entity_has_changed = TRUE;
      if ($has_autoupload) {

        // New entity with auto-upload
        if ($source_status == NULL || $source_status == Lingotek::STATUS_UNTRACKED) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
          try {
            $document_id = $translation_service
              ->uploadDocument($entity);
            $translation_service
              ->setTargetStatuses($entity, Lingotek::STATUS_REQUEST);
            \Drupal::messenger()
              ->addStatus(t('<em>@title</em> sent to Lingotek successfully.', [
              '@title' => $entity
                ->label(),
            ]));
          } catch (LingotekPaymentRequiredException $exception) {
            \Drupal::messenger()
              ->addError(t('Community has been disabled. Please contact support@lingotek.com to re-enable your community.'));
          } catch (LingotekApiException $exception) {
            \Drupal::messenger()
              ->addError(t('The upload for @entity_type %title failed. Please try again.', [
              '@entity_type' => $entity
                ->getEntityTypeId(),
              '%title' => $entity
                ->label(),
            ]));
          }
        }
        elseif ($entity_has_changed) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
          try {
            $response = $translation_service
              ->updateDocument($entity);
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_IMPORTING);
            $translation_service
              ->markTranslationsAsDirty($entity);
            $translation_service
              ->setTargetStatuses($entity, Lingotek::STATUS_PENDING);
            \Drupal::messenger()
              ->addStatus(t('<em>@title</em> was updated and sent to Lingotek successfully.', [
              '@title' => $entity
                ->label(),
            ]));
          } catch (LingotekPaymentRequiredException $exception) {
            \Drupal::messenger()
              ->addError(t('Community has been disabled. Please contact support@lingotek.com to re-enable your community.'));
          } catch (LingotekApiException $exception) {
            \Drupal::messenger()
              ->addError(t('The update for @entity_type %title failed. Please try again.', [
              '@entity_type' => $entity
                ->getEntityTypeId(),
              '%title' => $entity
                ->label(),
            ]));
          }
        }
      }

      // When inserting we never should set the status as EDITED.
    }
  }
}

/**
 * Implements hook_entity_update().
 */
function lingotek_entity_update(EntityInterface $entity) {

  // If it's new, has been already processed.
  if (isset($entity->lingotek_processed) && $entity->lingotek_processed || isset($entity->original->lingotek_processed) && $entity->original->lingotek_processed) {
    return;
  }

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $configuration_service */
  $configuration_service = \Drupal::service('lingotek.configuration');
  if ($entity instanceof ConfigEntityInterface) {
    if (\Drupal::isConfigSyncing()) {

      // We don't want to react to configuration imports.
      return;
    }

    /** @var \Drupal\lingotek\LingotekConfigTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('lingotek.config_translation');
    $entity_type_id = $entity
      ->getEntityTypeId();
    if ($entity instanceof FieldConfig) {
      $entity_type_id = $entity
        ->getTargetEntityTypeId() . '_fields';
    }
    if ($translation_service
      ->isEnabled($entity_type_id) && !in_array($entity
      ->language()
      ->getId(), [
      LanguageInterface::LANGCODE_NOT_SPECIFIED,
      LanguageInterface::LANGCODE_NOT_APPLICABLE,
    ])) {
      $profile = $configuration_service
        ->getConfigEntityProfile($entity);
      if ($profile === NULL) {

        // If for whatever reason there is no profile, we better be cautious and
        // do nothing. This can happen e.g. if there are modules implementing
        // hook_lingotek_content_entity_get_profile().
        return;
      }
      if ($profile
        ->id() === Lingotek::PROFILE_DISABLED) {
        $translation_service
          ->setSourceStatus($entity, Lingotek::STATUS_DISABLED);
        $translation_service
          ->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
        return;
      }
      elseif ($translation_service
        ->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
        return;
      }
      elseif ($translation_service
        ->getSourceStatus($entity) === Lingotek::STATUS_DISABLED) {
        if ($translation_service
          ->getDocumentId($entity) !== NULL) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        else {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
        }
        $translation_service
          ->checkTargetStatuses($entity);
        return;
      }
      $has_autoupload = $profile
        ->hasAutomaticUpload();
      $source_status = $translation_service
        ->getSourceStatus($entity);
      $entity_has_changed = $translation_service
        ->hasEntityChanged($entity);
      if ($has_autoupload) {

        // Updated entity with auto-upload
        $translation_service
          ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
        try {
          $document_id = $translation_service
            ->updateDocument($entity);
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_IMPORTING);
          $translation_service
            ->markTranslationsAsDirty($entity);
        } catch (LingotekDocumentArchivedException $exception) {
          \Drupal::messenger()
            ->addError(t('Document @entity_type %title has been archived. Please upload again.', [
            '@entity_type' => $entity
              ->getEntityTypeId(),
            '%title' => $entity
              ->label(),
          ]));
        } catch (LingotekDocumentLockedException $exception) {
          \Drupal::messenger()
            ->addError(t('Document @entity_type %title has a new version. The document id has been updated for all future interactions. Please try again.', [
            '@entity_type' => $entity
              ->getEntityTypeId(),
            '%title' => $entity
              ->label(),
          ]));
        } catch (LingotekPaymentRequiredException $exception) {
          \Drupal::messenger()
            ->addError(t('Community has been disabled. Please contact support@lingotek.com to re-enable your community.'));
        } catch (LingotekApiException $exception) {
          \Drupal::messenger()
            ->addError(t('The update for @entity_type %title failed. Please try again.', [
            '@entity_type' => $entity
              ->getEntityTypeId(),
            '%title' => $entity
              ->label(),
          ]));
        }
      }
      elseif (!$has_autoupload) {
        if ($entity_has_changed && $source_status !== Lingotek::STATUS_UNTRACKED) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
          $translation_service
            ->markTranslationsAsDirty($entity);
        }
      }
    }
  }
  elseif ($entity instanceof ContentEntityInterface) {
    if ($configuration_service
      ->isEnabled($entity
      ->getEntityTypeId(), $entity
      ->bundle())) {
      if ($entity instanceof ContentEntityInterface && $configuration_service
        ->isEnabled($entity
        ->getEntityTypeId(), $entity
        ->bundle())) {
        if ($entity->lingotek_metadata->entity !== NULL) {
          if (!$entity->lingotek_metadata->entity
            ->getContentEntityId()) {
            $entity->lingotek_metadata->entity
              ->setEntity($entity);
            $entity->lingotek_metadata->entity
              ->save();
          }
        }
      }

      /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
      $translation_service = \Drupal::service('lingotek.content_translation');
      if ($entity
        ->isDefaultTranslation()) {

        // If workbench moderation is enabled, we need to prevent that content is
        // processed if not the right state.

        /** @var \Drupal\lingotek\Moderation\LingotekModerationFactoryInterface $moderation_factory */
        $moderation_factory = \Drupal::service('lingotek.moderation_factory');
        $moderation_handler = $moderation_factory
          ->getModerationHandler();
        $preventUpload = $moderation_handler
          ->shouldModerationPreventUpload($entity);
        $profile = $configuration_service
          ->getEntityProfile($entity);
        if ($profile === NULL) {

          // If for whatever reason there is no profile, we better be cautious and
          // do nothing. This can happen e.g. if there are modules implementing
          // hook_lingotek_content_entity_get_profile().
          return;
        }
        if ($profile
          ->id() === Lingotek::PROFILE_DISABLED) {
          $translation_service
            ->setSourceStatus($entity, Lingotek::STATUS_DISABLED);
          $translation_service
            ->setTargetStatuses($entity, Lingotek::STATUS_DISABLED);
          return;
        }
        elseif ($translation_service
          ->getSourceStatus($entity) === Lingotek::STATUS_CANCELLED) {
          return;
        }
        elseif ($translation_service
          ->getSourceStatus($entity) === Lingotek::STATUS_DISABLED) {
          if ($translation_service
            ->getDocumentId($entity) !== NULL) {
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
          }
          else {
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_CURRENT);
          }
          $translation_service
            ->checkTargetStatuses($entity);
          return;
        }
        $has_autoupload = !$preventUpload && $profile
          ->hasAutomaticUpload();
        $source_status = $translation_service
          ->getSourceStatus($entity);
        $entity_has_changed = $translation_service
          ->hasEntityChanged($entity);
        if ($has_autoupload) {

          // New entity with auto-upload
          if ($source_status == NULL || $source_status == Lingotek::STATUS_UNTRACKED) {
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
            try {
              $document_id = $translation_service
                ->uploadDocument($entity);
              \Drupal::messenger()
                ->addStatus(t('<em>@title</em> sent to Lingotek successfully.', [
                '@title' => $entity
                  ->label(),
              ]));
            } catch (LingotekApiException $exception) {
              \Drupal::messenger()
                ->addError(t('The upload for @entity_type %title failed. Please try again.', [
                '@entity_type' => $entity
                  ->getEntityTypeId(),
                '%title' => $entity
                  ->label(),
              ]));
            }
          }
          elseif ($entity_has_changed) {
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
            try {
              $response = $translation_service
                ->updateDocument($entity);
              $translation_service
                ->setSourceStatus($entity, Lingotek::STATUS_IMPORTING);
              $translation_service
                ->markTranslationsAsDirty($entity);
              \Drupal::messenger()
                ->addStatus(t('<em>@title</em> was updated and sent to Lingotek successfully.', [
                '@title' => $entity
                  ->label(),
              ]));
            } catch (LingotekDocumentArchivedException $exception) {
              \Drupal::messenger()
                ->addError(t('Document @entity_type %title has been archived. Please upload again.', [
                '@entity_type' => $entity
                  ->getEntityTypeId(),
                '%title' => $entity
                  ->label(),
              ]));
            } catch (LingotekDocumentLockedException $exception) {
              \Drupal::messenger()
                ->addError(t('Document @entity_type %title has a new version. The document id has been updated for all future interactions. Please try again.', [
                '@entity_type' => $entity
                  ->getEntityTypeId(),
                '%title' => $entity
                  ->label(),
              ]));
            } catch (LingotekPaymentRequiredException $exception) {
              \Drupal::messenger()
                ->addError(t('Community has been disabled. Please contact support@lingotek.com to re-enable your community.'));
            } catch (LingotekApiException $exception) {
              \Drupal::messenger()
                ->addError(t('The update for @entity_type %title failed. Please try again.', [
                '@entity_type' => $entity
                  ->getEntityTypeId(),
                '%title' => $entity
                  ->label(),
              ]));
            }
          }
        }
        elseif (!$has_autoupload) {
          if ($entity_has_changed && $source_status !== Lingotek::STATUS_UNTRACKED) {
            $translation_service
              ->setSourceStatus($entity, Lingotek::STATUS_EDITED);
            $translation_service
              ->markTranslationsAsDirty($entity);
          }
        }
      }
      else {
        $langcode = $entity
          ->language()
          ->getId();

        // Edited a translation.
        if ($current_status = $translation_service
          ->getTargetStatus($entity, $langcode)) {

          // Only mark as out of date the current ones.
          $to_change = [
            Lingotek::STATUS_CURRENT,
          ];
          if (in_array($current_status, $to_change)) {
            $translation_service
              ->setTargetStatus($entity, $langcode, Lingotek::STATUS_EDITED);
          }
        }
      }
    }
  }
}

/**
 * Implements hook_entity_delete().
 */
function lingotek_entity_delete(EntityInterface $entity) {

  // Only act on content entities.
  if (!$entity instanceof ContentEntityInterface) {
    return;
  }
  if (\Drupal::isConfigSyncing()) {

    // We don't want to react to configuration imports.
    return;
  }

  /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
  $translation_service = \Drupal::service('lingotek.content_translation');

  // Cancel the TMS document if it's been uploaded.
  if ($translation_service
    ->getDocumentId($entity)) {
    try {
      $response = $translation_service
        ->cancelDocument($entity);
    } catch (LingotekApiException $exception) {
      \Drupal::messenger()
        ->addError(t('Failed cancelling @entity_type %title. Please try again.', [
        '@entity_type' => $entity
          ->getEntityTypeId(),
        '%title' => $entity
          ->label(),
      ]));
    }
  }
}

/**
 * Implements hook_form_alter().
 */
function lingotek_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $form_object = $form_state
    ->getFormObject();
  if ($form_object instanceof ContentEntityFormInterface) {

    // If it is a delete form, return.
    if ('delete' === $form_object
      ->getOperation()) {
      return;
    }
    $entity = $form_object
      ->getEntity();

    /** @var \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager */
    $content_translation_manager = \Drupal::service('content_translation.manager');

    /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
    $lingotek_config = \Drupal::service('lingotek.configuration');

    // If content translation is not enabled and lingotek configured, don't add
    // the form element.
    if (!$content_translation_manager
      ->isEnabled($entity
      ->getEntityTypeId(), $entity
      ->bundle()) || !$lingotek_config
      ->isEnabled($entity
      ->getEntityTypeId(), $entity
      ->bundle())) {
      return;
    }
    $default_profile = $lingotek_config
      ->getEntityProfile($entity);

    // We need to ensure it can't be NULL.
    if ($default_profile === NULL) {
      $default_profile = LingotekProfile::load(Lingotek::PROFILE_MANUAL);
    }
    $profile_options = $lingotek_config
      ->getProfileOptions();
    $current_user = \Drupal::currentUser();
    $can_assign_profile = $current_user
      ->hasPermission('assign lingotek translation profiles') || $current_user
      ->hasPermission('administer lingotek');
    $form['lingotek_translation_management'] = [
      '#type' => 'details',
      '#title' => t('Translation Management'),
      '#description' => t("The Lingotek Translation module was developed to help you translate your site. The module integrates the Lingotek translation management system directly into Drupal, so that your users can leverage the power of Lingotek's translation tools and services without ever having to leave the comfort of your Drupal environment."),
      '#tree' => TRUE,
      '#weight' => 0,
      '#access' => $can_assign_profile,
    ];
    if (isset($form['advanced'])) {
      $form['lingotek_translation_management']['#group'] = 'advanced';
      $form['lingotek_translation_management']['#weight'] = 15;
    }
    $form['lingotek_translation_management']['lingotek_translation_profile'] = [
      '#type' => 'select',
      '#title' => t('Translation Profile'),
      '#options' => $profile_options,
      // If the profile is invalid, default to not do anything for safety.
      '#default_value' => array_key_exists($default_profile
        ->id(), $profile_options) ? $default_profile
        ->id() : Lingotek::PROFILE_MANUAL,
      '#access' => $can_assign_profile,
    ];
    foreach (array_keys($form['actions']) as $action) {
      if ($action != 'preview' && $action != 'lingotek_metadata' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {

        // We need to act before the node itself is saved.
        $submit_actions = $form['actions'][$action]['#submit'];
        array_unshift($submit_actions, 'lingotek_form_content_entity_form_submit');
        $form['actions'][$action]['#submit'] = $submit_actions;
      }
    }
  }
}

/**
 * @param array $form
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 */
function lingotek_form_content_entity_form_submit(array $form, FormStateInterface $form_state) {
  $form_values = $form_state
    ->getValues();

  /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
  $translation_service = \Drupal::service('lingotek.content_translation');

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');

  /** @var \Drupal\Core\Entity\ContentEntityFormInterface $entity_form */
  $entity_form = $form_state
    ->getFormObject();

  /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
  $entity = $entity_form
    ->getEntity();
  if ($entity_form
    ->getOperation() !== 'lingotek_metadata') {
    $profile_id = $form_values['lingotek_translation_management']['lingotek_translation_profile'];
    $lingotek_config
      ->setProfile($entity, $profile_id, FALSE);
  }
}

/**
 * Implements hook_contextual_links_view_alter().
 */
function lingotek_contextual_links_view_alter(&$element, $items) {

  // TODO
}

/**
 * Implements hook_entity_type_alter().
 */
function lingotek_entity_type_alter(array &$entity_types) {

  // Provide defaults for lingotek translation info.

  /** @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */
  foreach ($entity_types as $entity_type) {
    if ($entity_type
      ->isTranslatable()) {
      if (!$entity_type
        ->hasHandlerClass('lingotek')) {
        $entity_type
          ->setHandlerClass('lingotek', 'Drupal\\lingotek\\LingotekContentTranslationHandler');
      }
    }
  }
}

/**
 * Implements hook_entity_base_field_info().
 */
function lingotek_entity_base_field_info(EntityTypeInterface $entity_type) {

  // Taken from content_translation.

  /** @var \Drupal\content_translation\ContentTranslationManagerInterface $manager */
  $manager = \Drupal::service('content_translation.manager');

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');
  $entity_type_id = $entity_type
    ->id();
  if ($manager
    ->isEnabled($entity_type_id) && $lingotek_config
    ->isEnabled($entity_type_id)) {
    $definitions = \Drupal::entityTypeManager()
      ->getHandler($entity_type_id, 'lingotek')
      ->getFieldDefinitions();
    $installed_storage_definitions = \Drupal::service('entity.last_installed_schema.repository')
      ->getLastInstalledFieldStorageDefinitions($entity_type_id);

    // We return metadata storage fields whenever content translation is enabled
    // or it was enabled before, so that we keep translation metadata around
    // when translation is disabled.
    if ($manager
      ->isEnabled($entity_type_id) || array_intersect_key($definitions, $installed_storage_definitions)) {
      return $definitions;
    }
  }
}

/**
 * Implements hook_entity_translation_insert().
 */
function lingotek_entity_translation_insert(ContentEntityInterface $translation) {

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');

  /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
  $translation_service = \Drupal::service('lingotek.content_translation');
  if ($lingotek_config
    ->isEnabled($translation
    ->getEntityTypeId(), $translation
    ->bundle())) {
    $status = $translation_service
      ->getTargetStatus($translation, $translation
      ->language()
      ->getId());

    // As untracked is a default, we save it anyway.
    if ($status === Lingotek::STATUS_REQUEST || $status === Lingotek::STATUS_UNTRACKED) {
      $translation = $translation_service
        ->setTargetStatus($translation, $translation
        ->language()
        ->getId(), Lingotek::STATUS_UNTRACKED, FALSE);
    }
  }
}
function lingotek_entity_translation_delete(ContentEntityInterface $entity) {

  /** @var \Drupal\lingotek\LanguageLocaleMapperInterface $languageMapper */
  $languageMapper = \Drupal::service('lingotek.language_locale_mapper');

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');

  /** @var \Drupal\lingotek\LingotekContentTranslationServiceInterface $translation_service */
  $translation_service = \Drupal::service('lingotek.content_translation');
  $langcode = $entity
    ->language()
    ->getId();
  if ($lingotek_config
    ->isEnabled($entity
    ->getEntityTypeId(), $entity
    ->bundle())) {
    $document_id = $translation_service
      ->getDocumentId($entity);
    if ($document_id) {
      $translation_statuses = \Drupal::service('lingotek')
        ->getDocumentTranslationStatuses($document_id);
      foreach ($translation_statuses as $lingotek_locale => $progress) {
        $drupal_language = $languageMapper
          ->getConfigurableLanguageForLocale($lingotek_locale);
        if ($drupal_language
          ->getId() === $langcode) {
          if ($progress === Lingotek::PROGRESS_COMPLETE) {
            $translation_service
              ->setTargetStatus($entity, $langcode, Lingotek::STATUS_READY);
          }
          else {
            $translation_service
              ->setTargetStatus($entity, $langcode, Lingotek::STATUS_PENDING);
          }
          if (isset($entity->original)) {
            $entity->original->lingotek_processed = TRUE;
          }
          return;
        }
      }
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function lingotek_form_language_admin_add_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  \Drupal::service('lingotek.language_form')
    ->form($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function lingotek_form_language_admin_edit_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  \Drupal::service('lingotek.language_form')
    ->form($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function lingotek_form_language_content_settings_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  \Drupal::service('lingotek.language_content_settings_form')
    ->form($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'.
 */
function lingotek_form_field_config_edit_form_alter(array &$form, FormStateInterface $form_state) {
  \Drupal::service('lingotek.field_config_edit_form')
    ->form($form, $form_state);
}

/**
 * Implements hook_form_FORM_ID_alter() for 'lingotek_management'.
 */
function lingotek_form_lingotek_management_alter(array &$form, FormStateInterface $form_state) {
  $build_info = $form_state
    ->getBuildInfo();
  if ($build_info && isset($build_info['callback_object'])) {
    $formObject = $build_info['callback_object'];
    if ($formObject
      ->getEntityTypeId() === 'paragraph') {
      \Drupal::service('lingotek.paragraphs_bulk_form')
        ->form($form, $form_state);
    }
    if ($formObject
      ->getEntityTypeId() === 'media') {
      \Drupal::service('lingotek.media_bulk_form')
        ->form($form, $form_state);
    }
  }
}

/**
 * Implements hook_element_info_alter().
 */
function lingotek_element_info_alter(&$type) {
  \Drupal::service('lingotek.element_info_alter')
    ->type($type);
}

/**
 * Implements hook_theme().
 */
function lingotek_theme() {
  return [
    'lingotek_source_status' => [
      'variables' => [
        'entity' => NULL,
        'status' => '',
        'status_title' => '',
        'language' => NULL,
        'url' => NULL,
      ],
    ],
    'lingotek_target_status' => [
      'variables' => [
        'entity' => NULL,
        'language' => '',
        'status' => [],
        'url' => NULL,
        'status_text' => '',
        'new_window' => FALSE,
      ],
    ],
    'lingotek_target_statuses' => [
      'variables' => [
        'entity' => NULL,
        'source_langcode' => '',
        'statuses' => [],
      ],
    ],
  ];
}

/**
 * Prepares variables for lingotek source status formatter templates.
 *
 * Default template: lingotek_source_status.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - entity: The entity which status we want to display.
 *   - status: The source status.
 *   - status_title: The source status title.
 *   - language: The language object.
 *   - url: An optional \Drupal\Core\Url object.
 */
function template_preprocess_lingotek_source_status(&$variables) {
}

/**
 * Prepares variables for lingotek target status formatter templates.
 *
 * Default template: lingotek_target_statuses.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - entity: The entity which status we want to display.
 *   - source_langcode: The language code.
 *   - statuses: The source statuses, keyed by language code. The keys are:
 *     - status: The status for that translation.
 *     - url: An optional \Drupal\Core\Url object.
 *     - new_window: A flag indicating if the link should be opened in a new window.
 *     - status_text: The status text, mainly though for link title.
 *     - language: The language code.
 */
function template_preprocess_lingotek_target_statuses(&$variables) {
}

/**
 * Prepares variables for lingotek target status formatter templates.
 *
 * Default template: lingotek_target_status.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - entity: The entity which status we want to display.
 *   - language: The language code.
 *   - status: The status for that translation.
 *   - url: An optional \Drupal\Core\Url object.
 *   - new_window: A flag indicating if the link should be opened in a new window.
 *   - status_text: The status text, mainly though for link title.
 */
function template_preprocess_lingotek_target_status(&$variables) {
}

Functions

Namesort descending Description
lingotek_contextual_links_view_alter Implements hook_contextual_links_view_alter().
lingotek_element_info_alter Implements hook_element_info_alter().
lingotek_entity_base_field_info Implements hook_entity_base_field_info().
lingotek_entity_delete Implements hook_entity_delete().
lingotek_entity_insert Implements hook_entity_insert().
lingotek_entity_presave Implements hook_entity_presave().
lingotek_entity_translation_delete
lingotek_entity_translation_insert Implements hook_entity_translation_insert().
lingotek_entity_type_alter Implements hook_entity_type_alter().
lingotek_entity_update Implements hook_entity_update().
lingotek_form_alter Implements hook_form_alter().
lingotek_form_content_entity_form_submit
lingotek_form_field_config_edit_form_alter Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'.
lingotek_form_language_admin_add_form_alter Implements hook_form_FORM_ID_alter().
lingotek_form_language_admin_edit_form_alter Implements hook_form_FORM_ID_alter().
lingotek_form_language_content_settings_form_alter Implements hook_form_FORM_ID_alter().
lingotek_form_lingotek_management_alter Implements hook_form_FORM_ID_alter() for 'lingotek_management'.
lingotek_module_implements_alter Implements hook_module_implements_alter().
lingotek_theme Implements hook_theme().
lingotek_toolbar Implements hook_toolbar().
template_preprocess_lingotek_source_status Prepares variables for lingotek source status formatter templates.
template_preprocess_lingotek_target_status Prepares variables for lingotek target status formatter templates.
template_preprocess_lingotek_target_statuses Prepares variables for lingotek target status formatter templates.