diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml
index 81c03dbca0..8850d40ef7 100644
--- a/core/config/schema/core.entity.schema.yml
+++ b/core/config/schema/core.entity.schema.yml
@@ -234,6 +234,9 @@ field.widget.settings.entity_reference_autocomplete_tags:
match_operator:
type: string
label: 'Autocomplete matching'
+ match_limit:
+ type: integer
+ label: 'Maximum number of autocomplete suggestions.'
size:
type: integer
label: 'Size of textfield'
@@ -248,6 +251,9 @@ field.widget.settings.entity_reference_autocomplete:
match_operator:
type: string
label: 'Autocomplete matching'
+ match_limit:
+ type: integer
+ label: 'Maximum number of autocomplete suggestions.'
size:
type: integer
label: 'Size of textfield'
diff --git a/core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php b/core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php
index 2cede4dffa..93a8539ced 100644
--- a/core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php
+++ b/core/lib/Drupal/Core/Entity/EntityAutocompleteMatcher.php
@@ -61,7 +61,8 @@ public function getMatches($target_type, $selection_handler, $selection_settings
if (isset($string)) {
// Get an array of matching entities.
$match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS';
- $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10);
+ $match_limit = isset($selection_settings['match_limit']) ? (int) $selection_settings['match_limit'] : 10;
+ $entity_labels = $handler->getReferenceableEntities($string, $match_operator, $match_limit);
// Loop through the entities and convert them into autocomplete output.
foreach ($entity_labels as $values) {
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 493d6a4f67..a407098f02 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldWidget/EntityReferenceAutocompleteWidget.php
@@ -28,7 +28,8 @@ class EntityReferenceAutocompleteWidget extends WidgetBase {
public static function defaultSettings() {
return [
'match_operator' => 'CONTAINS',
- 'size' => '60',
+ 'match_limit' => 10,
+ 'size' => 60,
'placeholder' => '',
] + parent::defaultSettings();
}
@@ -44,6 +45,13 @@ public function settingsForm(array $form, FormStateInterface $form_state) {
'#options' => $this->getMatchOperatorOptions(),
'#description' => t('Select the method used to collect autocomplete suggestions. Note that Contains can cause performance issues on sites with thousands of entities.'),
];
+ $element['match_limit'] = [
+ '#type' => 'number',
+ '#title' => t('Number of results'),
+ '#default_value' => $this->getSetting('match_limit'),
+ '#min' => 0,
+ '#description' => t('The number of suggestions that will be listed. Use 0 to remove the limit.'),
+ ];
$element['size'] = [
'#type' => 'number',
'#title' => t('Size of textfield'),
@@ -68,6 +76,7 @@ public function settingsSummary() {
$operators = $this->getMatchOperatorOptions();
$summary[] = t('Autocomplete matching: @match_operator', ['@match_operator' => $operators[$this->getSetting('match_operator')]]);
+ $summary[] = t('Autocomplete suggestion list size: @size', ['@size' => $this->getSetting('match_limit') ?: 'unlimited']);
$summary[] = t('Textfield size: @size', ['@size' => $this->getSetting('size')]);
$placeholder = $this->getSetting('placeholder');
if (!empty($placeholder)) {
@@ -88,7 +97,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
$referenced_entities = $items->referencedEntities();
// Append the match operation to the selection settings.
- $selection_settings = $this->getFieldSetting('handler_settings') + ['match_operator' => $this->getSetting('match_operator')];
+ $selection_settings = $this->getFieldSetting('handler_settings') + [
+ 'match_operator' => $this->getSetting('match_operator'),
+ 'match_limit' => $this->getSetting('match_limit'),
+ ];
$element += [
'#type' => 'entity_autocomplete',
diff --git a/core/modules/system/system.post_update.php b/core/modules/system/system.post_update.php
index b4e2b860a7..c08e722d6f 100644
--- a/core/modules/system/system.post_update.php
+++ b/core/modules/system/system.post_update.php
@@ -10,6 +10,7 @@
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\Entity\EntityViewDisplay;
+use Drupal\Core\Field\Plugin\Field\FieldWidget\EntityReferenceAutocompleteWidget;
/**
* Re-save all configuration entities to recalculate dependencies.
@@ -190,3 +191,32 @@ function system_post_update_add_expand_all_items_key_in_system_menu_block(&$sand
return strpos($block->getPluginId(), 'system_menu_block:') === 0;
});
}
+
+/**
+ * Populate the new 'match_limit' setting for entity reference autocomplete widget.
+ */
+function system_post_update_entity_reference_autocomplete_match_limit(&$sandbox = NULL) {
+ $config_entity_updater = \Drupal::classResolver(ConfigEntityUpdater::class);
+ /** @var \Drupal\Core\Field\WidgetPluginManager $field_widget_manager */
+ $field_widget_manager = \Drupal::service('plugin.manager.field.widget');
+
+ $callback = function (EntityDisplayInterface $display) use ($field_widget_manager) {
+ $needs_save = FALSE;
+ foreach ($display->getComponents() as $field_name => $component) {
+ if (empty($component['type'])) {
+ continue;
+ }
+
+ $plugin_definition = $field_widget_manager->getDefinition($component['type'], FALSE);
+ if (is_a($plugin_definition['class'], EntityReferenceAutocompleteWidget::class, TRUE)) {
+ $component['settings']['match_limit'] = 10;
+ $display->setComponent($field_name, $component);
+ $needs_save = TRUE;
+ }
+ }
+
+ return $needs_save;
+ };
+
+ $config_entity_updater->update($sandbox, 'entity_form_display', $callback);
+}
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.media.audio.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.media.audio.default.yml
index 231e7f3bdb..ff4680498f 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.media.audio.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.media.audio.default.yml
@@ -43,6 +43,7 @@ content:
weight: 5
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.media.file.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.media.file.default.yml
index a9fa8831c1..457d3b1a55 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.media.file.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.media.file.default.yml
@@ -43,6 +43,7 @@ content:
weight: 5
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.media.image.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.media.image.default.yml
index fe6cfed79f..58b07fc576 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.media.image.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.media.image.default.yml
@@ -45,6 +45,7 @@ content:
weight: 5
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.media.remote_video.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.media.remote_video.default.yml
index d0924b7042..69d5dab1e5 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.media.remote_video.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.media.remote_video.default.yml
@@ -44,6 +44,7 @@ content:
weight: 4
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.media.video.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.media.video.default.yml
index b21333f87c..482935b5a7 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.media.video.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.media.video.default.yml
@@ -43,6 +43,7 @@ content:
weight: 5
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.node.article.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.node.article.default.yml
index bc28702427..5e94f81013 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.node.article.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.node.article.default.yml
@@ -47,6 +47,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
@@ -97,6 +98,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.node.page.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.node.page.default.yml
index 76b8b9fe0b..71ab408f82 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.node.page.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.node.page.default.yml
@@ -76,6 +76,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
diff --git a/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml b/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml
index f1281c6283..6d0c211624 100644
--- a/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml
+++ b/core/profiles/demo_umami/config/install/core.entity_form_display.node.recipe.default.yml
@@ -78,6 +78,7 @@ content:
weight: 6
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
@@ -103,6 +104,7 @@ content:
weight: 7
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
@@ -154,6 +156,7 @@ content:
weight: 12
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
region: content
diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
index 99d0f60827..b440edaf6f 100644
--- a/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
+++ b/core/profiles/standard/config/install/core.entity_form_display.node.article.default.yml
@@ -53,6 +53,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
@@ -97,6 +98,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
diff --git a/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml b/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
index 682f1a550c..a7bb5b4c37 100644
--- a/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
+++ b/core/profiles/standard/config/install/core.entity_form_display.node.page.default.yml
@@ -68,6 +68,7 @@ content:
region: content
settings:
match_operator: CONTAINS
+ match_limit: 10
size: 60
placeholder: ''
third_party_settings: { }
diff --git a/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php b/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php
index d0b9c2953f..407e4cf37c 100644
--- a/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php
+++ b/core/tests/Drupal/FunctionalJavascriptTests/EntityReference/EntityReferenceAutocompleteWidgetTest.php
@@ -97,6 +97,30 @@ public function testEntityReferenceAutocompleteWidget() {
$this->assertCount(1, $results);
$assert_session->pageTextContains('Test page');
$assert_session->pageTextNotContains('Page test');
+
+ // Change the size of the result set.
+ entity_get_form_display('node', 'page', 'default')
+ ->setComponent($field_name, [
+ 'type' => 'entity_reference_autocomplete',
+ 'settings' => [
+ 'match_limit' => 1,
+ ],
+ ])
+ ->save();
+
+ $this->drupalGet('node/add/page');
+ $page = $this->getSession()->getPage();
+
+ $autocomplete_field = $page->findField($field_name . '[0][target_id]');
+ $autocomplete_field->setValue('Test');
+ $this->getSession()->getDriver()->keyDown($autocomplete_field->getXpath(), ' ');
+ $assert_session->waitOnAutocomplete();
+
+ $results = $page->findAll('css', '.ui-autocomplete li');
+
+ $this->assertCount(1, $results);
+ $assert_session->pageTextContains('Test page');
+ $assert_session->pageTextNotContains('Page test');
}
}
diff --git a/core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayResourceTestBase.php b/core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayResourceTestBase.php
index a44534a31f..78df2a7520 100644
--- a/core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayResourceTestBase.php
+++ b/core/tests/Drupal/FunctionalTests/Rest/EntityFormDisplayResourceTestBase.php
@@ -109,6 +109,7 @@ protected function getExpectedNormalizedEntity() {
'weight' => 5,
'settings' => [
'match_operator' => 'CONTAINS',
+ 'match_limit' => 10,
'size' => 60,
'placeholder' => '',
],