PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/web/core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php

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