Skip to content
Snippets Groups Projects
Commit 80f2ff71 authored by catch's avatar catch
Browse files

Issue #3489179 by godotislate, ghost of drupal past: Referring the same entity...

Issue #3489179 by godotislate, ghost of drupal past: Referring the same entity multiple times breaks _referringItem

(cherry picked from commit 40c1ab52)
parent d2b22e76
No related branches found
No related tags found
3 merge requests!11017Issue #3502540: Add date filter for moderated content.,!11009Issue #3486972 migrate feed icon,!10999Cleaning up Taxonomy hooks and updating baseline.
Pipeline #407727 passed
......@@ -57,7 +57,14 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item
$item->_accessCacheability = CacheableMetadata::createFromObject($access);
if ($access->isAllowed()) {
// Add the referring item, in case the formatter needs it.
$entity->_referringItem = $items[$delta];
if (isset($entity->_referringItem) && ($entity->_referringItem !== $item)) {
// If the entity is already being referenced by another field item,
// clone the entity so that _referringItem is set to the correct
// item in each instance.
$entity = clone $entity;
$item->entity = $entity;
}
$entity->_referringItem = $item;
$entities[$delta] = $entity;
}
}
......
......@@ -424,6 +424,44 @@ public function testLabelFormatter(): void {
$this->assertEquals($build[0]['#plain_text'], $entity_with_user->get('user_id')->entity->label(), 'For inaccessible links, the label should be displayed in plain text.');
}
/**
* Tests formatters set the correct _referringItem on referenced entities.
*/
public function testFormatterReferencingItem(): void {
$storage = \Drupal::entityTypeManager()->getStorage($this->entityType);
// Create a referencing entity and confirm that the _referringItem property
// on the referenced entity in the built render array's items is set to the
// field item on the referencing entity.
$referencing_entity_1 = $storage->create([
'name' => $this->randomMachineName(),
$this->fieldName => $this->referencedEntity,
]);
$referencing_entity_1->save();
$build_1 = $referencing_entity_1->get($this->fieldName)->view(['type' => 'entity_reference_entity_view']);
$this->assertEquals($this->referencedEntity->id(), $build_1['#items'][0]->entity->id());
$this->assertEquals($referencing_entity_1->id(), $build_1['#items'][0]->entity->_referringItem->getEntity()->id());
$this->assertEquals($referencing_entity_1->id(), $build_1[0]['#' . $this->entityType]->_referringItem->getEntity()->id());
// Create a second referencing entity and confirm that the _referringItem
// property on the referenced entity in the built render array's items is
// set to the field item on the second referencing entity.
$referencing_entity_2 = $storage->create([
'name' => $this->randomMachineName(),
$this->fieldName => $this->referencedEntity,
]);
$referencing_entity_2->save();
$build_2 = $referencing_entity_2->get($this->fieldName)->view(['type' => 'entity_reference_entity_view']);
$this->assertEquals($this->referencedEntity->id(), $build_2['#items'][0]->entity->id());
$this->assertEquals($referencing_entity_2->id(), $build_2['#items'][0]->entity->_referringItem->getEntity()->id());
$this->assertEquals($referencing_entity_2->id(), $build_2[0]['#' . $this->entityType]->_referringItem->getEntity()->id());
// Confirm that the _referringItem property for the entity referenced by the
// first referencing entity is still set to the field item on the first
// referencing entity.
$this->assertEquals($referencing_entity_1->id(), $build_1['#items'][0]->entity->_referringItem->getEntity()->id());
// Confirm that the _referringItem property is not the same for the two
// render arrays.
$this->assertNotEquals($build_1['#items'][0]->entity->_referringItem->getEntity()->id(), $build_2['#items'][0]->entity->_referringItem->getEntity()->id());
}
/**
* Sets field values and returns a render array.
*
......
......@@ -38,6 +38,13 @@ protected function getEntitiesToView(EntityReferenceFieldItemListInterface $item
'_loaded' => TRUE,
'_is_default' => TRUE,
]);
if ($file->_referringItem) {
// If the file entity is already being referenced by another field
// item, clone it so that _referringItem is set to the correct item
// in each instance.
$file = clone $file;
$items[0]->entity = $file;
}
$file->_referringItem = $items[0];
}
}
......
......@@ -145,6 +145,27 @@ public function testDefaultImages(): void {
$article = $this->drupalCreateNode(['type' => 'article']);
$article_built = $this->drupalBuildEntityView($article);
$this->assertEquals($default_images['field']->id(), $article_built[$field_name][0]['#item']->target_id, "A new article node without an image has the expected default image file ID of {$default_images['field']->id()}.");
// Confirm that the default image entity _referringItem property is set to
// the field item on the article node.
$article_default_image_referring_entity = $article_built[$field_name][0]['#item']->entity->_referringItem->getEntity();
$this->assertEquals($article->id(), $article_default_image_referring_entity->id());
// Confirm that the image default is shown for another new article node.
$article2 = $this->drupalCreateNode(['type' => 'article']);
$article2_built = $this->drupalBuildEntityView($article2);
$this->assertEquals($default_images['field']->id(), $article2_built[$field_name][0]['#item']->target_id, "A new article node without an image has the expected default image file ID of {$default_images['field']->id()}.");
// Confirm that the default image entity _referringItem property is set to
// the field item on the second article node.
$article2_default_image_referring_entity = $article2_built[$field_name][0]['#item']->entity->_referringItem->getEntity();
$this->assertEquals($article2->id(), $article2_default_image_referring_entity->id());
// Confirm that the default image entity _referringItem property on the
// first article is still set to the field item on the article node.
$article_default_image_referring_entity = $article_built[$field_name][0]['#item']->entity->_referringItem->getEntity();
$this->assertEquals($article->id(), $article_default_image_referring_entity->id());
// Confirm that the _referringItem values for the default image entities on
// the two nodes are referring to field items on different nodes.
$this->assertNotEquals($article_default_image_referring_entity->id(), $article2_default_image_referring_entity->id());
// Also check that the field renders without warnings when the label is
// hidden.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment