ContentTranslationSyncImageTest.php

Same filename in other branches
  1. 8.9.x core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php
  2. 10 core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php
  3. 11.x core/modules/content_translation/tests/src/Functional/ContentTranslationSyncImageTest.php

Namespace

Drupal\Tests\content_translation\Functional

File

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

View source
<?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',
    ];
    
    /**
     * {@inheritdoc}
     */
    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()
            ->statusMessageNotExists('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;
    }

}

Classes

Title Deprecated Summary
ContentTranslationSyncImageTest Tests the field synchronization behavior for the image field.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.