From a547ae61783bfe21a94acc077c66c015a7dd7c57 Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Mon, 7 Mar 2016 09:21:33 +0900
Subject: [PATCH] Issue #2412569 by claudiu.cristea, amateescu, yched, jibran,
 epari.siva: Allow setting the auto-create bundle on entity reference fields
 with multiple target bundles

---
 core/config/schema/core.data_types.schema.yml |   3 +
 .../DefaultSelection.php                      |  41 +++++++
 .../Field/FieldType/EntityReferenceItem.php   |  15 ++-
 .../EntityReferenceAutocompleteWidget.php     |  26 ++---
 core/modules/field/field.install              |  36 +++++++
 core/modules/field/field.module               |   2 +-
 .../EntityReferenceAdminTest.php              |  82 ++++++++++++--
 .../EntityReferenceAutoCreateTest.php         | 102 +++++++++++++++++-
 .../src/Tests/Update/FieldUpdateTest.php      |  20 ++++
 ...views_entity_reference_plugins-2429191.php |  37 +++++--
 ...e.article.field_ref_autocreate_2412569.yml |  29 +++++
 ...rage.node.field_ref_autocreate_2412569.yml |  20 ++++
 .../TermSelection.php                         |   7 --
 13 files changed, 376 insertions(+), 44 deletions(-)
 create mode 100644 core/modules/field/tests/fixtures/update/field.field.node.article.field_ref_autocreate_2412569.yml
 create mode 100644 core/modules/field/tests/fixtures/update/field.storage.node.field_ref_autocreate_2412569.yml

diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index 4ab0fd769c3d..559362f506ac 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -795,6 +795,9 @@ entity_reference_selection:
     auto_create:
       type: boolean
       label: 'Create referenced entities if they don''t already exist'
+    auto_create_bundle:
+      type: string
+      label: 'Bundle assigned to the auto-created entities.'
 
 entity_reference_selection.*:
   type: entity_reference_selection
diff --git a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
index b108bb45e89b..e89596c22507 100644
--- a/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
+++ b/core/lib/Drupal/Core/Entity/Plugin/EntityReferenceSelection/DefaultSelection.php
@@ -122,6 +122,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
         'field' => '_none',
       ),
       'auto_create' => FALSE,
+      'auto_create_bundle' => NULL,
     );
 
     if ($entity_type->hasKey('bundle')) {
@@ -139,7 +140,19 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
         '#size' => 6,
         '#multiple' => TRUE,
         '#element_validate' => [[get_class($this), 'elementValidateFilter']],
+        '#ajax' => TRUE,
+        '#limit_validation_errors' => [],
       );
+
+      $form['target_bundles_update'] = [
+        '#type' => 'submit',
+        '#value' => $this->t('Update form'),
+        '#limit_validation_errors' => [],
+        '#attributes' => [
+          'class' => ['js-hide'],
+        ],
+        '#submit' => [[EntityReferenceItem::class, 'settingsAjaxSubmit']],
+      ];
     }
     else {
       $form['target_bundles'] = array(
@@ -207,6 +220,30 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       }
     }
 
+    $form['auto_create'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t("Create referenced entities if they don't already exist"),
+      '#default_value' => $selection_handler_settings['auto_create'],
+      '#weight' => -2,
+    );
+
+    if ($entity_type->hasKey('bundle')) {
+      $bundles = array_intersect_key($bundle_options, array_filter((array) $selection_handler_settings['target_bundles']));
+      $form['auto_create_bundle'] = [
+        '#type' => 'select',
+        '#title' => $this->t('Store new items in'),
+        '#options' => $bundles,
+        '#default_value' => $selection_handler_settings['auto_create_bundle'],
+        '#access' => count($bundles) > 1,
+        '#states' => [
+          'visible' => [
+            ':input[name="settings[handler_settings][auto_create]"]' => ['checked' => TRUE],
+          ],
+        ],
+        '#weight' => -1,
+      ];
+    }
+
     return $form;
   }
 
@@ -221,6 +258,10 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
     if ($form_state->getValue(['settings', 'handler_settings', 'target_bundles']) === []) {
       $form_state->setValue(['settings', 'handler_settings', 'target_bundles'], NULL);
     }
+
+    // Don't store the 'target_bundles_update' button value into the field
+    // config settings.
+    $form_state->unsetValue(['settings', 'handler_settings', 'target_bundles_update']);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 9ad1a9d29aec..4c3235120333 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -413,7 +413,9 @@ public static function calculateDependencies(FieldDefinitionInterface $field_def
       }
     }
 
-    // Depend on target bundle configurations.
+    // Depend on target bundle configurations. Dependencies for 'target_bundles'
+    // also covers the 'auto_create_bundle' setting, if any, because its value
+    // is included in the 'target_bundles' list.
     $handler = $field_definition->getSetting('handler_settings');
     if (!empty($handler['target_bundles'])) {
       if ($bundle_entity_type_id = $target_entity_type->getBundleEntityType()) {
@@ -473,10 +475,19 @@ public static function onDependencyRemoval(FieldDefinitionInterface $field_defin
           foreach ($storage->loadMultiple($handler_settings['target_bundles']) as $bundle) {
             if (isset($dependencies[$bundle->getConfigDependencyKey()][$bundle->getConfigDependencyName()])) {
               unset($handler_settings['target_bundles'][$bundle->id()]);
+
+              // If this bundle is also used in the 'auto_create_bundle'
+              // setting, disable the auto-creation feature completely.
+              $auto_create_bundle = !empty($handler_settings['auto_create_bundle']) ? $handler_settings['auto_create_bundle'] : FALSE;
+              if ($auto_create_bundle && $auto_create_bundle == $bundle->id()) {
+                $handler_settings['auto_create'] = NULL;
+                $handler_settings['auto_create_bundle'] = NULL;
+              }
+
               $bundles_changed = TRUE;
 
               // In case we deleted the only target bundle allowed by the field
-              // we have to log a warning message because the field will not
+              // we have to log a critical message because the field will not
               // function correctly anymore.
               if ($handler_settings['target_bundles'] === []) {
                 \Drupal::logger('entity_reference')->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
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 79eff67b7579..667d01309b22 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -106,9 +106,9 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
       '#placeholder' => $this->getSetting('placeholder'),
     );
 
-    if ($this->getSelectionHandlerSetting('auto_create')) {
+    if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) {
       $element['#autocreate'] = array(
-        'bundle' => $this->getAutocreateBundle(),
+        'bundle' => $bundle,
         'uid' => ($entity instanceof EntityOwnerInterface) ? $entity->getOwnerId() : \Drupal::currentUser()->id()
       );
     }
@@ -147,18 +147,20 @@ public function massageFormValues(array $values, array $form, FormStateInterface
    */
   protected function getAutocreateBundle() {
     $bundle = NULL;
-    if ($this->getSelectionHandlerSetting('auto_create')) {
-      // If the 'target_bundles' setting is restricted to a single choice, we
-      // can use that.
-      if (($target_bundles = $this->getSelectionHandlerSetting('target_bundles')) && count($target_bundles) == 1) {
+    if ($this->getSelectionHandlerSetting('auto_create') && $target_bundles = $this->getSelectionHandlerSetting('target_bundles')) {
+      // If there's only one target bundle, use it.
+      if (count($target_bundles) == 1) {
         $bundle = reset($target_bundles);
       }
-      // Otherwise use the first bundle as a fallback.
-      else {
-        // @todo Expose a proper UI for choosing the bundle for autocreated
-        // entities in https://www.drupal.org/node/2412569.
-        $bundles = entity_get_bundles($this->getFieldSetting('target_type'));
-        $bundle = key($bundles);
+      // Otherwise use the target 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.
+        trigger_error(sprintf(
+          "The 'Create referenced entities if they don't already exist' option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
+          $this->fieldDefinition->getLabel(),
+          $this->fieldDefinition->getName()
+        ), E_USER_WARNING);
       }
     }
 
diff --git a/core/modules/field/field.install b/core/modules/field/field.install
index 1860ad8e6382..ecd2b3150bd0 100644
--- a/core/modules/field/field.install
+++ b/core/modules/field/field.install
@@ -68,3 +68,39 @@ function field_update_8002() {
     }
   }
 }
+
+/**
+ * Populate the new 'auto_create_bundle' setting for entity reference fields.
+ */
+function field_update_8003() {
+  $config = \Drupal::configFactory();
+  /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
+  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
+
+  // Iterate over all fields.
+  foreach ($config->listAll('field.field.') as $field_id) {
+    $field = $config->getEditable($field_id);
+    $class = $field_type_manager->getPluginClass($field->get('field_type'));
+
+    // Deal only with entity reference fields and descendants.
+    if ($class == EntityReferenceItem::class || is_subclass_of($class, EntityReferenceItem::class)) {
+      $handler_settings = $field->get('settings.handler_settings');
+
+      if (is_array($handler_settings) && !empty($handler_settings['auto_create'])) {
+        // If the field can reference multiple bundles, pick the first one
+        // available in order to replicate the previous behavior.
+        if (is_array($handler_settings['target_bundles']) && count($handler_settings['target_bundles']) > 1) {
+          $handler_settings['auto_create_bundle'] = reset($handler_settings['target_bundles']);
+        }
+        // Otherwise, we don't know which bundle to use for auto-creation so we
+        // have to disable the functionality completely.
+        elseif (!$handler_settings['target_bundles']) {
+          $handler_settings['auto_create'] = FALSE;
+          $handler_settings['auto_create_bundle'] = NULL;
+        }
+      }
+
+      $field->set('settings.handler_settings', $handler_settings)->save(TRUE);
+    }
+  }
+}
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index e453c46cbb7a..51b82e906fc1 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -250,7 +250,7 @@ function field_entity_bundle_delete($entity_type_id, $bundle) {
         $field_config->save();
 
         // In case we deleted the only target bundle allowed by the field we
-        // have to log a warning message because the field will not function
+        // have to log a critical message because the field will not function
         // correctly anymore.
         if ($handler_settings['target_bundles'] === []) {
           \Drupal::logger('entity_reference')->critical('The %target_bundle bundle (entity type: %target_entity_type) was deleted. As a result, the %field_name entity reference field (entity_type: %entity_type, bundle: %bundle) no longer has any valid bundle it can reference. The field is not working correctly anymore and has to be adjusted.', [
diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php
index 9ee63b0732b2..0d8c4b902719 100644
--- a/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php
+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceAdminTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\field\Tests\EntityReference;
 
+use Drupal\Component\Utility\Unicode;
+use Drupal\field\Entity\FieldConfig;
 use Drupal\Core\Entity\Entity;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field_ui\Tests\FieldUiTestTrait;
@@ -315,7 +317,7 @@ public function testFieldAdminHandler() {
 
     // Tests adding default values to autocomplete widgets.
     Vocabulary::create(array('vid' => 'tags', 'name' => 'tags'))->save();
-    $taxonomy_term_field_name = $this->createEntityReferenceField('taxonomy_term', 'tags');
+    $taxonomy_term_field_name = $this->createEntityReferenceField('taxonomy_term', ['tags']);
     $field_path = 'node.' . $this->type . '.field_' . $taxonomy_term_field_name;
     $this->drupalGet($bundle_path . '/fields/' . $field_path . '/storage');
     $edit = [
@@ -348,13 +350,13 @@ public function testAvailableFormatters() {
     Vocabulary::create(array('vid' => 'tags', 'name' => 'tags'))->save();
 
     // Create entity reference field with taxonomy term as a target.
-    $taxonomy_term_field_name = $this->createEntityReferenceField('taxonomy_term', 'tags');
+    $taxonomy_term_field_name = $this->createEntityReferenceField('taxonomy_term', ['tags']);
 
     // Create entity reference field with user as a target.
     $user_field_name = $this->createEntityReferenceField('user');
 
     // Create entity reference field with node as a target.
-    $node_field_name = $this->createEntityReferenceField('node', $this->type);
+    $node_field_name = $this->createEntityReferenceField('node', [$this->type]);
 
     // Create entity reference field with date format as a target.
     $date_format_field_name = $this->createEntityReferenceField('date_format');
@@ -402,18 +404,79 @@ public function testAvailableFormatters() {
     ));
   }
 
+  /**
+   * Tests field settings for an entity reference field when the field has
+   * multiple target bundles and is set to auto-create the target entity.
+   */
+  public function testMultipleTargetBundles() {
+    /** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabularies */
+    $vocabularies = [];
+    for ($i = 0; $i < 2; $i++) {
+      $vid = Unicode::strtolower($this->randomMachineName());
+      $vocabularies[$i] = Vocabulary::create([
+        'name' => $this->randomString(),
+        'vid' => $vid,
+      ]);
+      $vocabularies[$i]->save();
+    }
+
+    // Create a new field pointing to the first vocabulary.
+    $field_name = $this->createEntityReferenceField('taxonomy_term', [$vocabularies[0]->id()]);
+    $field_name = "field_$field_name";
+    $field_id = 'node.' . $this->type . '.' . $field_name;
+    $path = 'admin/structure/types/manage/' . $this->type . '/fields/' . $field_id;
+
+    $this->drupalGet($path);
+
+    // Expect that there's no 'auto_create_bundle' selected.
+    $this->assertNoFieldByName('settings[handler_settings][auto_create_bundle]');
+
+    $edit = [
+      'settings[handler_settings][target_bundles][' . $vocabularies[1]->id() . ']' => TRUE,
+    ];
+    // Enable the second vocabulary as a target bundle.
+    $this->drupalPostAjaxForm($path, $edit, key($edit));
+    // Expect a select element with the two vocabularies as options.
+    $this->assertFieldByXPath("//select[@name='settings[handler_settings][auto_create_bundle]']/option[@value='" . $vocabularies[0]->id() . "']");
+    $this->assertFieldByXPath("//select[@name='settings[handler_settings][auto_create_bundle]']/option[@value='" . $vocabularies[1]->id() . "']");
+
+    $edit = [
+      'settings[handler_settings][auto_create]' => TRUE,
+      'settings[handler_settings][auto_create_bundle]' => $vocabularies[1]->id(),
+    ];
+    $this->drupalPostForm(NULL, $edit, t('Save settings'));
+
+    /** @var \Drupal\field\Entity\FieldConfig $field_config */
+    $field_config = FieldConfig::load($field_id);
+    // Expect that the target bundle has been saved in the backend.
+    $this->assertEqual($field_config->getSetting('handler_settings')['auto_create_bundle'], $vocabularies[1]->id());
+
+    // Delete the other bundle. Field config should not be affected.
+    $vocabularies[0]->delete();
+    $field_config = FieldConfig::load($field_id);
+    $this->assertTrue($field_config->getSetting('handler_settings')['auto_create']);
+    $this->assertIdentical($field_config->getSetting('handler_settings')['auto_create_bundle'], $vocabularies[1]->id());
+
+    // Delete the bundle set for entity auto-creation. Auto-created settings
+    // should be reset (no auto-creation).
+    $vocabularies[1]->delete();
+    $field_config = FieldConfig::load($field_id);
+    $this->assertFalse($field_config->getSetting('handler_settings')['auto_create']);
+    $this->assertFalse(isset($field_config->getSetting('handler_settings')['auto_create_bundle']));
+  }
+
   /**
    * Creates a new Entity Reference fields with a given target type.
    *
-   * @param $target_type
+   * @param string $target_type
    *   The name of the target type
-   * @param $bundle
-   *   Name of the bundle
-   *   Default = NULL
+   * @param string[] $bundles
+   *   A list of bundle IDs. Defaults to [].
+   *
    * @return string
    *   Returns the generated field name
    */
-  public function createEntityReferenceField($target_type, $bundle = NULL) {
+  protected function createEntityReferenceField($target_type, $bundles = []) {
     // Generates a bundle path for the newly created content type.
     $bundle_path = 'admin/structure/types/manage/' . $this->type;
 
@@ -422,7 +485,7 @@ public function createEntityReferenceField($target_type, $bundle = NULL) {
 
     $storage_edit = $field_edit = array();
     $storage_edit['settings[target_type]'] = $target_type;
-    if ($bundle) {
+    foreach ($bundles as $bundle) {
       $field_edit['settings[handler_settings][target_bundles][' . $bundle . ']'] = TRUE;
     }
 
@@ -432,7 +495,6 @@ public function createEntityReferenceField($target_type, $bundle = NULL) {
     return $field_name;
   }
 
-
   /**
    * Checks if a select element contains the specified options.
    *
diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
index a381b1f93ab8..acaabdbd71a5 100644
--- a/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
+++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceAutoCreateTest.php
@@ -7,9 +7,11 @@
 
 namespace Drupal\field\Tests\EntityReference;
 
+use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Field\FieldStorageDefinitionInterface;
 use Drupal\field\Entity\FieldConfig;
 use Drupal\simpletest\WebTestBase;
+use Drupal\taxonomy\Entity\Vocabulary;
 use Drupal\node\Entity\Node;
 use Drupal\field\Entity\FieldStorageConfig;
 
@@ -20,7 +22,9 @@
  */
 class EntityReferenceAutoCreateTest extends WebTestBase {
 
-  public static $modules = ['node'];
+  use EntityReferenceTestTrait;
+
+  public static $modules = ['node', 'taxonomy'];
 
   /**
    * The name of a content type that will reference $referencedType.
@@ -84,6 +88,9 @@ protected function setUp() {
         'type' => 'entity_reference_autocomplete',
       ))
       ->save();
+
+    $account = $this->drupalCreateUser(['access content', "create $this->referencingType content"]);
+    $this->drupalLogin($account);
   }
 
   /**
@@ -91,9 +98,6 @@ protected function setUp() {
    * entity.
    */
   public function testAutoCreate() {
-    $user1 = $this->drupalCreateUser(array('access content', "create $this->referencingType content"));
-    $this->drupalLogin($user1);
-
     $this->drupalGet('node/add/' . $this->referencingType);
     $this->assertFieldByXPath('//input[@id="edit-test-field-0-target-id" and contains(@class, "form-autocomplete")]', NULL, 'The autocomplete input element appears.');
 
@@ -136,4 +140,94 @@ public function testAutoCreate() {
     $this->assertText($referencing_node->label(), 'Referencing node label found.');
     $this->assertText($referenced_node->label(), 'Referenced node label found.');
   }
+
+  /**
+   * Tests if an entity reference field having multiple target bundles is
+   * storing the auto-created entity in the right destination.
+   */
+  public function testMultipleTargetBundles() {
+    /** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabularies */
+    $vocabularies = [];
+    for ($i = 0; $i < 2; $i++) {
+      $vid = Unicode::strtolower($this->randomMachineName());
+      $vocabularies[$i] = Vocabulary::create([
+        'name' => $this->randomMachineName(),
+        'vid' => $vid,
+      ]);
+      $vocabularies[$i]->save();
+    }
+
+    // Create a taxonomy term entity reference field that saves the auto-created
+    // taxonomy terms in the second vocabulary from the two that were configured
+    // as targets.
+    $field_name = Unicode::strtolower($this->randomMachineName());
+    $handler_settings = [
+      'target_bundles' => [
+        $vocabularies[0]->id() => $vocabularies[0]->id(),
+        $vocabularies[1]->id() => $vocabularies[1]->id(),
+      ],
+      'auto_create' => TRUE,
+      'auto_create_bundle' => $vocabularies[1]->id(),
+    ];
+    $this->createEntityReferenceField('node', $this->referencingType, $field_name, $this->randomString(), 'taxonomy_term', 'default', $handler_settings);
+    /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $fd */
+    entity_get_form_display('node', $this->referencingType, 'default')
+      ->setComponent($field_name, ['type' => 'entity_reference_autocomplete'])
+      ->save();
+
+    $term_name = $this->randomString();
+    $edit = [
+      $field_name . '[0][target_id]' => $term_name,
+      'title[0][value]' => $this->randomString(),
+    ];
+
+    $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Save');
+    /** @var \Drupal\taxonomy\Entity\Term $term */
+    $term = taxonomy_term_load_multiple_by_name($term_name);
+    $term = reset($term);
+
+    // The new term is expected to be stored in the second vocabulary.
+    $this->assertEqual($vocabularies[1]->id(), $term->bundle());
+
+    /** @var \Drupal\field\Entity\FieldConfig $field_config */
+    $field_config = FieldConfig::loadByName('node', $this->referencingType, $field_name);
+    $handler_settings = $field_config->getSetting('handler_settings');
+
+    // Change the field setting to store the auto-created terms in the first
+    // vocabulary and test again.
+    $handler_settings['auto_create_bundle'] = $vocabularies[0]->id();
+    $field_config->setSetting('handler_settings', $handler_settings);
+    $field_config->save();
+
+    $term_name = $this->randomString();
+    $edit = [
+      $field_name . '[0][target_id]' => $term_name,
+      'title[0][value]' => $this->randomString(),
+    ];
+
+    $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Save');
+    /** @var \Drupal\taxonomy\Entity\Term $term */
+    $term = taxonomy_term_load_multiple_by_name($term_name);
+    $term = reset($term);
+
+    // The second term is expected to be stored in the first vocabulary.
+    $this->assertEqual($vocabularies[0]->id(), $term->bundle());
+
+    // @todo Re-enable this test when WebTestBase::curlHeaderCallback() provides
+    //   a way to catch and assert user-triggered errors.
+
+    // Test the case when the field config settings are inconsistent.
+    //unset($handler_settings['auto_create_bundle']);
+    //$field_config->setSetting('handler_settings', $handler_settings);
+    //$field_config->save();
+    //
+    //$this->drupalGet('node/add/' . $this->referencingType);
+    //$error_message = sprintf(
+    //  "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
+    //  $field_config->getLabel(),
+    //  $field_config->getName()
+    //);
+    //$this->assertErrorLogged($error_message);
+  }
+
 }
diff --git a/core/modules/field/src/Tests/Update/FieldUpdateTest.php b/core/modules/field/src/Tests/Update/FieldUpdateTest.php
index 65ca7200aeb3..d555f47d2a31 100644
--- a/core/modules/field/src/Tests/Update/FieldUpdateTest.php
+++ b/core/modules/field/src/Tests/Update/FieldUpdateTest.php
@@ -111,6 +111,26 @@ public function testFieldUpdate8002() {
     $this->assertEqual(array_keys($referencable['article']), [$node_1->id()]);
   }
 
+  /**
+   * Tests field_update_8003().
+   *
+   * @see field_update_8003()
+   */
+  public function testFieldUpdate8003() {
+    // Run updates.
+    $this->runUpdates();
+
+    // Check that the new 'auto_create_bundle' setting is populated correctly.
+    $field = $this->configFactory->get('field.field.node.article.field_ref_autocreate_2412569');
+    $handler_settings = $field->get('settings.handler_settings');
+
+    $expected_target_bundles = ['tags' => 'tags', 'test' => 'test'];
+    $this->assertEqual($handler_settings['target_bundles'], $expected_target_bundles);
+
+    $this->assertTrue($handler_settings['auto_create']);
+    $this->assertEqual($handler_settings['auto_create_bundle'], 'tags');
+  }
+
   /**
    * Asserts that a config depends on 'entity_reference' or not
    *
diff --git a/core/modules/field/tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php b/core/modules/field/tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php
index 90f395b6419b..ca7c51a1db74 100644
--- a/core/modules/field/tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php
+++ b/core/modules/field/tests/fixtures/update/drupal-8.views_entity_reference_plugins-2429191.php
@@ -26,8 +26,14 @@
   ])
   ->execute();
 
-// Configuration for an entity_reference field storage.
-$config = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_views_select_2429191.yml'));
+// Configuration for an entity_reference field storage using the View for
+// selection.
+$field_ref_views_select_2429191 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_views_select_2429191.yml'));
+
+// Configuration for an entity_reference field storage using the auto-create
+// feature.
+$field_ref_autocreate_2412569 = Yaml::decode(file_get_contents(__DIR__ . '/field.storage.node.field_ref_autocreate_2412569.yml'));
+
 $connection->insert('config')
   ->fields([
     'collection',
@@ -36,8 +42,13 @@
   ])
   ->values([
     'collection' => '',
-    'name' => 'field.storage.' . $config['id'],
-    'data' => serialize($config),
+    'name' => 'field.storage.' . $field_ref_views_select_2429191['id'],
+    'data' => serialize($field_ref_views_select_2429191),
+  ])
+  ->values([
+    'collection' => '',
+    'name' => 'field.storage.' . $field_ref_autocreate_2412569['id'],
+    'data' => serialize($field_ref_autocreate_2412569),
   ])
   ->execute();
 // We need to Update the registry of "last installed" field definitions.
@@ -48,7 +59,8 @@
   ->execute()
   ->fetchField();
 $installed = unserialize($installed);
-$installed['field_ref_views_select_2429191'] = new \Drupal\field\Entity\FieldStorageConfig($config);
+$installed['field_ref_views_select_2429191'] = new \Drupal\field\Entity\FieldStorageConfig($field_ref_views_select_2429191);
+$installed['field_ref_autocreate_2412569'] = new \Drupal\field\Entity\FieldStorageConfig($field_ref_autocreate_2412569);
 $connection->update('key_value')
   ->condition('collection', 'entity.definitions.installed')
   ->condition('name', 'node.field_storage_definitions')
@@ -58,7 +70,11 @@
   ->execute();
 
 // Configuration for an entity_reference field using the View for selection.
-$config = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_ref_views_select_2429191.yml'));
+$field_ref_views_select_2429191 = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_ref_views_select_2429191.yml'));
+
+// Configuration for an entity_reference field using the auto-create feature.
+$field_ref_autocreate_2412569 = Yaml::decode(file_get_contents(__DIR__ . '/field.field.node.article.field_ref_autocreate_2412569.yml'));
+
 $connection->insert('config')
   ->fields([
     'collection',
@@ -67,7 +83,12 @@
   ])
   ->values([
     'collection' => '',
-    'name' => 'field.field.' . $config['id'],
-    'data' => serialize($config),
+    'name' => 'field.field.' . $field_ref_views_select_2429191['id'],
+    'data' => serialize($field_ref_views_select_2429191),
+  ])
+  ->values([
+    'collection' => '',
+    'name' => 'field.field.' . $field_ref_autocreate_2412569['id'],
+    'data' => serialize($field_ref_autocreate_2412569),
   ])
   ->execute();
diff --git a/core/modules/field/tests/fixtures/update/field.field.node.article.field_ref_autocreate_2412569.yml b/core/modules/field/tests/fixtures/update/field.field.node.article.field_ref_autocreate_2412569.yml
new file mode 100644
index 000000000000..2606bf6f0aa5
--- /dev/null
+++ b/core/modules/field/tests/fixtures/update/field.field.node.article.field_ref_autocreate_2412569.yml
@@ -0,0 +1,29 @@
+uuid: d6deba8d-073a-4572-a000-ee2a2de94de2
+langcode: en
+status: true
+dependencies:
+  config:
+    - field.storage.node.field_ref_autocreate_2412569
+    - node.type.article
+    - taxonomy.vocabulary.tags
+    - taxonomy.vocabulary.test
+id: node.article.field_ref_autocreate_2412569
+field_name: field_ref_autocreate_2412569
+entity_type: node
+bundle: article
+label: 'Ref Autocreate 2412569'
+description: ''
+required: false
+translatable: false
+default_value: {  }
+default_value_callback: ''
+settings:
+  handler: 'default:taxonomy_term'
+  handler_settings:
+    target_bundles:
+      tags: tags
+      test: test
+    sort:
+      field: _none
+    auto_create: true
+field_type: entity_reference
diff --git a/core/modules/field/tests/fixtures/update/field.storage.node.field_ref_autocreate_2412569.yml b/core/modules/field/tests/fixtures/update/field.storage.node.field_ref_autocreate_2412569.yml
new file mode 100644
index 000000000000..19e4a6abf76c
--- /dev/null
+++ b/core/modules/field/tests/fixtures/update/field.storage.node.field_ref_autocreate_2412569.yml
@@ -0,0 +1,20 @@
+uuid: 5e4095a3-8f89-4d7a-b222-34bf5240b646
+langcode: en
+status: true
+dependencies:
+  module:
+    - node
+    - taxonomy
+id: node.field_ref_autocreate_2412569
+field_name: field_ref_autocreate_2412569
+entity_type: node
+type: entity_reference
+settings:
+  target_type: taxonomy_term
+module: core
+locked: false
+cardinality: 1
+translatable: true
+indexes: {  }
+persist_with_no_fields: false
+custom_storage: false
diff --git a/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
index ef8a89239fb1..f9bb7374493b 100644
--- a/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
+++ b/core/modules/taxonomy/src/Plugin/EntityReferenceSelection/TermSelection.php
@@ -40,13 +40,6 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
     $form = parent::buildConfigurationForm($form, $form_state);
 
     $form['target_bundles']['#title'] = $this->t('Available Vocabularies');
-    // @todo: Currently allow auto-create only on taxonomy terms.
-    $form['auto_create'] = array(
-      '#type' => 'checkbox',
-      '#weight' => -1,
-      '#title' => $this->t("Create referenced entities if they don't already exist"),
-      '#default_value' => isset($this->configuration['handler_settings']['auto_create']) ? $this->configuration['handler_settings']['auto_create'] : FALSE,
-    );
 
     // Sorting is not possible for taxonomy terms because we use
     // \Drupal\taxonomy\TermStorageInterface::loadTree() to retrieve matches.
-- 
GitLab