From 9e46cd9e177c89fb04931ddf28dffc7df3c0077f Mon Sep 17 00:00:00 2001 From: Alex Pott Date: Mon, 21 Sep 2020 14:23:25 +0100 Subject: [PATCH] Issue #2821352 by chr.fritsch, jian he, Pancho, RaphaelBriskie, jonathanshaw, alexpott, amateescu, larowlan: EntityReferenceAutocompleteWidget::getAutocreateBundle() unnecessarily requires the 'target_bundles' setting --- .../DefaultSelection.php | 15 +++--- .../EntityReferenceAutocompleteWidget.php | 17 +++++-- .../EntityReferenceAutoCreateTest.php | 49 ++++++++++++++++++- .../Entity/EntityTestNoBundleWithLabel.php | 28 +++++++++++ 4 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoBundleWithLabel.php diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php index 13e32857bd9..d44a3c6f01f 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php +++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php @@ -373,13 +373,16 @@ class DefaultSelection extends SelectionPluginBase implements ContainerFactoryPl */ public function createNewEntity($entity_type_id, $bundle, $label, $uid) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); - $bundle_key = $entity_type->getKey('bundle'); - $label_key = $entity_type->getKey('label'); - $entity = $this->entityTypeManager->getStorage($entity_type_id)->create([ - $bundle_key => $bundle, - $label_key => $label, - ]); + $values = [ + $entity_type->getKey('label') => $label, + ]; + + if ($bundle_key = $entity_type->getKey('bundle')) { + $values[$bundle_key] = $bundle; + } + + $entity = $this->entityTypeManager->getStorage($entity_type_id)->create($values); if ($entity instanceof EntityOwnerInterface) { $entity->setOwnerId($uid); diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php index af3c80a9b06..d9f5b581f38 100644 --- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php +++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php @@ -117,7 +117,7 @@ class EntityReferenceAutocompleteWidget extends WidgetBase { '#placeholder' => $this->getSetting('placeholder'), ]; - if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) { + if ($bundle = $this->getAutocreateBundle()) { $element['#autocreate'] = [ 'bundle' => $bundle, 'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id(), @@ -154,16 +154,23 @@ class EntityReferenceAutocompleteWidget extends WidgetBase { * Returns the name of the bundle which will be used for autocreated entities. * * @return string - * The bundle name. + * The bundle name. If autocreate is not active, NULL will be returned. */ protected function getAutocreateBundle() { $bundle = NULL; - if ($this->getSelectionHandlerSetting('auto_create') && $target_bundles = $this->getSelectionHandlerSetting('target_bundles')) { + if ($this->getSelectionHandlerSetting('auto_create')) { + $target_bundles = $this->getSelectionHandlerSetting('target_bundles'); + // If there's no target bundle at all, use the target_type. It's the + // default for bundleless entity types. + if (empty($target_bundles)) { + $bundle = $this->getFieldSetting('target_type'); + } // If there's only one target bundle, use it. - if (count($target_bundles) == 1) { + elseif (count($target_bundles) == 1) { $bundle = reset($target_bundles); } - // Otherwise use the target bundle stored in selection handler settings. + // If there's more than one target bundle, use the autocreate bundle + // stored in selection handler settings. elseif (!$bundle = $this->getSelectionHandlerSetting('auto_create_bundle')) { // If no bundle has been set as auto create target means that there is // an inconsistency in entity reference field settings. diff --git a/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php b/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php index 4b03dbfeed5..6f2754ad445 100644 --- a/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php +++ b/core/modules/field/tests/src/Functional/EntityReference/EntityReferenceAutoCreateTest.php @@ -19,7 +19,7 @@ class EntityReferenceAutoCreateTest extends BrowserTestBase { use EntityReferenceTestTrait; - protected static $modules = ['node', 'taxonomy']; + protected static $modules = ['node', 'taxonomy', 'entity_test']; /** * {@inheritdoc} @@ -237,4 +237,51 @@ class EntityReferenceAutoCreateTest extends BrowserTestBase { // $this->assertErrorLogged($error_message); } + /** + * Tests autocreation for an entity that has no bundles. + */ + public function testNoBundles() { + $account = $this->drupalCreateUser([ + 'access content', + "create $this->referencingType content", + 'administer entity_test content', + ]); + $this->drupalLogin($account); + + $field_name = mb_strtolower($this->randomMachineName()); + $handler_settings = [ + 'auto_create' => TRUE, + ]; + $this->createEntityReferenceField('node', $this->referencingType, $field_name, $this->randomString(), 'entity_test_no_bundle_with_label', 'default', $handler_settings); + \Drupal::service('entity_display.repository') + ->getFormDisplay('node', $this->referencingType) + ->setComponent($field_name, ['type' => 'entity_reference_autocomplete']) + ->save(); + + $node_title = $this->randomMachineName(); + $name = $this->randomMachineName(); + $edit = [ + $field_name . '[0][target_id]' => $name, + 'title[0][value]' => $node_title, + ]; + + $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Save'); + + // Assert referenced entity was created. + $result = \Drupal::entityQuery('entity_test_no_bundle_with_label') + ->condition('name', $name) + ->execute(); + $this->assertNotEmpty($result, 'Referenced entity was created.'); + $referenced_id = key($result); + + // Assert the referenced entity is associated with referencing node. + $result = \Drupal::entityQuery('node') + ->condition('type', $this->referencingType) + ->execute(); + $this->assertCount(1, $result); + $referencing_nid = key($result); + $referencing_node = Node::load($referencing_nid); + $this->assertEqual($referenced_id, $referencing_node->$field_name->target_id, 'Newly created node is referenced from the referencing entity.'); + } + } diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoBundleWithLabel.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoBundleWithLabel.php new file mode 100644 index 00000000000..84771f84955 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestNoBundleWithLabel.php @@ -0,0 +1,28 @@ +