Issue #3489179 by godotislate, ghost of drupal past: Referring the same entity multiple times breaks _referringItem
parent
b45e19af0d
commit
40c1ab5260
|
@ -57,7 +57,14 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
|
|||
$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 @@ class EntityReferenceFormatterTest extends EntityKernelTestBase {
|
|||
$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 @@ abstract class ImageFormatterBase extends FileFormatterBase {
|
|||
'_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 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase {
|
|||
$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.
|
||||
|
|
Loading…
Reference in New Issue