Backup of db before drupal security update
[yaffs-website] / web / core / modules / content_translation / src / Tests / ContentTranslationSyncImageTest.php
1 <?php
2
3 namespace Drupal\content_translation\Tests;
4
5 use Drupal\Core\Entity\EntityInterface;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\field\Entity\FieldStorageConfig;
8 use Drupal\file\Entity\File;
9
10 /**
11  * Tests the field synchronization behavior for the image field.
12  *
13  * @group content_translation
14  */
15 class ContentTranslationSyncImageTest extends ContentTranslationTestBase {
16
17   /**
18    * The cardinality of the image field.
19    *
20    * @var int
21    */
22   protected $cardinality;
23
24   /**
25    * The test image files.
26    *
27    * @var array
28    */
29   protected $files;
30
31   /**
32    * Modules to enable.
33    *
34    * @var array
35    */
36   public static $modules = ['language', 'content_translation', 'entity_test', 'image', 'field_ui'];
37
38   protected function setUp() {
39     parent::setUp();
40     $this->files = $this->drupalGetTestFiles('image');
41   }
42
43   /**
44    * Creates the test image field.
45    */
46   protected function setupTestFields() {
47     $this->fieldName = 'field_test_et_ui_image';
48     $this->cardinality = 3;
49
50     FieldStorageConfig::create([
51       'field_name' => $this->fieldName,
52       'entity_type' => $this->entityTypeId,
53       'type' => 'image',
54       'cardinality' => $this->cardinality,
55     ])->save();
56
57     FieldConfig::create([
58       'entity_type' => $this->entityTypeId,
59       'field_name' => $this->fieldName,
60       'bundle' => $this->entityTypeId,
61       'label' => 'Test translatable image field',
62       'third_party_settings' => [
63         'content_translation' => [
64           'translation_sync' => [
65             'file' => FALSE,
66             'alt' => 'alt',
67             'title' => 'title',
68           ],
69         ],
70       ],
71     ])->save();
72   }
73
74   /**
75    * {@inheritdoc}
76    */
77   protected function getEditorPermissions() {
78     // Every entity-type-specific test needs to define these.
79     return ['administer entity_test_mul fields', 'administer languages', 'administer content translation'];
80   }
81
82   /**
83    * Tests image field field synchronization.
84    */
85   public function testImageFieldSync() {
86     // Check that the alt and title fields are enabled for the image field.
87     $this->drupalLogin($this->editor);
88     $this->drupalGet('entity_test_mul/structure/' . $this->entityTypeId . '/fields/' . $this->entityTypeId . '.' . $this->entityTypeId . '.' . $this->fieldName);
89     $this->assertFieldChecked('edit-third-party-settings-content-translation-translation-sync-alt');
90     $this->assertFieldChecked('edit-third-party-settings-content-translation-translation-sync-title');
91     $edit = [
92       'third_party_settings[content_translation][translation_sync][alt]' => FALSE,
93       'third_party_settings[content_translation][translation_sync][title]' => FALSE,
94     ];
95     $this->drupalPostForm(NULL, $edit, t('Save settings'));
96
97     // Check that the content translation settings page reflects the changes
98     // performed in the field edit page.
99     $this->drupalGet('admin/config/regional/content-language');
100     $this->assertNoFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
101     $this->assertNoFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
102     $edit = [
103       'settings[entity_test_mul][entity_test_mul][fields][field_test_et_ui_image]' => TRUE,
104       'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][alt]' => TRUE,
105       'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][title]' => TRUE,
106     ];
107     $this->drupalPostForm('admin/config/regional/content-language', $edit, t('Save configuration'));
108     $errors = $this->xpath('//div[contains(@class, "messages--error")]');
109     $this->assertFalse($errors, 'Settings correctly stored.');
110     $this->assertFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
111     $this->assertFieldChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
112     $this->drupalLogin($this->translator);
113
114     $default_langcode = $this->langcodes[0];
115     $langcode = $this->langcodes[1];
116
117     // Populate the test entity with some random initial values.
118     $values = [
119       'name' => $this->randomMachineName(),
120       'user_id' => mt_rand(1, 128),
121       'langcode' => $default_langcode,
122     ];
123     $entity = entity_create($this->entityTypeId, $values);
124
125     // Create some file entities from the generated test files and store them.
126     $values = [];
127     for ($delta = 0; $delta < $this->cardinality; $delta++) {
128       // For the default language use the same order for files and field items.
129       $index = $delta;
130
131       // Create the file entity for the image being processed and record its
132       // identifier.
133       $field_values = [
134         'uri' => $this->files[$index]->uri,
135         'uid' => \Drupal::currentUser()->id(),
136         'status' => FILE_STATUS_PERMANENT,
137       ];
138       $file = File::create($field_values);
139       $file->save();
140       $fid = $file->id();
141       $this->files[$index]->fid = $fid;
142
143       // Generate the item for the current image file entity and attach it to
144       // the entity.
145       $item = [
146         'target_id' => $fid,
147         'alt' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
148         'title' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
149       ];
150       $entity->{$this->fieldName}[] = $item;
151
152       // Store the generated values keying them by fid for easier lookup.
153       $values[$default_langcode][$fid] = $item;
154     }
155     $entity = $this->saveEntity($entity);
156
157     // Create some field translations for the test image field. The translated
158     // items will be one less than the original values to check that only the
159     // translated ones will be preserved. In fact we want the same fids and
160     // items order for both languages.
161     $translation = $entity->addTranslation($langcode);
162     for ($delta = 0; $delta < $this->cardinality - 1; $delta++) {
163       // Simulate a field reordering: items are shifted of one position ahead.
164       // The modulo operator ensures we start from the beginning after reaching
165       // the maximum allowed delta.
166       $index = ($delta + 1) % $this->cardinality;
167
168       // Generate the item for the current image file entity and attach it to
169       // the entity.
170       $fid = $this->files[$index]->fid;
171       $item = [
172         'target_id' => $fid,
173         'alt' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
174         'title' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
175       ];
176       $translation->{$this->fieldName}[] = $item;
177
178       // Again store the generated values keying them by fid for easier lookup.
179       $values[$langcode][$fid] = $item;
180     }
181
182     // Perform synchronization: the translation language is used as source,
183     // while the default language is used as target.
184     $this->manager->getTranslationMetadata($translation)->setSource($default_langcode);
185     $entity = $this->saveEntity($translation);
186     $translation = $entity->getTranslation($langcode);
187
188     // Check that one value has been dropped from the original values.
189     $assert = count($entity->{$this->fieldName}) == 2;
190     $this->assertTrue($assert, 'One item correctly removed from the synchronized field values.');
191
192     // Check that fids have been synchronized and translatable column values
193     // have been retained.
194     $fids = [];
195     foreach ($entity->{$this->fieldName} as $delta => $item) {
196       $value = $values[$default_langcode][$item->target_id];
197       $source_item = $translation->{$this->fieldName}->get($delta);
198       $assert = $item->target_id == $source_item->target_id && $item->alt == $value['alt'] && $item->title == $value['title'];
199       $this->assertTrue($assert, format_string('Field item @fid has been successfully synchronized.', ['@fid' => $item->target_id]));
200       $fids[$item->target_id] = TRUE;
201     }
202
203     // Check that the dropped value is the right one.
204     $removed_fid = $this->files[0]->fid;
205     $this->assertTrue(!isset($fids[$removed_fid]), format_string('Field item @fid has been correctly removed.', ['@fid' => $removed_fid]));
206
207     // Add back an item for the dropped value and perform synchronization again.
208     $values[$langcode][$removed_fid] = [
209       'target_id' => $removed_fid,
210       'alt' => $langcode . '_' . $removed_fid . '_' . $this->randomMachineName(),
211       'title' => $langcode . '_' . $removed_fid . '_' . $this->randomMachineName(),
212     ];
213     $translation->{$this->fieldName}->setValue(array_values($values[$langcode]));
214     $entity = $this->saveEntity($translation);
215     $translation = $entity->getTranslation($langcode);
216
217     // Check that the value has been added to the default language.
218     $assert = count($entity->{$this->fieldName}->getValue()) == 3;
219     $this->assertTrue($assert, 'One item correctly added to the synchronized field values.');
220
221     foreach ($entity->{$this->fieldName} as $delta => $item) {
222       // When adding an item its value is copied over all the target languages,
223       // thus in this case the source language needs to be used to check the
224       // values instead of the target one.
225       $fid_langcode = $item->target_id != $removed_fid ? $default_langcode : $langcode;
226       $value = $values[$fid_langcode][$item->target_id];
227       $source_item = $translation->{$this->fieldName}->get($delta);
228       $assert = $item->target_id == $source_item->target_id && $item->alt == $value['alt'] && $item->title == $value['title'];
229       $this->assertTrue($assert, format_string('Field item @fid has been successfully synchronized.', ['@fid' => $item->target_id]));
230     }
231   }
232
233   /**
234    * Saves the passed entity and reloads it, enabling compatibility mode.
235    *
236    * @param \Drupal\Core\Entity\EntityInterface $entity
237    *   The entity to be saved.
238    *
239    * @return \Drupal\Core\Entity\EntityInterface
240    *   The saved entity.
241    */
242   protected function saveEntity(EntityInterface $entity) {
243     $entity->save();
244     $entity = entity_test_mul_load($entity->id(), TRUE);
245     return $entity;
246   }
247
248 }