function EntityReferenceFormatterTest::testEntityFormatterRecursiveRendering
Same name and namespace in other branches
- 10 core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php \Drupal\Tests\field\Kernel\EntityReference\EntityReferenceFormatterTest::testEntityFormatterRecursiveRendering()
- 9 core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php \Drupal\Tests\field\Kernel\EntityReference\EntityReferenceFormatterTest::testEntityFormatterRecursiveRendering()
- 8.9.x core/modules/field/tests/src/Kernel/EntityReference/EntityReferenceFormatterTest.php \Drupal\Tests\field\Kernel\EntityReference\EntityReferenceFormatterTest::testEntityFormatterRecursiveRendering()
Tests the recursive rendering protection of the entity formatter.
File
-
core/
modules/ field/ tests/ src/ Kernel/ EntityReference/ EntityReferenceFormatterTest.php, line 278
Class
- EntityReferenceFormatterTest
- Tests the formatters functionality.
Namespace
Drupal\Tests\field\Kernel\EntityReferenceCode
public function testEntityFormatterRecursiveRendering() : void {
// Intercept our specific warning and suppress it.
set_error_handler(function (int $errno, string $errstr) : bool {
return $errno === E_USER_WARNING && str_starts_with($errstr, 'Recursive rendering attempt aborted');
});
/** @var \Drupal\Core\Render\RendererInterface $renderer */
$renderer = $this->container
->get('renderer');
$view_builder = $this->entityTypeManager
->getViewBuilder($this->entityType);
$this->createNonCacheableViewMode();
// Set the default view mode to use the 'entity_reference_entity_view'
// formatter.
\Drupal::service('entity_display.repository')->getViewDisplay($this->entityType, $this->bundle)
->setComponent($this->fieldName, [
'type' => 'entity_reference_entity_view',
])
->save();
$storage = \Drupal::entityTypeManager()->getStorage($this->entityType);
$referencing_entity_1 = $storage->create([
'name' => $this->randomMachineName(),
]);
$referencing_entity_1->save();
// Create a self-reference.
$referencing_entity_1->{$this->fieldName}->entity = $referencing_entity_1;
$referencing_entity_1->save();
$referencing_entity_1_label = $referencing_entity_1->label();
// Using a different view mode is not recursion.
$build = $view_builder->view($referencing_entity_1, 'teaser');
$output = (string) $renderer->renderRoot($build);
// 2 occurrences of the entity title per entity.
$expected_occurrences = 4;
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
// Self-references should not be rendered.
// entity_1 -> entity_1
$build = $view_builder->view($referencing_entity_1, $this->nonCacheableViewMode);
$output = (string) $renderer->renderRoot($build);
$expected_occurrences = 2;
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
$build = $view_builder->view($referencing_entity_1, $this->nonCacheableViewMode);
// Repetition is not wrongly detected as recursion.
// entity_1 -> entity_1
$output = (string) $renderer->renderRoot($build);
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
// Referencing from another entity works fine.
// entity_2 -> entity_1
$referencing_entity_2 = $storage->create([
'name' => $this->randomMachineName(),
]);
$referencing_entity_2->save();
$referencing_entity_2_label = $referencing_entity_2->label();
$referencing_entity_2->{$this->fieldName}->entity = $referencing_entity_1;
$referencing_entity_2->save();
$build = $view_builder->view($referencing_entity_2, $this->nonCacheableViewMode);
$output = (string) $renderer->renderRoot($build);
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
// Referencing from multiple is fine.
// entity_1 -> entity_1
// entity_2 -> entity_1
$build = $view_builder->viewMultiple([
$referencing_entity_1,
$referencing_entity_2,
], $this->nonCacheableViewMode);
$output = (string) $renderer->renderRoot($build);
// entity_1 should be seen once as a parent and once as a child of entity_2.
$expected_occurrences = 4;
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
// entity_2 is seen only once, as a parent.
$expected_occurrences = 2;
$actual_occurrences = substr_count($output, $referencing_entity_2_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
// Indirect recursion is not ok.
// entity_2 -> entity_1 -> entity_2
$referencing_entity_1->{$this->fieldName}->entity = $referencing_entity_2;
$referencing_entity_1->save();
$build = $view_builder->view($referencing_entity_2, $this->nonCacheableViewMode);
$output = (string) $renderer->renderRoot($build);
// Each entity should be seen once.
$expected_occurrences = 2;
$actual_occurrences = substr_count($output, $referencing_entity_1_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
$expected_occurrences = 2;
$actual_occurrences = substr_count($output, $referencing_entity_2_label);
$this->assertEquals($expected_occurrences, $actual_occurrences);
restore_error_handler();
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.