public function 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 in the field instance 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\EntityInterface $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

drupal/core/modules/translation_entity/lib/Drupal/translation_entity/FieldTranslationSynchronizer.php, line 39
Contains \Drupal\translation_entity\FieldTranslationSynchronizer.

Class

FieldTranslationSynchronizer
Provides field translation synchronization capabilities.

Namespace

Drupal\translation_entity

Code

public function synchronizeFields(EntityInterface $entity, $sync_langcode, $original_langcode = NULL) {

  // Field synchronization is only supported for NG entities.
  $entity = $entity
    ->getNGEntity();
  if (!$entity instanceof EntityNG) {
    return;
  }
  $translations = $entity
    ->getTranslationLanguages();

  // 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 && !$original_langcode) {
    return;
  }

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

  // @todo Use Entity Field API to retrieve field definitions.
  $instances = field_info_instances($entity_type, $entity
    ->bundle());
  foreach ($instances as $field_name => $instance) {
    $field = $instance
      ->getField();

    // Sync when the field is not empty, when the synchronization translations
    // setting is set, and the field is translatable.
    if (!$entity
      ->get($field_name)
      ->isEmpty() && !empty($instance['settings']['translation_sync']) && field_is_translatable($entity_type, $field)) {

      // Retrieve all the untranslatable column groups and merge them into
      // single list.
      $groups = array_keys(array_diff($instance['settings']['translation_sync'], array_filter($instance['settings']['translation_sync'])));
      if (!empty($groups)) {
        $columns = array();
        foreach ($groups as $group) {
          $info = $field['settings']['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]);
          }
        }
      }
    }
  }
}