You are here

public function FieldTranslationSynchronizer::synchronizeFields in Zircon Profile 8.0

Same name and namespace in other branches
  1. 8 core/modules/content_translation/src/FieldTranslationSynchronizer.php \Drupal\content_translation\FieldTranslationSynchronizer::synchronizeFields()

Performs field column synchronization on the given entity.

Field column synchronization takes care of propagating any change in the field items order and in the column values themselves to all the available translations. This functionality is provided by defining a 'translation_sync' key for the 'content_translation' module's portion of the field definition's 'third_party_settings', holding an array of column names to be synchronized. The synchronized column values are shared across translations, while the rest varies per-language. This is useful for instance to translate the "alt" and "title" textual elements of an image field, while keeping the same image on every translation.

Parameters

\Drupal\Core\Entity\ContentEntityInterface $entity: The entity whose values should be synchronized.

string $sync_langcode: The language of the translation whose values should be used as source for synchronization.

string $original_langcode: (optional) If a new translation is being created, this should be the language code of the original values. Defaults to NULL.

Overrides FieldTranslationSynchronizerInterface::synchronizeFields

File

core/modules/content_translation/src/FieldTranslationSynchronizer.php, line 39
Contains \Drupal\content_translation\FieldTranslationSynchronizer.

Class

FieldTranslationSynchronizer
Provides field translation synchronization capabilities.

Namespace

Drupal\content_translation

Code

public function synchronizeFields(ContentEntityInterface $entity, $sync_langcode, $original_langcode = NULL) {
  $translations = $entity
    ->getTranslationLanguages();
  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');

  // If we have no information about what to sync to, if we are creating a new
  // entity, if we have no translations for the current entity and we are not
  // creating one, then there is nothing to synchronize.
  if (empty($sync_langcode) || $entity
    ->isNew() || count($translations) < 2) {
    return;
  }

  // If the entity language is being changed there is nothing to synchronize.
  $entity_type = $entity
    ->getEntityTypeId();
  $entity_unchanged = isset($entity->original) ? $entity->original : $this->entityManager
    ->getStorage($entity_type)
    ->loadUnchanged($entity
    ->id());
  if ($entity
    ->getUntranslated()
    ->language()
    ->getId() != $entity_unchanged
    ->getUntranslated()
    ->language()
    ->getId()) {
    return;
  }

  /** @var \Drupal\Core\Field\FieldItemListInterface $items */
  foreach ($entity as $field_name => $items) {
    $field_definition = $items
      ->getFieldDefinition();
    $field_type_definition = $field_type_manager
      ->getDefinition($field_definition
      ->getType());
    $column_groups = $field_type_definition['column_groups'];

    // Sync if the field is translatable, not empty, and the synchronization
    // setting is enabled.
    if ($field_definition instanceof ThirdPartySettingsInterface && $field_definition
      ->isTranslatable() && !$items
      ->isEmpty() && ($translation_sync = $field_definition
      ->getThirdPartySetting('content_translation', 'translation_sync'))) {

      // Retrieve all the untranslatable column groups and merge them into
      // single list.
      $groups = array_keys(array_diff($translation_sync, array_filter($translation_sync)));
      if (!empty($groups)) {
        $columns = array();
        foreach ($groups as $group) {
          $info = $column_groups[$group];

          // A missing 'columns' key indicates we have a single-column group.
          $columns = array_merge($columns, isset($info['columns']) ? $info['columns'] : array(
            $group,
          ));
        }
        if (!empty($columns)) {
          $values = array();
          foreach ($translations as $langcode => $language) {
            $values[$langcode] = $entity
              ->getTranslation($langcode)
              ->get($field_name)
              ->getValue();
          }

          // If a translation is being created, the original values should be
          // used as the unchanged items. In fact there are no unchanged items
          // to check against.
          $langcode = $original_langcode ?: $sync_langcode;
          $unchanged_items = $entity_unchanged
            ->getTranslation($langcode)
            ->get($field_name)
            ->getValue();
          $this
            ->synchronizeItems($values, $unchanged_items, $sync_langcode, array_keys($translations), $columns);
          foreach ($translations as $langcode => $language) {
            $entity
              ->getTranslation($langcode)
              ->get($field_name)
              ->setValue($values[$langcode]);
          }
        }
      }
    }
  }
}