protected function ContentEntitySource::doSaveTranslations

Saves translation data in an entity translation.

Parameters

\Drupal\Core\Entity\ContentEntityInterface $entity: The entity for which the translation should be saved.

array $data: The translation data for the fields.

string $target_langcode: The target language.

\Drupal\tmgmt\JobItemInterface $item: The job item.

bool $save: (optional) Whether to save the translation or not.

Throws

\Exception Thrown when a field or field offset is missing.

1 call to ContentEntitySource::doSaveTranslations()
ContentEntitySource::saveTranslation in sources/content/src/Plugin/tmgmt/Source/ContentEntitySource.php
Saves a translation.

File

sources/content/src/Plugin/tmgmt/Source/ContentEntitySource.php, line 492

Class

ContentEntitySource
Content entity source plugin controller.

Namespace

Drupal\tmgmt_content\Plugin\tmgmt\Source

Code

protected function doSaveTranslations(ContentEntityInterface $entity, array $data, $target_langcode, JobItemInterface $item, $save = TRUE) {

  // If the translation for this language does not exist yet, initialize it.
  if (!$entity
    ->hasTranslation($target_langcode)) {
    $entity
      ->addTranslation($target_langcode, $entity
      ->toArray());
  }
  $translation = $entity
    ->getTranslation($target_langcode);
  $manager = \Drupal::service('content_translation.manager');
  if ($manager
    ->isEnabled($translation
    ->getEntityTypeId(), $translation
    ->bundle())) {
    $manager
      ->getTranslationMetadata($translation)
      ->setSource($entity
      ->language()
      ->getId());
  }
  foreach (Element::children($data) as $field_name) {
    $field_data = $data[$field_name];
    if (!$translation
      ->hasField($field_name)) {
      throw new \Exception("Field '{$field_name}' does not exist on entity " . $translation
        ->getEntityTypeId() . '/' . $translation
        ->id());
    }
    $field = $translation
      ->get($field_name);
    $field_processor = $this
      ->getFieldProcessor($field
      ->getFieldDefinition()
      ->getType());
    $field_processor
      ->setTranslations($field_data, $field);
  }
  $embeddable_fields = static::getEmbeddableFields($entity);
  foreach ($embeddable_fields as $field_name => $field_definition) {
    if (!isset($data[$field_name])) {
      continue;
    }
    $field = $translation
      ->get($field_name);
    $target_type = $field
      ->getFieldDefinition()
      ->getFieldStorageDefinition()
      ->getSetting('target_type');
    $is_target_type_translatable = $manager
      ->isEnabled($target_type);

    // In case the target type is not translatable, the referenced entity will
    // be duplicated. As a consequence, remove all the field items from the
    // translation, update the field value to use the field object from the
    // source language.
    if (!$is_target_type_translatable) {
      $field = clone $entity
        ->get($field_name);
      if (!$translation
        ->get($field_name)
        ->isEmpty()) {
        $translation
          ->set($field_name, NULL);
      }
    }
    foreach (Element::children($data[$field_name]) as $delta) {
      $field_item = $data[$field_name][$delta];
      foreach (Element::children($field_item) as $property) {

        // Find the referenced entity. In case we are dealing with
        // untranslatable target types, the source entity will be returned.
        if ($target_entity = $this
          ->findReferencedEntity($field, $field_item, $delta, $property, $is_target_type_translatable)) {
          if ($is_target_type_translatable) {

            // If the field is an embeddable reference and the property is a
            // content entity, process it recursively.
            // If the field is ERR and the target entity supports
            // the needs saving interface, do not save it immediately to avoid
            // creating two versions when content moderation is used but just
            // ensure it will be saved.
            $target_save = TRUE;
            if ($field
              ->getFieldDefinition()
              ->getType() == 'entity_reference_revisions' && $target_entity instanceof EntityNeedsSaveInterface) {
              $target_save = FALSE;
              $target_entity
                ->needsSave();
            }
            $this
              ->doSaveTranslations($target_entity, $field_item[$property], $target_langcode, $item, $target_save);
          }
          else {
            $duplicate = $this
              ->createTranslationDuplicate($target_entity, $target_langcode);

            // Do not save the duplicate as it's going to be saved with the
            // main entity.
            $this
              ->doSaveTranslations($duplicate, $field_item[$property], $target_langcode, $item, FALSE);
            $translation
              ->get($field_name)
              ->set($delta, $duplicate);
          }
        }
      }
    }
  }
  if (static::isModeratedEntity($translation)) {

    // Use the given moderation status if set. Otherwise, fallback to the
    // configured one in TMGMT settings.
    if (isset($data['#moderation_state'][0])) {
      $moderation_state = $data['#moderation_state'][0];
    }
    else {
      $moderation_info = \Drupal::service('content_moderation.moderation_information');
      $workflow = $moderation_info
        ->getWorkflowForEntity($entity);
      $moderation_state = \Drupal::config('tmgmt_content.settings')
        ->get('default_moderation_states.' . $workflow
        ->id());
    }
    if ($moderation_state) {
      $translation
        ->set('moderation_state', $moderation_state);
    }
  }
  elseif (isset($data['#published'][0]) && $translation instanceof EntityPublishedInterface) {
    if ($data['#published'][0]) {
      $translation
        ->setPublished();
    }
    else {
      $translation
        ->setUnpublished();
    }
  }
  if ($entity
    ->getEntityType()
    ->isRevisionable()) {

    /** @var \Drupal\Core\Entity\TranslatableRevisionableStorageInterface $storage */
    $storage = \Drupal::entityTypeManager()
      ->getStorage($entity
      ->getEntityTypeId());
    if ($storage instanceof TranslatableRevisionableStorageInterface) {

      // Always create a new revision of the translation.
      $translation = $storage
        ->createRevision($translation, $translation
        ->isDefaultRevision());
      if ($entity instanceof RevisionLogInterface) {
        $translation
          ->setRevisionLogMessage($this
          ->t('Created by translation job <a href=":url">@label</a>.', [
          ':url' => $item
            ->getJob()
            ->toUrl()
            ->toString(),
          '@label' => $item
            ->label(),
        ]));
      }
    }
  }
  if ($save) {
    $translation
      ->save();
  }
}