You are here

public function LanguageKernelTest::testItemTranslations in Search API 8

Tests translation handling of the content entity datasource.

File

tests/src/Kernel/Datasource/LanguageKernelTest.php, line 156

Class

LanguageKernelTest
Tests translation handling of the content entity datasource.

Namespace

Drupal\Tests\search_api\Kernel\Datasource

Code

public function testItemTranslations() {

  // Test retrieving language and translations when no translations are
  // available.

  /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $entity_1 */
  $entity_1 = EntityTestMulRevChanged::create([
    'id' => 1,
    'name' => 'test 1',
    'user_id' => $this->container
      ->get('current_user')
      ->id(),
  ]);
  $entity_1
    ->save();
  $entity_1
    ->set('link', $entity_1
    ->id());
  $this
    ->assertEquals('en', $entity_1
    ->language()
    ->getId(), new FormattableMarkup('%entity_type: Entity language set to site default.', [
    '%entity_type' => $this->testEntityTypeId,
  ]));
  $this
    ->assertEmpty($entity_1
    ->getTranslationLanguages(FALSE), new FormattableMarkup('%entity_type: No translations are available', [
    '%entity_type' => $this->testEntityTypeId,
  ]));

  /** @var \Drupal\entity_test\Entity\EntityTestMulRevChanged $entity_2 */
  $entity_2 = EntityTestMulRevChanged::create([
    'id' => 2,
    'name' => 'test 2',
    'user_id' => $this->container
      ->get('current_user')
      ->id(),
  ]);
  $entity_2
    ->save();
  $this
    ->assertEquals('en', $entity_2
    ->language()
    ->getId(), new FormattableMarkup('%entity_type: Entity language set to site default.', [
    '%entity_type' => $this->testEntityTypeId,
  ]));
  $this
    ->assertEmpty($entity_2
    ->getTranslationLanguages(FALSE), new FormattableMarkup('%entity_type: No translations are available', [
    '%entity_type' => $this->testEntityTypeId,
  ]));

  // Test that the datasource returns the correct item IDs.
  $datasource = $this->index
    ->getDatasource('entity:' . $this->testEntityTypeId);
  $datasource_item_ids = $datasource
    ->getItemIds();
  sort($datasource_item_ids);
  $expected = [
    '1:en',
    '2:en',
  ];
  $this
    ->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids.');

  // Test indexing the new entity.
  $this
    ->assertEquals(0, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'The index is empty.');
  $this
    ->assertEquals(2, $this->index
    ->getTrackerInstance()
    ->getTotalItemsCount(), 'There are two items to be indexed.');
  $this->index
    ->indexItems();
  $this
    ->assertEquals(2, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'Two items have been indexed.');

  // Now, make the first entity language-specific by assigning a language.
  $default_langcode = $this->langcodes[0];
  $entity_1
    ->get('langcode')
    ->setValue($default_langcode);
  $entity_1
    ->save();
  $this
    ->assertEquals(\Drupal::languageManager()
    ->getLanguage($this->langcodes[0]), $entity_1
    ->language(), new FormattableMarkup('%entity_type: Entity language retrieved.', [
    '%entity_type' => $this->testEntityTypeId,
  ]));
  $this
    ->assertEmpty($entity_1
    ->getTranslationLanguages(FALSE), new FormattableMarkup('%entity_type: No translations are available', [
    '%entity_type' => $this->testEntityTypeId,
  ]));

  // Test that the datasource returns the correct item IDs.
  $datasource_item_ids = $datasource
    ->getItemIds();
  sort($datasource_item_ids);
  $expected = [
    '1:' . $this->langcodes[0],
    '2:en',
  ];
  $this
    ->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids.');

  // Test that the index needs to be updated.
  $this
    ->assertEquals(1, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'The updated item needs to be reindexed.');
  $this
    ->assertEquals(2, $this->index
    ->getTrackerInstance()
    ->getTotalItemsCount(), 'There are two items in total.');

  // Set two translations for the first entity and test that the datasource
  // returns three separate item IDs, one for each translation.
  $translation = $entity_1
    ->addTranslation($this->langcodes[1]);
  $this
    ->assertEquals(1, $entity_1->link[0]->entity
    ->id());
  $translation
    ->set('name', 'test 1 - ' . $this->langcodes[1]);
  $translation
    ->set('link', $entity_1
    ->id());
  $translation
    ->save();
  $translation = $entity_1
    ->addTranslation($this->langcodes[2]);
  $translation
    ->set('name', 'test 1 - ' . $this->langcodes[2]);
  $translation
    ->set('link', $entity_1
    ->id());
  $translation
    ->save();
  $this
    ->assertNotEmpty($entity_1
    ->getTranslationLanguages(FALSE), new FormattableMarkup('%entity_type: Translations are available', [
    '%entity_type' => $this->testEntityTypeId,
  ]));
  $datasource_item_ids = $datasource
    ->getItemIds();
  sort($datasource_item_ids);
  $expected = [
    '1:' . $this->langcodes[0],
    '1:' . $this->langcodes[1],
    '1:' . $this->langcodes[2],
    '2:en',
  ];
  $this
    ->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids for a translated entity.');
  foreach ($datasource
    ->loadMultiple($datasource_item_ids) as $id => $object) {

    // Test whether the item reports the correct language.
    list($entity_id, $langcode) = explode(':', $id, 2);
    $item = \Drupal::getContainer()
      ->get('search_api.fields_helper')
      ->createItemFromObject($this->index, $object, NULL, $datasource);
    $this
      ->assertEquals($langcode, $item
      ->getLanguage(), "Item with ID '{$id}' has the correct language set.");

    // Test whether nested field extraction works correctly.
    if ($entity_id == 1) {
      $field = $item
        ->getField('link');
      $translation_label = $entity_1
        ->getTranslation($langcode)
        ->label();
      $this
        ->assertEquals([
        $translation_label,
      ], $field
        ->getValues());
    }
  }

  // Tests that a query with an empty array of languages will return an empty
  // result set, without going through the server. (Our test backend wouldn't
  // care about languages.)
  $results = $this->index
    ->query()
    ->setLanguages([])
    ->execute();
  $this
    ->assertEquals(0, $results
    ->getResultCount(), 'Query with empty languages list returned correct number of results.');
  $this
    ->assertEquals([], $results
    ->getResultItems(), 'Query with empty languages list returned correct result.');

  // Test that the index needs to be updated.
  $this
    ->assertEquals(1, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'The updated items needs to be reindexed.');
  $this
    ->assertEquals(4, $this->index
    ->getTrackerInstance()
    ->getTotalItemsCount(), 'There are four items in total.');

  // Delete one translation and test that the datasource returns only three
  // items.
  $entity_1
    ->removeTranslation($this->langcodes[2]);
  $entity_1
    ->save();
  $datasource_item_ids = $datasource
    ->getItemIds();
  sort($datasource_item_ids);
  $expected = [
    '1:' . $this->langcodes[0],
    '1:' . $this->langcodes[1],
    '2:en',
  ];
  $this
    ->assertEquals($expected, $datasource_item_ids, 'Datasource returns correct item ids for a translated entity.');

  // Test reindexing.
  $this
    ->assertEquals(3, $this->index
    ->getTrackerInstance()
    ->getTotalItemsCount(), 'There are three items in total.');
  $this
    ->assertEquals(1, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'The updated items needs to be reindexed.');
  $this->index
    ->indexItems();
  $this
    ->assertEquals(3, $this->index
    ->getTrackerInstance()
    ->getIndexedItemsCount(), 'Three items are indexed.');
}