Issue #2966137 by vaplas, tim.plunkett: Circular entity references cause infinite loop in EntityReferenceItem::generateSampleValue()
parent
75850cddaf
commit
89a7f66bc8
|
@ -272,6 +272,10 @@ class EntityReferenceItem extends FieldItemBase implements OptionsProviderInterf
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public static function generateSampleValue(FieldDefinitionInterface $field_definition) {
|
||||
// An associative array keyed by the reference type, target type, and
|
||||
// bundle.
|
||||
static $recursion_tracker = [];
|
||||
|
||||
$manager = \Drupal::service('plugin.manager.entity_reference_selection');
|
||||
|
||||
// Instead of calling $manager->getSelectionHandler($field_definition)
|
||||
|
@ -300,9 +304,25 @@ class EntityReferenceItem extends FieldItemBase implements OptionsProviderInterf
|
|||
|
||||
// Attempt to create a sample entity, avoiding recursion.
|
||||
$entity_storage = \Drupal::entityTypeManager()->getStorage($options['target_type']);
|
||||
if ($options['target_type'] !== $field_definition->getTargetEntityTypeId() && $entity_storage instanceof ContentEntityStorageInterface) {
|
||||
if ($entity_storage instanceof ContentEntityStorageInterface) {
|
||||
$bundle = static::getRandomBundle($entity_type, $options['handler_settings']);
|
||||
$values['entity'] = $entity_storage->createWithSampleValues($bundle);
|
||||
|
||||
// Track the generated entity by reference type, target type, and bundle.
|
||||
$key = $field_definition->getTargetEntityTypeId() . ':' . $options['target_type'] . ':' . $bundle;
|
||||
|
||||
// If entity generation was attempted but did not finish, do not continue.
|
||||
if (isset($recursion_tracker[$key])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Mark this as an attempt at generation.
|
||||
$recursion_tracker[$key] = TRUE;
|
||||
|
||||
// Mark the sample entity as being a preview.
|
||||
$values['entity'] = $entity_storage->createWithSampleValues($bundle, ['in_preview' => TRUE]);
|
||||
|
||||
// Remove the indicator once the entity is successfully generated.
|
||||
unset($recursion_tracker[$key]);
|
||||
return $values;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Drupal\Tests\field\Kernel\EntityReference;
|
||||
|
||||
use Drupal\comment\Entity\Comment;
|
||||
use Drupal\comment\Entity\CommentType;
|
||||
use Drupal\Component\Render\FormattableMarkup;
|
||||
use Drupal\Core\Field\FieldItemListInterface;
|
||||
use Drupal\Core\Field\FieldItemInterface;
|
||||
|
@ -14,6 +15,7 @@ use Drupal\entity_test\Entity\EntityTestStringId;
|
|||
use Drupal\field\Entity\FieldConfig;
|
||||
use Drupal\field\Entity\FieldStorageConfig;
|
||||
use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
|
||||
use Drupal\node\Entity\NodeType;
|
||||
use Drupal\node\NodeInterface;
|
||||
use Drupal\taxonomy\TermInterface;
|
||||
use Drupal\Tests\field\Kernel\FieldKernelTestBase;
|
||||
|
@ -89,6 +91,14 @@ class EntityReferenceItemTest extends FieldKernelTestBase {
|
|||
]);
|
||||
$this->term->save();
|
||||
|
||||
NodeType::create([
|
||||
'type' => $this->randomMachineName(),
|
||||
])->save();
|
||||
CommentType::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
'target_entity_type_id' => 'node',
|
||||
])->save();
|
||||
|
||||
$this->entityStringId = EntityTestStringId::create([
|
||||
'id' => $this->randomMachineName(),
|
||||
]);
|
||||
|
@ -102,6 +112,7 @@ class EntityReferenceItemTest extends FieldKernelTestBase {
|
|||
$this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_user', 'Test user entity reference', 'user');
|
||||
$this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_comment', 'Test comment entity reference', 'comment');
|
||||
$this->createEntityReferenceField('entity_test', 'entity_test', 'field_test_file', 'Test file entity reference', 'file');
|
||||
$this->createEntityReferenceField('entity_test_string_id', 'entity_test_string_id', 'field_test_entity_test', 'Test content entity reference with string ID', 'entity_test');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,6 +222,19 @@ class EntityReferenceItemTest extends FieldKernelTestBase {
|
|||
$this->entityValidateAndSave($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the ::generateSampleValue() method when it has a circular reference.
|
||||
*/
|
||||
public function testGenerateSampleValueCircularReference() {
|
||||
// Delete the existing entity.
|
||||
$this->entityStringId->delete();
|
||||
|
||||
$entity_storage = \Drupal::entityTypeManager()->getStorage('entity_test');
|
||||
$entity = $entity_storage->createWithSampleValues('entity_test');
|
||||
$this->assertInstanceOf(EntityTestStringId::class, $entity->field_test_entity_test_string_id->entity);
|
||||
$this->assertInstanceOf(EntityTest::class, $entity->field_test_entity_test_string_id->entity->field_test_entity_test->entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests referencing content entities with string IDs.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue