/web/core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php
PHP | 267 lines | 160 code | 33 blank | 74 comment | 15 complexity | 5264fee53c565653f1a992faaead583d MD5 | raw file
- <?php
- namespace Drupal\Tests\content_translation\Functional;
- use Drupal\Component\Render\FormattableMarkup;
- use Drupal\Core\Entity\EntityInterface;
- use Drupal\field\Entity\FieldConfig;
- use Drupal\field\Entity\FieldStorageConfig;
- use Drupal\file\Entity\File;
- use Drupal\Tests\TestFileCreationTrait;
- /**
- * Tests the field synchronization behavior for the image field.
- *
- * @group content_translation
- */
- class ContentTranslationSyncImageTest extends ContentTranslationTestBase {
- use TestFileCreationTrait {
- getTestFiles as drupalGetTestFiles;
- }
- /**
- * {@inheritdoc}
- */
- protected $defaultTheme = 'stark';
- /**
- * The cardinality of the image field.
- *
- * @var int
- */
- protected $cardinality;
- /**
- * The test image files.
- *
- * @var array
- */
- protected $files;
- /**
- * Modules to enable.
- *
- * @var array
- */
- protected static $modules = [
- 'language',
- 'content_translation',
- 'entity_test',
- 'image',
- 'field_ui',
- ];
- protected function setUp(): void {
- parent::setUp();
- $this->files = $this->drupalGetTestFiles('image');
- }
- /**
- * Creates the test image field.
- */
- protected function setupTestFields() {
- $this->fieldName = 'field_test_et_ui_image';
- $this->cardinality = 3;
- FieldStorageConfig::create([
- 'field_name' => $this->fieldName,
- 'entity_type' => $this->entityTypeId,
- 'type' => 'image',
- 'cardinality' => $this->cardinality,
- ])->save();
- FieldConfig::create([
- 'entity_type' => $this->entityTypeId,
- 'field_name' => $this->fieldName,
- 'bundle' => $this->entityTypeId,
- 'label' => 'Test translatable image field',
- 'third_party_settings' => [
- 'content_translation' => [
- 'translation_sync' => [
- 'file' => FALSE,
- 'alt' => 'alt',
- 'title' => 'title',
- ],
- ],
- ],
- ])->save();
- }
- /**
- * {@inheritdoc}
- */
- protected function getEditorPermissions() {
- // Every entity-type-specific test needs to define these.
- return ['administer entity_test_mul fields', 'administer languages', 'administer content translation'];
- }
- /**
- * Tests image field synchronization.
- */
- public function testImageFieldSync() {
- // Check that the alt and title fields are enabled for the image field.
- $this->drupalLogin($this->editor);
- $this->drupalGet('entity_test_mul/structure/' . $this->entityTypeId . '/fields/' . $this->entityTypeId . '.' . $this->entityTypeId . '.' . $this->fieldName);
- $this->assertSession()->checkboxChecked('edit-third-party-settings-content-translation-translation-sync-alt');
- $this->assertSession()->checkboxChecked('edit-third-party-settings-content-translation-translation-sync-title');
- $edit = [
- 'third_party_settings[content_translation][translation_sync][alt]' => FALSE,
- 'third_party_settings[content_translation][translation_sync][title]' => FALSE,
- ];
- $this->submitForm($edit, 'Save settings');
- // Check that the content translation settings page reflects the changes
- // performed in the field edit page.
- $this->drupalGet('admin/config/regional/content-language');
- $this->assertSession()->checkboxNotChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
- $this->assertSession()->checkboxNotChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
- $edit = [
- 'settings[entity_test_mul][entity_test_mul][fields][field_test_et_ui_image]' => TRUE,
- 'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][alt]' => TRUE,
- 'settings[entity_test_mul][entity_test_mul][columns][field_test_et_ui_image][title]' => TRUE,
- ];
- $this->drupalGet('admin/config/regional/content-language');
- $this->submitForm($edit, 'Save configuration');
- $this->assertSession()->elementNotExists('xpath', '//div[contains(@class, "messages--error")]');
- $this->assertSession()->checkboxChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-alt');
- $this->assertSession()->checkboxChecked('edit-settings-entity-test-mul-entity-test-mul-columns-field-test-et-ui-image-title');
- $this->drupalLogin($this->translator);
- $default_langcode = $this->langcodes[0];
- $langcode = $this->langcodes[1];
- // Populate the test entity with some random initial values.
- $values = [
- 'name' => $this->randomMachineName(),
- 'user_id' => mt_rand(1, 128),
- 'langcode' => $default_langcode,
- ];
- $entity = \Drupal::entityTypeManager()
- ->getStorage($this->entityTypeId)
- ->create($values);
- // Create some file entities from the generated test files and store them.
- $values = [];
- for ($delta = 0; $delta < $this->cardinality; $delta++) {
- // For the default language use the same order for files and field items.
- $index = $delta;
- // Create the file entity for the image being processed and record its
- // identifier.
- $field_values = [
- 'uri' => $this->files[$index]->uri,
- 'uid' => \Drupal::currentUser()->id(),
- ];
- $file = File::create($field_values);
- $file->setPermanent();
- $file->save();
- $fid = $file->id();
- $this->files[$index]->fid = $fid;
- // Generate the item for the current image file entity and attach it to
- // the entity.
- $item = [
- 'target_id' => $fid,
- 'alt' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
- 'title' => $default_langcode . '_' . $fid . '_' . $this->randomMachineName(),
- ];
- $entity->{$this->fieldName}[] = $item;
- // Store the generated values keying them by fid for easier lookup.
- $values[$default_langcode][$fid] = $item;
- }
- $entity = $this->saveEntity($entity);
- // Create some field translations for the test image field. The translated
- // items will be one less than the original values to check that only the
- // translated ones will be preserved. In fact we want the same fids and
- // items order for both languages.
- $translation = $entity->addTranslation($langcode);
- for ($delta = 0; $delta < $this->cardinality - 1; $delta++) {
- // Simulate a field reordering: items are shifted of one position ahead.
- // The modulo operator ensures we start from the beginning after reaching
- // the maximum allowed delta.
- $index = ($delta + 1) % $this->cardinality;
- // Generate the item for the current image file entity and attach it to
- // the entity.
- $fid = $this->files[$index]->fid;
- $item = [
- 'target_id' => $fid,
- 'alt' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
- 'title' => $langcode . '_' . $fid . '_' . $this->randomMachineName(),
- ];
- $translation->{$this->fieldName}[] = $item;
- // Again store the generated values keying them by fid for easier lookup.
- $values[$langcode][$fid] = $item;
- }
- // Perform synchronization: the translation language is used as source,
- // while the default language is used as target.
- $this->manager->getTranslationMetadata($translation)->setSource($default_langcode);
- $entity = $this->saveEntity($translation);
- $translation = $entity->getTranslation($langcode);
- // Check that one value has been dropped from the original values.
- $assert = count($entity->{$this->fieldName}) == 2;
- $this->assertTrue($assert, 'One item correctly removed from the synchronized field values.');
- // Check that fids have been synchronized and translatable column values
- // have been retained.
- $fids = [];
- foreach ($entity->{$this->fieldName} as $delta => $item) {
- $value = $values[$default_langcode][$item->target_id];
- $source_item = $translation->{$this->fieldName}->get($delta);
- $assert = $item->target_id == $source_item->target_id && $item->alt == $value['alt'] && $item->title == $value['title'];
- $this->assertTrue($assert, new FormattableMarkup('Field item @fid has been successfully synchronized.', ['@fid' => $item->target_id]));
- $fids[$item->target_id] = TRUE;
- }
- // Check that the dropped value is the right one.
- $removed_fid = $this->files[0]->fid;
- $this->assertTrue(!isset($fids[$removed_fid]), new FormattableMarkup('Field item @fid has been correctly removed.', ['@fid' => $removed_fid]));
- // Add back an item for the dropped value and perform synchronization again.
- $values[$langcode][$removed_fid] = [
- 'target_id' => $removed_fid,
- 'alt' => $langcode . '_' . $removed_fid . '_' . $this->randomMachineName(),
- 'title' => $langcode . '_' . $removed_fid . '_' . $this->randomMachineName(),
- ];
- $translation->{$this->fieldName}->setValue(array_values($values[$langcode]));
- $entity = $this->saveEntity($translation);
- $translation = $entity->getTranslation($langcode);
- // Check that the value has been added to the default language.
- $assert = count($entity->{$this->fieldName}->getValue()) == 3;
- $this->assertTrue($assert, 'One item correctly added to the synchronized field values.');
- foreach ($entity->{$this->fieldName} as $delta => $item) {
- // When adding an item its value is copied over all the target languages,
- // thus in this case the source language needs to be used to check the
- // values instead of the target one.
- $fid_langcode = $item->target_id != $removed_fid ? $default_langcode : $langcode;
- $value = $values[$fid_langcode][$item->target_id];
- $source_item = $translation->{$this->fieldName}->get($delta);
- $assert = $item->target_id == $source_item->target_id && $item->alt == $value['alt'] && $item->title == $value['title'];
- $this->assertTrue($assert, new FormattableMarkup('Field item @fid has been successfully synchronized.', ['@fid' => $item->target_id]));
- }
- }
- /**
- * Saves the passed entity and reloads it, enabling compatibility mode.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The entity to be saved.
- *
- * @return \Drupal\Core\Entity\EntityInterface
- * The saved entity.
- */
- protected function saveEntity(EntityInterface $entity) {
- $entity->save();
- $entity = \Drupal::entityTypeManager()->getStorage('entity_test_mul')->loadUnchanged($entity->id());
- return $entity;
- }
- }