You are here

lingotek.install in Lingotek Translation 8.2

Install, update and uninstall functions for the Lingotek module.

File

lingotek.install
View source
<?php

/**
 * @file
 * Install, update and uninstall functions for the Lingotek module.
 */
use Drupal\Component\Render\FormattableMarkup;
use Drupal\system\Entity\Action;
use Drupal\lingotek\Entity\LingotekContentMetadata;
use Drupal\Core\Entity\ContentEntityType;
use Drupal\lingotek\Entity\LingotekConfigMetadata;
use Drupal\config_translation\ConfigFieldMapper;
use Drupal\config_translation\ConfigEntityMapper;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\lingotek\Entity\LingotekProfile;

/**
 * Implements hook_install().
 */
function lingotek_install() {

  // Assign a fairly low weight to ensure our implementation of
  // hook_module_implements_alter() is run after content_translation.
  module_set_weight('lingotek', 15);
}

/**
 * Implements hook_schema().
 */
function lingotek_schema() {
  $schema['lingotek_content_metadata'] = [
    'description' => 'Stores Lingotek-related metadata about Drupal entities.',
    'fields' => [
      'document_id' => [
        'description' => 'The Lingotek document identifier.',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ],
      'entity_type' => [
        'description' => 'The entity type (node, comment, etc.).',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ],
      'entity_id' => [
        'description' => 'The primary identifier for the entity.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
    ],
    'primary key' => [
      'document_id',
    ],
  ];
  $schema['lingotek_translation_agent'] = [
    'description' => 'An assignment of IDs to agents from which translations were added.',
    'fields' => [
      'id' => [
        'description' => 'the ID assigned to a given translation agent.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'name' => [
        'description' => 'The name of a given tool for adding translations.',
        'type' => 'varchar',
        'length' => 63,
        'not null' => TRUE,
        'default' => '',
      ],
    ],
    'primary key' => [
      'id',
    ],
  ];
  $schema['lingotek_config_map'] = [
    'description' => 'An assignment of lids from locales_source and locales_target to set_ids for translation by Lingotek.',
    'fields' => [
      'lid' => [
        'description' => 'The ID assigned by the i18n_string module.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'set_id' => [
        'description' => 'The ID of the set assigned to the string by the Lingotek Translation module.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'current' => [
        'description' => 'Tells whether the translation for the individual config item is dirty and needs to be updated or not.',
        'type' => 'int',
        'size' => 'tiny',
        'not null' => TRUE,
        'default' => 0,
      ],
    ],
    'primary key' => [
      'lid',
    ],
  ];
  return $schema;
}

/**
 * Implements hook_update_N().
 */
function lingotek_update_8001() {

  // Get all mappers and update config entity ones, but not field ones.

  /** @var \Drupal\config_translation\ConfigMapperManager $mapper_manager */
  $mapper_manager = \Drupal::service('plugin.manager.config_translation.mapper');
  $mappers = $mapper_manager
    ->getMappers();
  foreach ($mappers as $mapper_id => $mapper) {
    if ($mapper instanceof ConfigEntityMapper && !$mapper instanceof ConfigFieldMapper) {
      $ids = \Drupal::entityTypeManager()
        ->getStorage($mapper_id)
        ->getQuery()
        ->exists('third_party_settings.lingotek.lingotek_document_id')
        ->execute();
      if (!empty($ids)) {

        /** @var \Drupal\Core\Config\Entity\ConfigEntityInterface[] $entities */
        $entities = \Drupal::entityTypeManager()
          ->getStorage($mapper_id)
          ->loadMultiple($ids);
        foreach ($entities as $entity) {
          $settings = $entity
            ->getThirdPartySettings('lingotek');
          $metadata = LingotekConfigMetadata::loadByConfigName($entity
            ->getEntityTypeId() . '.' . $entity
            ->id());
          $metadata
            ->setDocumentId($settings['lingotek_document_id']);
          $metadata
            ->setSourceStatus($settings['lingotek_translation_source']);
          $metadata
            ->setTargetStatus($settings['lingotek_translation_status']);
          $metadata
            ->setHash($settings['lingotek_hash']);
          $metadata
            ->save();
          $entity
            ->unsetThirdPartySetting('lingotek', 'lingotek_document_id');
          $entity
            ->unsetThirdPartySetting('lingotek', 'lingotek_translation_source');
          $entity
            ->unsetThirdPartySetting('lingotek', 'lingotek_translation_status');
          $entity
            ->unsetThirdPartySetting('lingotek', 'lingotek_hash');
          $entity
            ->save();
        }
      }
    }
  }

  // Take care of fields now.
  $ids = \Drupal::entityTypeManager()
    ->getStorage('field_config')
    ->getQuery()
    ->exists('third_party_settings.lingotek.lingotek_document_id')
    ->execute();
  if (!empty($ids)) {
    $entities = \Drupal::entityTypeManager()
      ->getStorage('field_config')
      ->loadMultiple($ids);
    foreach ($entities as $entity) {
      $settings = $entity
        ->getThirdPartySettings('lingotek');
      $metadata = LingotekConfigMetadata::loadByConfigName($entity
        ->getEntityTypeId() . '.' . $entity
        ->id());
      $metadata
        ->setDocumentId($settings['lingotek_document_id']);
      $metadata
        ->setSourceStatus($settings['lingotek_translation_source']);
      $metadata
        ->setTargetStatus($settings['lingotek_translation_status']);
      $metadata
        ->setHash($settings['lingotek_hash']);
      $metadata
        ->save();
      $entity
        ->unsetThirdPartySetting('lingotek', 'lingotek_document_id');
      $entity
        ->unsetThirdPartySetting('lingotek', 'lingotek_translation_source');
      $entity
        ->unsetThirdPartySetting('lingotek', 'lingotek_translation_status');
      $entity
        ->unsetThirdPartySetting('lingotek', 'lingotek_hash');
      $entity
        ->save();
    }
  }
}

/**
 * Update lingotek_profile definition after adding the lingotek prefix.
 */
function lingotek_update_8002() {
  $manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = $manager
    ->getEntityType('profile');
  $entity_type
    ->set('id', 'lingotek_profile');
  $manager
    ->installEntityType($entity_type);
}

/**
 * Clear route names cache.
 */
function lingotek_update_8003() {

  // We changed a route name, so we need to ensure that the routing caches are
  // cleared.
}

/**
 * Migrate Lingotek content metadata from fields to its own entity.
 */
function lingotek_update_8011(&$sandbox) {

  // We need a temporary table for storing this data.
  $temp_schema['lingotek_temporary_content_metadata'] = [
    'fields' => [
      'entity_type' => [
        'description' => 'The entity type (node, comment, etc.).',
        'type' => 'varchar',
        'length' => 128,
        'not null' => TRUE,
        'default' => '',
      ],
      'entity_id' => [
        'description' => 'The primary identifier for the entity.',
        'type' => 'int',
        'unsigned' => TRUE,
        'not null' => TRUE,
        'default' => 0,
      ],
      'document_id' => [
        'description' => 'The Lingotek document identifier.',
        'type' => 'varchar',
        'length' => 128,
        'not null' => FALSE,
        'default' => NULL,
      ],
      'hash' => [
        'description' => 'The Lingotek hash.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
        'default' => NULL,
      ],
      'profile' => [
        'description' => 'The Lingotek profile being used.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
        'default' => NULL,
      ],
      'translation_source' => [
        'description' => 'The Lingotek translation source.',
        'type' => 'varchar',
        'length' => 255,
        'not null' => FALSE,
        'default' => '',
      ],
      'translation_status' => [
        'description' => 'The Lingotek translation status.',
        'type' => 'blob',
        'not null' => TRUE,
      ],
    ],
    'primary key' => [
      'entity_type',
      'entity_id',
    ],
  ];
  if (!isset($sandbox['step'])) {

    // We need the temporary table.
    if (!\Drupal::database()
      ->schema()
      ->tableExists('lingotek_temporary_content_metadata')) {
      \Drupal::database()
        ->schema()
        ->createTable('lingotek_temporary_content_metadata', $temp_schema['lingotek_temporary_content_metadata']);
    }

    // We fetch all the entities we have info about.
    $entities = \Drupal::database()
      ->select('lingotek_content_metadata', 'lcm')
      ->fields('lcm', [
      'entity_id',
      'entity_type',
    ])
      ->execute()
      ->fetchAll();
    \Drupal::logger('lingotek')
      ->debug('Entities to update: %count', [
      '%count' => count($entities),
    ]);

    // We start collecting data.
    $sandbox['step'] = 'collect';

    // Initialize the sandbox.
    $sandbox['entities'] = $entities;
    $sandbox['progress'] = 0;
  }

  // We need to collect all the data.
  if (isset($sandbox['step']) && $sandbox['step'] === 'collect') {
    $entities = $sandbox['entities'];
    $sandbox['max'] = count($entities);
    $count = 0;
    for ($i = $sandbox['progress']; $count < 10 && $i < $sandbox['max']; $i++, $count++) {
      $entity_data = (array) $entities[$i];
      $entity_type_id = $entity_data['entity_type'];

      /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */
      $storage = \Drupal::entityTypeManager()
        ->getStorage($entity_type_id);
      $entity = $storage
        ->load($entity_data['entity_id']);
      if ($entity) {
        $lingotek_document_id = $entity->lingotek_document_id->value;
        $lingotek_hash = $entity->lingotek_hash->value;
        $lingotek_profile = $entity->lingotek_profile->entity;
        $lingotek_profile_id = $lingotek_profile !== NULL ? $lingotek_profile
          ->id() : NULL;
        $lingotek_translation_source = $entity->lingotek_translation_source->value;
        $lingotek_translation_status = lingotek_legacy_get_translation_status($entity->lingotek_translation_status);
        \Drupal::logger('lingotek')
          ->debug('Storing temporary data for entity %entity_type %entity_id with document id %document_id', [
          '%entity_type' => $entity
            ->getEntityTypeId(),
          '%entity_id' => $entity
            ->id(),
          '%document_id' => $lingotek_document_id,
        ]);
        \Drupal::database()
          ->merge('lingotek_temporary_content_metadata')
          ->fields([
          'entity_type' => $entity
            ->getEntityTypeId(),
          'entity_id' => $entity
            ->id(),
          'document_id' => $lingotek_document_id,
          'hash' => $lingotek_hash,
          'profile' => $lingotek_profile_id,
          'translation_source' => $lingotek_translation_source,
          'translation_status' => json_encode($lingotek_translation_status),
        ])
          ->keys([
          'entity_type',
          'entity_id',
        ], [
          $entity
            ->getEntityTypeId(),
          $entity
            ->id(),
        ])
          ->execute();
      }
      $sandbox['progress']++;
      $sandbox['#finished'] = empty($sandbox['max']) ? 1 : $sandbox['progress'] / $sandbox['max'];
    }
    if (empty($entities) || $sandbox['#finished'] === 1) {

      // If we are finished, we must store everything now after installing our entity.
      $sandbox['#finished'] = 0;
      $sandbox['progress'] = 0;
      $sandbox['step'] = 'store';
      unset($sandbox['entities']);
      unset($sandbox['max']);
    }
  }

  // We need to store all the data.
  if (isset($sandbox['step']) && $sandbox['step'] === 'store') {

    // First we install the entity.
    if ($sandbox['progress'] === 0 && !isset($sandbox['max'])) {

      /** @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $entity_definition_update_manager */
      $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
      $entity_definition_update_manager
        ->installEntityType(new ContentEntityType([
        'id' => 'lingotek_content_metadata',
        'label' => new TranslatableMarkup("Lingotek Content Metadata"),
        'base_table' => 'lingotek_metadata',
        'data_table' => 'lingotek_metadata_field_data',
        'entity_keys' => [
          'id' => 'id',
        ],
      ]));
      $fields['id'] = BaseFieldDefinition::create('integer')
        ->setLabel(new TranslatableMarkup('ID'))
        ->setReadOnly(TRUE)
        ->setSetting('unsigned', TRUE);
      $fields['content_entity_type_id'] = BaseFieldDefinition::create('string')
        ->setLabel(new TranslatableMarkup('Content entity type ID'))
        ->setDescription(new TranslatableMarkup('The ID of the content entity type this Lingotek status is for.'))
        ->setRequired(TRUE);
      $fields['content_entity_id'] = BaseFieldDefinition::create('integer')
        ->setLabel(new TranslatableMarkup('Content entity ID'))
        ->setDescription(new TranslatableMarkup('The ID of the content entity this Lingotek status is for.'))
        ->setRequired(TRUE);
      $fields['document_id'] = BaseFieldDefinition::create('string')
        ->setLabel(new TranslatableMarkup('Lingotek document id'))
        ->setDescription(new TranslatableMarkup('The Lingotek document id.'));
      $fields['hash'] = BaseFieldDefinition::create('string')
        ->setLabel(new TranslatableMarkup('Lingotek hash'))
        ->setDescription(new TranslatableMarkup('A hash of the Lingotek saved entity data, required for checking for changes.'));
      $fields['profile'] = BaseFieldDefinition::create('entity_reference')
        ->setLabel(new TranslatableMarkup('Lingotek profile'))
        ->setDescription(new TranslatableMarkup('The Lingotek profile defining this translation.'))
        ->setSetting('target_type', 'lingotek_profile');
      $fields['translation_source'] = BaseFieldDefinition::create('language')
        ->setLabel(new TranslatableMarkup('Lingotek translation source'))
        ->setDescription(new TranslatableMarkup('The source language from which this translation was created.'))
        ->setDefaultValue(LanguageInterface::LANGCODE_NOT_SPECIFIED)
        ->setTranslatable(TRUE);
      $fields['translation_status'] = BaseFieldDefinition::create('lingotek_language_key_value')
        ->setLabel(new TranslatableMarkup('Lingotek translation status'))
        ->setDescription(new TranslatableMarkup('The status of the source in case of being the source translation, or the status of the translation.'))
        ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED);
      foreach ($fields as $name => $storage_definition) {
        $entity_definition_update_manager
          ->installFieldStorageDefinition($name, 'lingotek_content_metadata', 'lingotek', $storage_definition);
      }

      // ToDo: Remove the fields when possible. See https://www.drupal.org/node/2859665
      // We need to keep these until we can purge data.
      // See https://www.drupal.org/node/2282119.
    }
    if (!isset($sandbox['entities'])) {

      // We fetch all the entities we have info about.
      $entities = \Drupal::database()
        ->select('lingotek_temporary_content_metadata', 'lcm')
        ->fields('lcm', [
        'entity_id',
        'entity_type',
        'hash',
        'document_id',
        'profile',
        'translation_source',
        'translation_status',
      ])
        ->execute()
        ->fetchAll();
      if (!$entities) {

        // There are no entity metadata stored. We must be done.
        $sandbox['#finished'] = 1;
        return;
      }
      $sandbox['entities'] = $entities;
      $sandbox['max'] = count($entities);
      $sandbox['progress'] = 0;
    }
    $count = 0;
    for ($i = $sandbox['progress']; $count < 10 && $i < $sandbox['max']; $i++, $count++) {
      $entity_data = (array) $sandbox['entities'][$i];
      $entity = \Drupal::entityTypeManager()
        ->getStorage($entity_data['entity_type'])
        ->load($entity_data['entity_id']);
      if ($entity) {
        $metadata = LingotekContentMetadata::create([
          'content_entity_type_id' => $entity_data['entity_type'],
          'content_entity_id' => $entity_data['entity_id'],
          'document_id' => $entity_data['document_id'],
          'hash' => $entity_data['hash'],
          'profile' => $entity_data['profile'],
          'translation_source' => $entity_data['translation_source'],
        ]);
        lingotek_legacy_set_translation_status($metadata, $entity_data['translation_status']);
        $metadata
          ->save();
      }
      $sandbox['progress']++;
      $sandbox['#finished'] = empty($sandbox['max']) ? 1 : $sandbox['progress'] / $sandbox['max'];
      if ($sandbox['#finished'] === 1) {

        // If we are finished, we must clear the temporary table.
        \Drupal::database()
          ->schema()
          ->dropTable('lingotek_temporary_content_metadata');
        unset($sandbox['step']);
      }
    }
  }
}

/**
 * Change module weight to ensure lingotek hooks run after content_translation.
 */
function lingotek_update_8201() {

  // Assign a fairly low weight to ensure our implementation of
  // hook_module_implements_alter() is run after content_translation.
  // It changed in https://www.drupal.org/node/2679008
  module_set_weight('lingotek', 15);
}

/**
 * Set the new default intelligence configuration
 */
function lingotek_update_8204() {
  $config_factory = \Drupal::configFactory();
  $config = $config_factory
    ->getEditable('lingotek.settings');
  $config
    ->set('intelligence', [
    'business_unit' => NULL,
    'business_division' => NULL,
    'campaign_id' => NULL,
    'campaign_rating' => 0,
    'channel' => NULL,
    'contact_name' => NULL,
    'contact_email' => NULL,
    'content_description' => NULL,
    'external_style_id' => NULL,
    'purchase_order' => NULL,
    'region' => NULL,
    'use_author' => TRUE,
    'default_author_email' => NULL,
    'use_author_email' => TRUE,
    'use_contact_email_for_author' => FALSE,
    'use_business_unit' => TRUE,
    'use_business_division' => TRUE,
    'use_campaign_id' => TRUE,
    'use_campaign_rating' => TRUE,
    'use_channel' => TRUE,
    'use_contact_name' => TRUE,
    'use_contact_email' => TRUE,
    'use_content_description' => TRUE,
    'use_external_style_id' => TRUE,
    'use_purchase_order' => TRUE,
    'use_region' => TRUE,
    'use_base_domain' => TRUE,
    'use_reference_url' => TRUE,
  ]);
  $config
    ->save();
}

/**
 * Set the default filter for existing profiles and settings.
 */
function lingotek_update_8205() {
  $config_factory = \Drupal::configFactory();
  $config = $config_factory
    ->getEditable('lingotek.settings');
  $config
    ->set('default.filter', 'project_default');
  $config
    ->set('default.subfilter', 'project_default');
  $config
    ->set('account.resources.filter', []);
  $config
    ->save();

  /** @var \Drupal\lingotek\Entity\LingotekProfile $profiles */
  $profiles = LingotekProfile::loadMultiple();
  foreach ($profiles as $id => $profile) {
    $profile
      ->setFilter('project_default');
    $profile
      ->setSubfilter('project_default');
    $profile
      ->save();
  }
}

/**
 * Install the job_id field definition in Lingotek content metadata.
 */
function lingotek_update_8206() {
  $fields = [];
  $fields['job_id'] = BaseFieldDefinition::create('string')
    ->setLabel(new TranslatableMarkup('Lingotek job id'))
    ->setDescription(new TranslatableMarkup('The Lingotek job id.'));
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  foreach ($fields as $name => $storage_definition) {
    $entity_definition_update_manager
      ->installFieldStorageDefinition($name, 'lingotek_content_metadata', 'lingotek', $storage_definition);
  }
}

/**
 * Clear route names cache.
 */
function lingotek_update_8207() {

  // We added routes, so we need to ensure that the routing caches are cleared.
}
function lingotek_update_8208() {

  /** @var \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entity_repository */
  $entity_repository = \Drupal::service('entity.last_installed_schema.repository');
  $entity_type = $entity_repository
    ->getLastInstalledDefinition('lingotek_content_metadata');
  $entity_type
    ->set('data_table', NULL);
  $entity_type
    ->setHandlerClass('views_data', '\\Drupal\\lingotek\\Views\\LingotekContentMetadataViewsData');
  $entity_repository
    ->setLastInstalledDefinition($entity_type);
  $definitions = $entity_repository
    ->getLastInstalledFieldStorageDefinitions('lingotek_content_metadata');
  if (isset($definitions['translation_source'])) {
    $entity_repository
      ->deleteLastInstalledFieldStorageDefinition($definitions['translation_source']);
  }
}

/**
 * Change the lingotek_target_status id to lingotek_target_statuses.
 */
function lingotek_update_8209() {
  $config_factory = \Drupal::configFactory();
  $message = NULL;
  $ids = [];
  foreach ($config_factory
    ->listAll('views.view.') as $view_config_name) {
    $changed = FALSE;
    $view = $config_factory
      ->getEditable($view_config_name);
    $displays = $view
      ->get('display');
    foreach ($displays as $display_name => $display) {
      if (!empty($display['display_options']['fields'])) {
        foreach ($display['display_options']['fields'] as $field_name => $field) {
          if (isset($field['type']) && $field['type'] === 'lingotek_translation_status') {
            $base = "display.{$display_name}.display_options.fields.{$field_name}";
            $view
              ->set($base . '.type', 'lingotek_translation_statuses');
            $changed = TRUE;
          }
        }
      }
    }
    if ($changed) {
      $ids[] = $view
        ->get('id');
      $view
        ->save(TRUE);
    }
  }
  if (!empty($ids)) {
    $message = \Drupal::translation()
      ->translate('Updated field plugins for views: @ids', [
      '@ids' => implode(', ', array_unique($ids)),
    ]);
  }
  return $message;
}

/**
 * Install needed actions if action module and lingotek are enabled.
 */
function lingotek_update_8210() {
  if (!\Drupal::moduleHandler()
    ->moduleExists('action')) {
    return;
  }
  $actions = [
    'entity:lingotek_upload_action',
    'entity:lingotek_check_upload_action',
    'entity:lingotek_request_translations_action',
    'entity:lingotek_check_translations_action',
    'entity:lingotek_download_translations_action',
    'entity:lingotek_disassociate_action',
  ];
  $enabled_entity_types = \Drupal::service('lingotek.configuration')
    ->getEnabledEntityTypes();
  foreach ($enabled_entity_types as $entity_type_id => $entity_type) {
    foreach ($actions as $action) {
      $pluginId = $action . ':' . $entity_type_id;

      /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
      $plugin = \Drupal::service('plugin.manager.action')
        ->getDefinition($pluginId);
      $action_id = $entity_type_id . '_' . str_replace('entity:', '', $action);
      Action::create([
        'id' => $action_id,
        'label' => $plugin['label'],
        'type' => $entity_type_id,
        'plugin' => $pluginId,
        'configuration' => [],
      ])
        ->save();
    }
  }
}

/**
 * The default for appending content type to the document name was changed
 * so make sure current users continue to see the same behavior as before the update.
 */
function lingotek_update_8211() {

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');
  $lingotek_config
    ->setPreference('append_type_to_title', TRUE);
}

/**
 * Set the default filter for existing profiles and settings.
 */
function lingotek_update_8212() {
  $config_factory = \Drupal::configFactory();
  $config = $config_factory
    ->getEditable('lingotek.settings');
  $modified = FALSE;
  if ($config
    ->get('default.filter') === 'project_default') {
    $config
      ->set('default.filter', 'drupal_default');
    $modified = TRUE;
  }
  if ($config
    ->get('default.subfilter') === 'project_default') {
    $config
      ->set('default.subfilter', 'drupal_default');
    $modified = TRUE;
  }
  if ($modified) {
    $config
      ->save();
  }

  /** @var \Drupal\lingotek\Entity\LingotekProfile $profiles */
  $profiles = LingotekProfile::loadMultiple();
  $modified = FALSE;
  foreach ($profiles as $id => $profile) {
    if ($profile
      ->getFilter() === 'project_default') {
      $profile
        ->setFilter('drupal_default');
      $modified = TRUE;
    }
    if ($profile
      ->getSubfilter() === 'project_default') {
      $profile
        ->setSubfilter('drupal_default');
      $modified = TRUE;
    }
    if ($modified) {
      $profile
        ->save();
      $modified = FALSE;
    }
  }
}

/**
 * Empty on purpose.
 */
function lingotek_update_8213() {

  // Needed for LingotekModuleUninstallWith8x1xDataTest to pass.
}

/**
 * Create actions for enabled entity types per target language.
 */
function lingotek_update_8214() {

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotek_config */
  $lingotek_config = \Drupal::service('lingotek.configuration');
  $action_manager = \Drupal::service('plugin.manager.action');
  $lang_actions = [
    'entity:lingotek_check_translation_action',
    'entity:lingotek_download_translation_action',
    'entity:lingotek_request_translation_action',
  ];
  $languages = \Drupal::languageManager()
    ->getLanguages();
  $entity_types = \Drupal::entityTypeManager()
    ->getDefinitions();
  $enabled_entity_types = $lingotek_config
    ->getEnabledEntityTypes();
  foreach ($entity_types as $entity_type_id => $entity_type) {
    foreach ($lang_actions as $action) {
      foreach ($languages as $langcode => $language) {
        $pluginId = $action . ':' . $entity_type_id;

        /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
        $plugin = $action_manager
          ->getDefinition($pluginId, FALSE);
        $action_id = $entity_type_id . '_' . $langcode . '_' . str_replace('entity:', '', $action);
        $existingAction = \Drupal::entityTypeManager()
          ->getStorage('action')
          ->load($action_id);
        if ($plugin && isset($enabled_entity_types[$entity_type_id]) && !$existingAction) {
          Action::create([
            'id' => $action_id,
            'label' => new FormattableMarkup($plugin['action_label'], [
              '@entity_label' => $entity_type
                ->getSingularLabel(),
              '@language' => $language
                ->getName(),
            ]),
            'type' => $entity_type_id,
            'plugin' => $pluginId,
            'configuration' => [
              'language' => $langcode,
            ],
          ])
            ->save();
        }
        elseif (!isset($enabled_entity_types[$entity_type_id]) && $existingAction) {
          $existingAction
            ->delete();
        }
      }
    }
  }
}

/**
 * Remove old unused Lingotek metadata fields from content entities.
 */
function lingotek_update_8215() {
  $fields = [
    'lingotek_document_id',
    'lingotek_hash',
    'lingotek_profile',
    'lingotek_translation_source',
    'lingotek_translation_status',
    'lingotek_translation_created',
    'lingotek_translation_changed',
  ];

  /** @var \Drupal\Core\Entity\EntityDefinitionUpdateManagerInterface $entity_definition_update_manager */
  $connection = \Drupal::database();
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type_manager = \Drupal::entityTypeManager();
  $entities = $entity_type_manager
    ->getDefinitions();
  foreach ($entities as $entity_type_id => $entity_type) {
    foreach ($fields as $field) {
      if ($field_definition = $entity_definition_update_manager
        ->getFieldStorageDefinition($field, $entity_type_id)) {
        try {

          // Data was migrated in lingotek_update_8011, we can delete values from
          // columns or tables without looking behind now.
          if ($field !== 'lingotek_translation_status') {
            $connection
              ->update($entity_type
              ->getDataTable())
              ->fields([
              $field => NULL,
            ])
              ->execute();
            $message = new FormattableMarkup('%field_name values deleted for entity %entity_type_id', [
              '%field_name' => $field,
              '%entity_type_id' => $entity_type_id,
            ]);
            \Drupal::messenger()
              ->addWarning($message);
            \Drupal::logger('lingotek')
              ->warning($message);
          }
          else {
            $data_table_name = _lingotek_get_deleted_translation_status_data_table_name($entity_type_id);
            $tables = [
              $data_table_name,
            ];
            if ($entity_type
              ->isRevisionable()) {
              $revision_table_name = _lingotek_get_deleted_translation_status_revision_table_name($entity_type_id);
              $tables[] = $revision_table_name;
            }
            foreach ($tables as $table_name) {
              $connection
                ->schema()
                ->dropTable($table_name);
              $message = new FormattableMarkup('%table deleted for updating entity %entity_type_id field %field_name', [
                '%table' => $table_name,
                '%field_name' => $field,
                '%entity_type_id' => $entity_type_id,
              ]);
              \Drupal::messenger()
                ->addWarning($message);
              \Drupal::logger('lingotek')
                ->warning($message);
            }
          }
        } catch (\Exception $e) {
          $error = new FormattableMarkup('%field_name values deletion previous to field deletion failed for entity %entity_type_id with message: %message', [
            '%field_name' => $field,
            '%entity_type_id' => $entity_type_id,
            '%message' => $e
              ->getMessage(),
          ]);
          \Drupal::messenger()
            ->addError($error);
          \Drupal::logger('lingotek')
            ->error($error);
        }
        try {
          $entity_definition_update_manager
            ->uninstallFieldStorageDefinition($field_definition);
          \Drupal::messenger()
            ->addStatus(new FormattableMarkup('%field_name deleted for entity %entity_type_id', [
            '%field_name' => $field,
            '%entity_type_id' => $entity_type_id,
          ]));
        } catch (\Exception $e) {
          $error = new FormattableMarkup('%field_name deletion failed for entity %entity_type_id with message: %message', [
            '%field_name' => $field,
            '%entity_type_id' => $entity_type_id,
            '%message' => $e
              ->getMessage(),
          ]);
          \Drupal::messenger()
            ->addError($error);
          \Drupal::logger('lingotek')
            ->error($error);
        }
      }
      else {
        \Drupal::messenger()
          ->addWarning(new FormattableMarkup('%field_name not found in entity %entity_type_id', [
          '%field_name' => $field,
          '%entity_type_id' => $entity_type_id,
        ]));
      }
    }
  }
}

/**
 * Install needed actions if action module and lingotek are enabled.
 */
function lingotek_update_8216() {
  $action_manager = \Drupal::service('plugin.manager.action');
  $actions = [
    'entity:lingotek_delete_translations_action',
  ];
  $lang_actions = [
    'entity:lingotek_delete_translation_action',
  ];
  $languages = \Drupal::languageManager()
    ->getLanguages();
  $enabled_entity_types = \Drupal::service('lingotek.configuration')
    ->getEnabledEntityTypes();
  foreach ($enabled_entity_types as $entity_type_id => $entity_type) {
    foreach ($actions as $action) {
      $pluginId = $action . ':' . $entity_type_id;

      /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
      $plugin = \Drupal::service('plugin.manager.action')
        ->getDefinition($pluginId);
      $action_id = $entity_type_id . '_' . str_replace('entity:', '', $action);
      Action::create([
        'id' => $action_id,
        'label' => $plugin['label'],
        'type' => $entity_type_id,
        'plugin' => $pluginId,
        'configuration' => [],
      ])
        ->save();
    }
    foreach ($lang_actions as $action) {
      foreach ($languages as $langcode => $language) {
        $pluginId = $action . ':' . $entity_type_id;

        /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
        $plugin = $action_manager
          ->getDefinition($pluginId, FALSE);
        $action_id = $entity_type_id . '_' . $langcode . '_' . str_replace('entity:', '', $action);
        $existingAction = \Drupal::entityTypeManager()
          ->getStorage('action')
          ->load($action_id);
        if ($plugin && isset($enabled_entity_types[$entity_type_id]) && !$existingAction) {
          Action::create([
            'id' => $action_id,
            'label' => new FormattableMarkup($plugin['action_label'], [
              '@entity_label' => $entity_type
                ->getSingularLabel(),
              '@language' => $language
                ->getName(),
            ]),
            'type' => $entity_type_id,
            'plugin' => $pluginId,
            'configuration' => [
              'language' => $langcode,
            ],
          ])
            ->save();
        }
        elseif (!isset($enabled_entity_types[$entity_type_id]) && $existingAction) {
          $existingAction
            ->delete();
        }
      }
    }
  }
}

/**
 * Move Lingotek profile to config metadata from settings.
 */
function lingotek_update_8217() {
  $lingotekSettings = \Drupal::configFactory()
    ->getEditable('lingotek.settings');
  $keys = [];
  $data = $lingotekSettings
    ->get('translate.config');
  _lingotek_find_key($keys, '', $data);

  /** @var \Drupal\Core\Config\ConfigManagerInterface $config_manager */
  $config_manager = \Drupal::service('config.manager');

  /** @var \Drupal\lingotek\LingotekConfigurationServiceInterface $lingotekConfig */
  $lingotekConfig = \Drupal::service('lingotek.configuration');
  foreach ($keys as $plugin_id) {
    $entity_type = $rootLabel = substr($plugin_id, 0, strpos($plugin_id, '.'));
    $entity_name = substr_replace($plugin_id, '', 0, strlen($entity_type) + 1);

    // Check if it's a field.
    if (substr($entity_type, -7) == '_fields') {

      // Hack for fields, the entity is field config.
      $entity_type = 'field_config';
    }
    if (\Drupal::entityTypeManager()
      ->hasDefinition($entity_type) && ($entity = \Drupal::entityTypeManager()
      ->getStorage($entity_type)
      ->load($entity_name))) {
      $profile_key = 'translate.config.' . $plugin_id . '.profile';
      $profile_id = $lingotekSettings
        ->get($profile_key);
      $lingotekConfig
        ->setConfigEntityProfile($entity, $profile_id);

      // Clear old value.
      foreach ($data as $type => $typeData) {
        foreach ($typeData as $key => $value) {
          if (!in_array($key, [
            'enabled',
            'profile',
          ])) {
            $lingotekSettings
              ->clear('translate.config.' . $rootLabel . '.' . $key);
          }
        }
      }
    }
    else {
      $profile_key = 'translate.config.' . $plugin_id . '.profile';
      $profile_id = $lingotekSettings
        ->get($profile_key);

      /** @var \Drupal\config_translation\ConfigNamesMapper $mapper */
      $mapper = _lingotek_get_mapper($plugin_id);
      if ($mapper) {
        $lingotekConfig
          ->setConfigProfile($plugin_id, $profile_id);
        $lingotekSettings
          ->clear('translate.config.' . $plugin_id);
      }
    }
  }
  $lingotekSettings
    ->save();
}

/**
 * Remove delete_tms_documents_upon_disassociation preference from lingotek.settings.
 */
function lingotek_update_8218() {
  $lingotekSettings = \Drupal::configFactory()
    ->getEditable('lingotek.settings');
  $lingotekSettings
    ->clear('preference.delete_tms_documents_upon_disassociation');
  $lingotekSettings
    ->save();
}

/**
 * Install needed actions if action module and lingotek are enabled.
 */
function lingotek_update_8219() {

  /** @var \Drupal\Core\Action\ActionManager $action_manager */
  $action_manager = \Drupal::service('plugin.manager.action');
  $actions = [
    'entity:lingotek_cancel_action',
  ];
  $lang_actions = [
    'entity:lingotek_cancel_translation_action',
  ];
  $languages = \Drupal::languageManager()
    ->getLanguages();
  $enabled_entity_types = \Drupal::service('lingotek.configuration')
    ->getEnabledEntityTypes();
  foreach ($enabled_entity_types as $entity_type_id => $entity_type) {
    foreach ($actions as $action) {
      $pluginId = $action . ':' . $entity_type_id;

      /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
      $plugin = \Drupal::service('plugin.manager.action')
        ->getDefinition($pluginId);
      $action_id = $entity_type_id . '_' . str_replace('entity:', '', $action);
      Action::create([
        'id' => $action_id,
        'label' => $plugin['label'],
        'type' => $entity_type_id,
        'plugin' => $pluginId,
        'configuration' => [],
      ])
        ->save();
    }
    foreach ($lang_actions as $action) {
      foreach ($languages as $langcode => $language) {
        $pluginId = $action . ':' . $entity_type_id;

        /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
        $plugin = $action_manager
          ->getDefinition($pluginId, FALSE);
        $action_id = $entity_type_id . '_' . $langcode . '_' . str_replace('entity:', '', $action);
        $existingAction = \Drupal::entityTypeManager()
          ->getStorage('action')
          ->load($action_id);
        if ($plugin && isset($enabled_entity_types[$entity_type_id]) && !$existingAction) {
          Action::create([
            'id' => $action_id,
            'label' => new FormattableMarkup($plugin['action_label'], [
              '@entity_label' => $entity_type
                ->getSingularLabel(),
              '@language' => $language
                ->getName(),
            ]),
            'type' => $entity_type_id,
            'plugin' => $pluginId,
            'configuration' => [
              'language' => $langcode,
            ],
          ])
            ->save();
        }
        elseif (!isset($enabled_entity_types[$entity_type_id]) && $existingAction) {
          $existingAction
            ->delete();
        }
      }
    }

    // Remove the disassociate one.
    $action = 'entity:lingotek_disassociate_action';
    $pluginId = $action . ':' . $entity_type_id;

    /** @var \Drupal\Component\Plugin\Definition\PluginDefinitionInterface $plugin */
    $plugin = $action_manager
      ->getDefinition($pluginId, FALSE);
    $action_id = $entity_type_id . '_' . str_replace('entity:', '', $action);
    $disassociateAction = Action::load($action_id);
    if ($disassociateAction) {
      $disassociateAction
        ->delete();
    }
  }
}

/**
 * Adds split_download_all preference to lingotek.settings.
 */
function lingotek_update_8220() {
  $lingotekSettings = \Drupal::configFactory()
    ->getEditable('lingotek.settings');
  $lingotekSettings
    ->set('preference.split_download_all', FALSE);
  $lingotekSettings
    ->save();
}

/**
 * Removes Lingotek Content Cloud unused settings.
 */
function lingotek_update_8221() {
  $lingotekSettings = \Drupal::configFactory()
    ->getEditable('lingotek.settings');
  $lingotekSettings
    ->clear('preference.enable_content_cloud');
  $lingotekSettings
    ->clear('preference.content_cloud_import_format');
  $lingotekSettings
    ->clear('preference.content_cloud_import_status');
  $lingotekSettings
    ->save();
}

/**
 * Adds enable_download_interim preference to lingotek.settings.
 */
function lingotek_update_8222() {

  // Default will be FALSE, but as we want to maintain the current behavior we
  // set this to TRUE.
  $lingotekSettings = \Drupal::configFactory()
    ->getEditable('lingotek.settings');
  $lingotekSettings
    ->set('preference.enable_download_interim', TRUE);
  $lingotekSettings
    ->save();
}
function _lingotek_find_key(&$keys, $id, array $array) {
  foreach ($array as $x => $y) {

    // if (!in_array($x, ['enabled', 'profile'])) {}
    if (is_array($y) && !in_array($id, [
      'enabled',
      'profile',
    ])) {
      $newId = empty($id) ? $x : $id . '.' . $x;
      _lingotek_find_key($keys, $newId, $y);
    }
    else {
      if (count($array) == 1) {
        $keys[] = $id;
      }
    }
  }
}
function lingotek_legacy_get_translation_status($field) {
  $status = [];
  foreach ($field
    ->getIterator() as $delta => $value) {
    $status[$value->language] = $value->value;
  }
  return $status;
}
function lingotek_legacy_set_translation_status(&$metadata, $value) {
  $statuses = json_decode($value);
  foreach ($statuses as $langcode => $status) {
    $metadata->translation_status
      ->appendItem([
      'language' => $langcode,
      'value' => $status,
    ]);
  }
}
function _lingotek_get_mapper($plugin_id) {

  /** @var \Drupal\config_translation\ConfigMapperManager $mapper_manager */
  $mapper_manager = \Drupal::service('plugin.manager.config_translation.mapper');
  $mappers = $mapper_manager
    ->getMappers();
  $mapper = isset($mappers[$plugin_id]) ? $mappers[$plugin_id] : NULL;
  return $mapper;
}
function _lingotek_get_deleted_translation_status_data_table_name($entity_type_id) {
  $unique_id = $entity_type_id . '-' . 'lingotek_translation_status';
  return "field_deleted_data_" . substr(hash('sha256', $unique_id), 0, 10);
}
function _lingotek_get_deleted_translation_status_revision_table_name($entity_type_id) {
  $unique_id = $entity_type_id . '-' . 'lingotek_translation_status';
  return "field_deleted_revision_" . substr(hash('sha256', $unique_id), 0, 10);
}

Functions

Namesort descending Description
lingotek_install Implements hook_install().
lingotek_legacy_get_translation_status
lingotek_legacy_set_translation_status
lingotek_schema Implements hook_schema().
lingotek_update_8001 Implements hook_update_N().
lingotek_update_8002 Update lingotek_profile definition after adding the lingotek prefix.
lingotek_update_8003 Clear route names cache.
lingotek_update_8011 Migrate Lingotek content metadata from fields to its own entity.
lingotek_update_8201 Change module weight to ensure lingotek hooks run after content_translation.
lingotek_update_8204 Set the new default intelligence configuration
lingotek_update_8205 Set the default filter for existing profiles and settings.
lingotek_update_8206 Install the job_id field definition in Lingotek content metadata.
lingotek_update_8207 Clear route names cache.
lingotek_update_8208
lingotek_update_8209 Change the lingotek_target_status id to lingotek_target_statuses.
lingotek_update_8210 Install needed actions if action module and lingotek are enabled.
lingotek_update_8211 The default for appending content type to the document name was changed so make sure current users continue to see the same behavior as before the update.
lingotek_update_8212 Set the default filter for existing profiles and settings.
lingotek_update_8213 Empty on purpose.
lingotek_update_8214 Create actions for enabled entity types per target language.
lingotek_update_8215 Remove old unused Lingotek metadata fields from content entities.
lingotek_update_8216 Install needed actions if action module and lingotek are enabled.
lingotek_update_8217 Move Lingotek profile to config metadata from settings.
lingotek_update_8218 Remove delete_tms_documents_upon_disassociation preference from lingotek.settings.
lingotek_update_8219 Install needed actions if action module and lingotek are enabled.
lingotek_update_8220 Adds split_download_all preference to lingotek.settings.
lingotek_update_8221 Removes Lingotek Content Cloud unused settings.
lingotek_update_8222 Adds enable_download_interim preference to lingotek.settings.
_lingotek_find_key
_lingotek_get_deleted_translation_status_data_table_name
_lingotek_get_deleted_translation_status_revision_table_name
_lingotek_get_mapper