1<?php
2
3namespace Drupal\config_translation\FormElement;
4
5use Drupal\Core\Config\Config;
6use Drupal\Core\Language\LanguageInterface;
7use Drupal\config_translation\Form\ConfigTranslationFormBase;
8use Drupal\Core\StringTranslation\StringTranslationTrait;
9use Drupal\Core\TypedData\DataDefinitionInterface;
10use Drupal\Core\TypedData\TraversableTypedDataInterface;
11use Drupal\Core\TypedData\TypedDataInterface;
12use Drupal\language\Config\LanguageConfigOverride;
13
14/**
15 * Defines the list element for the configuration translation interface.
16 */
17class ListElement implements ElementInterface {
18
19  use StringTranslationTrait;
20
21  /**
22   * The schema element this form is for.
23   *
24   * @var \Drupal\Core\TypedData\TraversableTypedDataInterface
25   */
26  protected $element;
27
28  /**
29   * Constructs a ListElement.
30   *
31   * @param \Drupal\Core\TypedData\TraversableTypedDataInterface $element
32   *   The schema element this form element is for.
33   */
34  public function __construct(TraversableTypedDataInterface $element) {
35    $this->element = $element;
36  }
37
38  /**
39   * {@inheritdoc}
40   */
41  public static function create(TypedDataInterface $schema) {
42    return new static($schema);
43  }
44
45  /**
46   * {@inheritdoc}
47   */
48  public function getTranslationBuild(LanguageInterface $source_language, LanguageInterface $translation_language, $source_config, $translation_config, array $parents, $base_key = NULL) {
49    $build = [];
50    foreach ($this->element as $key => $element) {
51      $sub_build = [];
52      $element_key = isset($base_key) ? "$base_key.$key" : $key;
53      $definition = $element->getDataDefinition();
54
55      if ($form_element = ConfigTranslationFormBase::createFormElement($element)) {
56        $element_parents = array_merge($parents, [$key]);
57        $sub_build += $form_element->getTranslationBuild($source_language, $translation_language, $source_config[$key], $translation_config[$key], $element_parents, $element_key);
58
59        if (empty($sub_build)) {
60          continue;
61        }
62
63        // Build the sub-structure and include it with a wrapper in the form if
64        // there are any translatable elements there.
65        $build[$key] = [];
66        if ($element instanceof TraversableTypedDataInterface) {
67          $build[$key] = [
68            '#type' => 'details',
69            '#title' => $this->getGroupTitle($definition, $sub_build),
70            '#open' => empty($base_key),
71          ];
72        }
73        $build[$key] += $sub_build;
74      }
75    }
76
77    return $build;
78  }
79
80  /**
81   * {@inheritdoc}
82   */
83  public function setConfig(Config $base_config, LanguageConfigOverride $config_translation, $config_values, $base_key = NULL) {
84    foreach ($this->element as $key => $element) {
85      $element_key = isset($base_key) ? "$base_key.$key" : $key;
86      if ($form_element = ConfigTranslationFormBase::createFormElement($element)) {
87        // Traverse into the next level of the configuration.
88        $value = isset($config_values[$key]) ? $config_values[$key] : NULL;
89        $form_element->setConfig($base_config, $config_translation, $value, $element_key);
90      }
91    }
92  }
93
94  /**
95   * Returns the title for the 'details' element of a group of schema elements.
96   *
97   * For some configuration elements the same element structure can be repeated
98   * multiple times (for example views displays, filters, etc.). Thus, we try to
99   * find a more usable title for the details summary. First check if there is
100   * an element which is called title or label and use its value. Then check if
101   * there is an element which contains these words and use those. Fall back
102   * to the generic definition label if no such element is found.
103   *
104   * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
105   *   The definition of the schema element.
106   * @param array $group_build
107   *   The renderable array for the group of schema elements.
108   *
109   * @return string
110   *   The title for the group of schema elements.
111   */
112  protected function getGroupTitle(DataDefinitionInterface $definition, array $group_build) {
113    $title = '';
114    if (isset($group_build['title']['source'])) {
115      $title = $group_build['title']['source']['#markup'];
116    }
117    elseif (isset($group_build['label']['source'])) {
118      $title = $group_build['label']['source']['#markup'];
119    }
120    else {
121      foreach (array_keys($group_build) as $title_key) {
122        if (isset($group_build[$title_key]['source']) && (strpos($title_key, 'title') !== FALSE || strpos($title_key, 'label') !== FALSE)) {
123          $title = $group_build[$title_key]['source']['#markup'];
124          break;
125        }
126      }
127    }
128    return (!empty($title) ? (strip_tags($title) . ' ') : '') . $this->t($definition['label']);
129  }
130
131}
132