Version 1
[yaffs-website] / web / core / modules / field / tests / src / Kernel / TranslationTest.php
1 <?php
2
3 namespace Drupal\Tests\field\Kernel;
4
5 use Drupal\Component\Utility\Unicode;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\language\Entity\ConfigurableLanguage;
8 use Drupal\field\Entity\FieldStorageConfig;
9
10 /**
11  * Tests multilanguage fields logic.
12  *
13  * The following tests will check the multilanguage logic in field handling.
14  *
15  * @group field
16  */
17 class TranslationTest extends FieldKernelTestBase {
18
19   /**
20    * Modules to enable.
21    *
22    * node is required because the tests alter the node entity type.
23    *
24    * @var array
25    */
26   public static $modules = ['language', 'node'];
27
28   /**
29    * The name of the field to use in this test.
30    *
31    * @var string
32    */
33   protected $fieldName;
34
35   /**
36    * The name of the entity type to use in this test.
37    *
38    * @var string
39    */
40   protected $entityType = 'test_entity';
41
42   /**
43    * An array defining the field storage to use in this test.
44    *
45    * @var array
46    */
47   protected $fieldStorageDefinition;
48
49   /**
50    * An array defining the field to use in this test.
51    *
52    * @var array
53    */
54   protected $fieldDefinition;
55
56   /**
57    * The field storage to use in this test.
58    *
59    * @var \Drupal\field\Entity\FieldStorageConfig
60    */
61   protected $fieldStorage;
62
63   /**
64    * The field to use in this test.
65    *
66    * @var \Drupal\field\Entity\FieldConfig
67    */
68   protected $field;
69
70   /**
71    * {@inheritdoc}
72    */
73   protected function setUp() {
74     parent::setUp();
75
76     $this->installConfig(['language']);
77
78     $this->fieldName = Unicode::strtolower($this->randomMachineName());
79
80     $this->entityType = 'entity_test';
81
82     $this->fieldStorageDefinition = [
83       'field_name' => $this->fieldName,
84       'entity_type' => $this->entityType,
85       'type' => 'test_field',
86       'cardinality' => 4,
87     ];
88     $this->fieldStorage = FieldStorageConfig::create($this->fieldStorageDefinition);
89     $this->fieldStorage->save();
90
91     $this->fieldDefinition = [
92       'field_storage' => $this->fieldStorage,
93       'bundle' => 'entity_test',
94     ];
95     $this->field = FieldConfig::create($this->fieldDefinition);
96     $this->field->save();
97
98     for ($i = 0; $i < 3; ++$i) {
99       ConfigurableLanguage::create([
100         'id' => 'l' . $i,
101         'label' => $this->randomString(),
102       ])->save();
103     }
104   }
105
106   /**
107    * Test translatable fields storage/retrieval.
108    */
109   public function testTranslatableFieldSaveLoad() {
110     // Enable field translations for nodes.
111     field_test_entity_info_translatable('node', TRUE);
112     $entity_type = \Drupal::entityManager()->getDefinition('node');
113     $this->assertTrue($entity_type->isTranslatable(), 'Nodes are translatable.');
114
115     // Prepare the field translations.
116     $entity_type_id = 'entity_test';
117     field_test_entity_info_translatable($entity_type_id, TRUE);
118     $entity = $this->container->get('entity_type.manager')
119       ->getStorage($entity_type_id)
120       ->create(['type' => $this->field->getTargetBundle()]);
121     $field_translations = [];
122     $available_langcodes = array_keys($this->container->get('language_manager')->getLanguages());
123     $entity->langcode->value = reset($available_langcodes);
124     foreach ($available_langcodes as $langcode) {
125       $field_translations[$langcode] = $this->_generateTestFieldValues($this->fieldStorage->getCardinality());
126       $translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
127       $translation->{$this->fieldName}->setValue($field_translations[$langcode]);
128     }
129
130     // Save and reload the field translations.
131     $entity = $this->entitySaveReload($entity);
132
133     // Check if the correct values were saved/loaded.
134     foreach ($field_translations as $langcode => $items) {
135       $result = TRUE;
136       foreach ($items as $delta => $item) {
137         $result = $result && $item['value'] == $entity->getTranslation($langcode)->{$this->fieldName}[$delta]->value;
138       }
139       $this->assertTrue($result, format_string('%language translation correctly handled.', ['%language' => $langcode]));
140     }
141
142     // Test default values.
143     $field_name_default = Unicode::strtolower($this->randomMachineName() . '_field_name');
144     $field_storage_definition = $this->fieldStorageDefinition;
145     $field_storage_definition['field_name'] = $field_name_default;
146     $field_storage = FieldStorageConfig::create($field_storage_definition);
147     $field_storage->save();
148
149     $field_definition = $this->fieldDefinition;
150     $field_definition['field_storage'] = $field_storage;
151     $field_definition['default_value'] = [['value' => rand(1, 127)]];
152     $field = FieldConfig::create($field_definition);
153     $field->save();
154
155     $translation_langcodes = array_slice($available_langcodes, 0, 2);
156     asort($translation_langcodes);
157     $translation_langcodes = array_values($translation_langcodes);
158
159     $values = ['type' => $field->getTargetBundle(), 'langcode' => $translation_langcodes[0]];
160     $entity = $this->container->get('entity_type.manager')
161       ->getStorage($entity_type_id)
162       ->create($values);
163     foreach ($translation_langcodes as $langcode) {
164       $values[$this->fieldName][$langcode] = $this->_generateTestFieldValues($this->fieldStorage->getCardinality());
165       $translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
166       $translation->{$this->fieldName}->setValue($values[$this->fieldName][$langcode]);
167     }
168
169     $field_langcodes = array_keys($entity->getTranslationLanguages());
170     sort($field_langcodes);
171     $this->assertEqual($translation_langcodes, $field_langcodes, 'Missing translations did not get a default value.');
172
173     // @todo Test every translation once the Entity Translation API allows for
174     //   multilingual defaults.
175     $langcode = $entity->language()->getId();
176     $this->assertEqual($entity->getTranslation($langcode)->{$field_name_default}->getValue(), $field->getDefaultValueLiteral(), format_string('Default value correctly populated for language %language.', ['%language' => $langcode]));
177
178     // Check that explicit empty values are not overridden with default values.
179     foreach ([NULL, []] as $empty_items) {
180       $values = ['type' => $field->getTargetBundle(), 'langcode' => $translation_langcodes[0]];
181       $entity = entity_create($entity_type_id, $values);
182       foreach ($translation_langcodes as $langcode) {
183         $values[$this->fieldName][$langcode] = $this->_generateTestFieldValues($this->fieldStorage->getCardinality());
184         $translation = $entity->hasTranslation($langcode) ? $entity->getTranslation($langcode) : $entity->addTranslation($langcode);
185         $translation->{$this->fieldName}->setValue($values[$this->fieldName][$langcode]);
186         $translation->{$field_name_default}->setValue($empty_items);
187         $values[$field_name_default][$langcode] = $empty_items;
188       }
189
190       foreach ($entity->getTranslationLanguages() as $langcode => $language) {
191         $this->assertEquals([], $entity->getTranslation($langcode)->{$field_name_default}->getValue(), format_string('Empty value correctly populated for language %language.', ['%language' => $langcode]));
192       }
193     }
194   }
195
196   /**
197    * Tests field access.
198    *
199    * Regression test to verify that fieldAccess() can be called while only
200    * passing the required parameters.
201    *
202    * @see https://www.drupal.org/node/2404739
203    */
204   public function testFieldAccess() {
205     $access_control_handler = \Drupal::entityManager()->getAccessControlHandler($this->entityType);
206     $this->assertTrue($access_control_handler->fieldAccess('view', $this->field));
207   }
208
209 }