1ffd1a2c5c3fc8cda6f34d61b5a1c4d36a71b3a9
[yaffs-website] / web / core / modules / language / src / Form / NegotiationBrowserForm.php
1 <?php
2
3 namespace Drupal\language\Form;
4
5 use Drupal\Core\Config\ConfigFactoryInterface;
6 use Drupal\Core\Form\ConfigFormBase;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Url;
9 use Drupal\language\ConfigurableLanguageManagerInterface;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
11
12 /**
13  * Configure the browser language negotiation method for this site.
14  *
15  * @internal
16  */
17 class NegotiationBrowserForm extends ConfigFormBase {
18
19   /**
20    * The configurable language manager.
21    *
22    * @var \Drupal\language\ConfigurableLanguageManagerInterface
23    */
24   protected $languageManager;
25
26   /**
27    * {@inheritdoc}
28    */
29   public function __construct(ConfigFactoryInterface $config_factory, ConfigurableLanguageManagerInterface $language_manager) {
30     parent::__construct($config_factory);
31     $this->languageManager = $language_manager;
32   }
33
34   /**
35    * {@inheritdoc}
36    */
37   public static function create(ContainerInterface $container) {
38     return new static(
39       $container->get('config.factory'),
40       $container->get('language_manager')
41     );
42   }
43
44   /**
45    * {@inheritdoc}
46    */
47   public function getFormId() {
48     return 'language_negotiation_configure_browser_form';
49   }
50
51   /**
52    * {@inheritdoc}
53    */
54   protected function getEditableConfigNames() {
55     return ['language.mappings'];
56   }
57
58   /**
59    * {@inheritdoc}
60    */
61   public function buildForm(array $form, FormStateInterface $form_state) {
62     $form = [];
63
64     // Initialize a language list to the ones available, including English.
65     $languages = $this->languageManager->getLanguages();
66
67     $existing_languages = [];
68     foreach ($languages as $langcode => $language) {
69       $existing_languages[$langcode] = $language->getName();
70     }
71
72     // If we have no languages available, present the list of predefined languages
73     // only. If we do have already added languages, set up two option groups with
74     // the list of existing and then predefined languages.
75     if (empty($existing_languages)) {
76       $language_options = $this->languageManager->getStandardLanguageListWithoutConfigured();
77     }
78     else {
79       $language_options = [
80         (string) $this->t('Existing languages') => $existing_languages,
81         (string) $this->t('Languages not yet added') => $this->languageManager->getStandardLanguageListWithoutConfigured(),
82       ];
83     }
84
85     $form['mappings'] = [
86       '#type' => 'table',
87       '#header' => [
88         $this->t('Browser language code'),
89         $this->t('Site language'),
90         $this->t('Operations'),
91       ],
92       '#attributes' => ['id' => 'language-negotiation-browser'],
93       '#empty' => $this->t('No browser language mappings available.'),
94     ];
95
96     $mappings = $this->language_get_browser_drupal_langcode_mappings();
97     foreach ($mappings as $browser_langcode => $drupal_langcode) {
98       $form['mappings'][$browser_langcode] = [
99         'browser_langcode' => [
100           '#title' => $this->t('Browser language code'),
101           '#title_display' => 'invisible',
102           '#type' => 'textfield',
103           '#default_value' => $browser_langcode,
104           '#size' => 20,
105           '#required' => TRUE,
106         ],
107         'drupal_langcode' => [
108           '#title' => $this->t('Site language'),
109           '#title_display' => 'invisible',
110           '#type' => 'select',
111           '#options' => $language_options,
112           '#default_value' => $drupal_langcode,
113           '#required' => TRUE,
114         ],
115       ];
116       // Operations column.
117       $form['mappings'][$browser_langcode]['operations'] = [
118         '#type' => 'operations',
119         '#links' => [],
120       ];
121       $form['mappings'][$browser_langcode]['operations']['#links']['delete'] = [
122         'title' => $this->t('Delete'),
123         'url' => Url::fromRoute('language.negotiation_browser_delete', ['browser_langcode' => $browser_langcode]),
124       ];
125     }
126
127     // Add empty row.
128     $form['new_mapping'] = [
129       '#type' => 'details',
130       '#title' => $this->t('Add a new mapping'),
131       '#tree' => TRUE,
132     ];
133     $form['new_mapping']['browser_langcode'] = [
134       '#type' => 'textfield',
135       '#title' => $this->t('Browser language code'),
136       '#description' => $this->t('Use language codes as <a href=":w3ctags">defined by the W3C</a> for interoperability. <em>Examples: "en", "en-gb" and "zh-hant".</em>', [':w3ctags' => 'http://www.w3.org/International/articles/language-tags/']),
137       '#size' => 20,
138     ];
139     $form['new_mapping']['drupal_langcode'] = [
140       '#type' => 'select',
141       '#title' => $this->t('Site language'),
142       '#options' => $language_options,
143     ];
144
145     return parent::buildForm($form, $form_state);
146   }
147
148   /**
149    * {@inheritdoc}
150    */
151   public function validateForm(array &$form, FormStateInterface $form_state) {
152     // Array to check if all browser language codes are unique.
153     $unique_values = [];
154
155     // Check all mappings.
156     if ($form_state->hasValue('mappings')) {
157       $mappings = $form_state->getValue('mappings');
158       foreach ($mappings as $key => $data) {
159         // Make sure browser_langcode is unique.
160         if (array_key_exists($data['browser_langcode'], $unique_values)) {
161           $form_state->setErrorByName('mappings][new_mapping][browser_langcode', $this->t('Browser language codes must be unique.'));
162         }
163         elseif (preg_match('/[^a-z\-]/', $data['browser_langcode'])) {
164           $form_state->setErrorByName('mappings][new_mapping][browser_langcode', $this->t('Browser language codes can only contain lowercase letters and a hyphen(-).'));
165         }
166         $unique_values[$data['browser_langcode']] = $data['drupal_langcode'];
167       }
168     }
169
170     // Check new mapping.
171     $data = $form_state->getValue('new_mapping');
172     if (!empty($data['browser_langcode'])) {
173       // Make sure browser_langcode is unique.
174       if (array_key_exists($data['browser_langcode'], $unique_values)) {
175         $form_state->setErrorByName('mappings][' . $key . '][browser_langcode', $this->t('Browser language codes must be unique.'));
176       }
177       elseif (preg_match('/[^a-z\-]/', $data['browser_langcode'])) {
178         $form_state->setErrorByName('mappings][' . $key . '][browser_langcode', $this->t('Browser language codes can only contain lowercase letters and a hyphen(-).'));
179       }
180       $unique_values[$data['browser_langcode']] = $data['drupal_langcode'];
181     }
182
183     $form_state->set('mappings', $unique_values);
184   }
185
186   /**
187    * {@inheritdoc}
188    */
189   public function submitForm(array &$form, FormStateInterface $form_state) {
190     $mappings = $form_state->get('mappings');
191     if (!empty($mappings)) {
192       $config = $this->config('language.mappings');
193       $config->setData(['map' => $mappings]);
194       $config->save();
195     }
196
197     parent::submitForm($form, $form_state);
198   }
199
200   /**
201    * Retrieves the browser's langcode mapping configuration array.
202    *
203    * @return array
204    *   The browser's langcode mapping configuration array.
205    */
206   protected function language_get_browser_drupal_langcode_mappings() {
207     $config = $this->config('language.mappings');
208     if ($config->isNew()) {
209       return [];
210     }
211     return $config->get('map');
212   }
213
214 }