From b2bf8069669234c0380e3244f812ce70b5e9e9cc Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Thu, 20 Sep 2018 11:36:22 +0200 Subject: [PATCH 1/6] Issue #3000623: Implement pagination for autocomplete requests --- js/select2.js | 9 +++++++++ src/Controller/EntityAutocompleteController.php | 3 ++- src/EntityAutocompleteMatcher.php | 6 ++++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/js/select2.js b/js/select2.js index 72471f57..5925e66c 100644 --- a/js/select2.js +++ b/js/select2.js @@ -19,6 +19,15 @@ text: term }; }; + if (config.hasOwnProperty('ajax')) { + // Use pagination for ajax requests. + config.ajax.data = function (params) { + return { + q: params.term, + page: params.page || 1 + }; + } + } $(this).css('width', '100%').select2(config); // Copied from https://github.com/woocommerce/woocommerce/blob/master/assets/js/admin/wc-enhanced-select.js#L118 diff --git a/src/Controller/EntityAutocompleteController.php b/src/Controller/EntityAutocompleteController.php index 66ec9663..9921d37e 100644 --- a/src/Controller/EntityAutocompleteController.php +++ b/src/Controller/EntityAutocompleteController.php @@ -99,7 +99,8 @@ public function handleAutocomplete(Request $request, $target_type, $selection_ha throw new AccessDeniedHttpException(); } - $matches['results'] = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string); + $matches['results'] = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string, $request->query->get('page') - 1); + $matches['pagination']['more'] = count($matches['results']) == 10; } return new JsonResponse($matches); diff --git a/src/EntityAutocompleteMatcher.php b/src/EntityAutocompleteMatcher.php index 36cb9e19..f6de3734 100644 --- a/src/EntityAutocompleteMatcher.php +++ b/src/EntityAutocompleteMatcher.php @@ -38,6 +38,8 @@ public function __construct(SelectionPluginManagerInterface $selection_manager) * An array of settings that will be passed to the selection handler. * @param string $string * (optional) The label of the entity to query by. + * @param int $page + * (optional) An offset for the results. * * @return array * An array of matched entity labels, in the format required by the AJAX @@ -48,7 +50,7 @@ public function __construct(SelectionPluginManagerInterface $selection_manager) * * @see \Drupal\system\Controller\EntityAutocompleteController */ - public function getMatches($target_type, $selection_handler, array $selection_settings, $string = '') { + public function getMatches($target_type, $selection_handler, array $selection_settings, $string = '', $page = 0) { $matches = []; $options = $selection_settings + [ @@ -60,7 +62,7 @@ public function getMatches($target_type, $selection_handler, array $selection_se 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); + $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10, $page * 10); // Loop through the entities and convert them into autocomplete output. foreach ($entity_labels as $values) { From 499934f144c14fbedb9b71c7353570cc5b26b24d Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Thu, 20 Sep 2018 15:32:18 +0200 Subject: [PATCH 2/6] Fix cs issue --- js/select2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/select2.js b/js/select2.js index 5925e66c..61c8ac4b 100644 --- a/js/select2.js +++ b/js/select2.js @@ -26,7 +26,7 @@ q: params.term, page: params.page || 1 }; - } + }; } $(this).css('width', '100%').select2(config); From dede46de77bb4a50b64e5c87fb9b5ede1a915d10 Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Sun, 23 Sep 2018 15:11:20 +0200 Subject: [PATCH 3/6] Set matchsize in widget --- src/Controller/EntityAutocompleteController.php | 2 +- src/EntityAutocompleteMatcher.php | 3 ++- .../Field/FieldWidget/Select2EntityReferenceWidget.php | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Controller/EntityAutocompleteController.php b/src/Controller/EntityAutocompleteController.php index 9921d37e..ce0d9b9d 100644 --- a/src/Controller/EntityAutocompleteController.php +++ b/src/Controller/EntityAutocompleteController.php @@ -100,7 +100,7 @@ public function handleAutocomplete(Request $request, $target_type, $selection_ha } $matches['results'] = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, $typed_string, $request->query->get('page') - 1); - $matches['pagination']['more'] = count($matches['results']) == 10; + $matches['pagination']['more'] = count($matches['results']) == $selection_settings['match_size']; } return new JsonResponse($matches); diff --git a/src/EntityAutocompleteMatcher.php b/src/EntityAutocompleteMatcher.php index f6de3734..08ecdc00 100644 --- a/src/EntityAutocompleteMatcher.php +++ b/src/EntityAutocompleteMatcher.php @@ -62,7 +62,8 @@ public function getMatches($target_type, $selection_handler, array $selection_se 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, $page * 10); + $match_size = !empty($selection_settings['match_size']) ? $selection_settings['match_size'] : 10; + $entity_labels = $handler->getReferenceableEntities($string, $match_operator, $match_size, $page * $match_size); // Loop through the entities and convert them into autocomplete output. foreach ($entity_labels as $values) { diff --git a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php index 680ebcac..bb1009a0 100644 --- a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php +++ b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php @@ -79,7 +79,10 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element['#target_type'] = $this->getFieldSetting('target_type'); $element['#selection_handler'] = $this->getFieldSetting('handler'); - $element['#selection_settings'] = $this->getFieldSetting('handler_settings') + ['match_operator' => $this->getSetting('match_operator')]; + $element['#selection_settings'] = $this->getFieldSetting('handler_settings') + [ + 'match_operator' => $this->getSetting('match_operator'), + 'match_size' => 10, + ]; $element['#autocomplete'] = $this->getSetting('autocomplete'); if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) { From 05a9ee84ebf9cc786148fd70fe90af63c2b95184 Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Thu, 25 Jul 2019 13:55:39 +0200 Subject: [PATCH 4/6] Fix eslint --- js/select2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/select2.js b/js/select2.js index c1f43e7c..b5ddca1e 100644 --- a/js/select2.js +++ b/js/select2.js @@ -19,7 +19,7 @@ text: term }; }; - if (config.hasOwnProperty('ajax')) { + if (Object.prototype.hasOwnProperty.call(config, 'ajax')) { // Use pagination for ajax requests. config.ajax.data = function (params) { return { From d815240c5dd00c2a4bc6ffcd7d9a0c24a8ac7eff Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Thu, 25 Jul 2019 14:54:12 +0200 Subject: [PATCH 5/6] Remove empty lines --- src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php index 6adf274c..4324c1cb 100644 --- a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php +++ b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php @@ -140,7 +140,6 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $element['#target_type'] = $this->getFieldSetting('target_type'); $element['#selection_handler'] = $this->getFieldSetting('handler'); $element['#selection_settings'] = $this->getSelectionSettings(); - $element['#autocomplete'] = $this->getSetting('autocomplete'); if ($this->getSelectionHandlerSetting('auto_create') && ($bundle = $this->getAutocreateBundle())) { From 9d392606e26cc341e65d6865179d9001578819f8 Mon Sep 17 00:00:00 2001 From: Christian Fritsch Date: Tue, 8 Oct 2019 12:52:24 +0200 Subject: [PATCH 6/6] Add parameter check --- src/Controller/EntityAutocompleteController.php | 13 ++++++++++++- src/EntityAutocompleteMatcher.php | 3 +-- .../FieldWidget/Select2EntityReferenceWidget.php | 1 - 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Controller/EntityAutocompleteController.php b/src/Controller/EntityAutocompleteController.php index 8fc503f7..7a0d168f 100644 --- a/src/Controller/EntityAutocompleteController.php +++ b/src/Controller/EntityAutocompleteController.php @@ -84,7 +84,18 @@ public function handleAutocomplete(Request $request, $target_type, $selection_ha } $matches['results'] = $this->matcher->getMatches($target_type, $selection_handler, $selection_settings, mb_strtolower($input), $request->query->get('page') - 1); - $matches['pagination']['more'] = count($matches['results']) == $selection_settings['match_limit']; + + // Remove reflection in Drupal 9.0.0. + $options = $selection_settings + [ + 'target_type' => $target_type, + 'handler' => $selection_handler, + ]; + $handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options); + $method = new \ReflectionMethod($handler, 'getReferenceableEntities'); + $parameters = $method->getParameters(); + if (count($parameters) > 3 && $parameters[3]->getName() === 'offset') { + $matches['pagination']['more'] = count($matches['results']) == 10; + } } return new JsonResponse($matches); diff --git a/src/EntityAutocompleteMatcher.php b/src/EntityAutocompleteMatcher.php index 5e27e0d3..675e3a97 100644 --- a/src/EntityAutocompleteMatcher.php +++ b/src/EntityAutocompleteMatcher.php @@ -73,8 +73,7 @@ public function getMatches($target_type, $selection_handler, array $selection_se if (isset($string)) { // Get an array of matching entities. $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS'; - $match_limit = !empty($selection_settings['match_limit']) ? $selection_settings['match_limit'] : 10; - $entity_labels = $handler->getReferenceableEntities($string, $match_operator, $match_limit, $page * $match_limit); + $entity_labels = $handler->getReferenceableEntities($string, $match_operator, 10, $page * 10); // Loop through the entities and convert them into autocomplete output. foreach ($entity_labels as $values) { diff --git a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php index 4324c1cb..22fe07c6 100644 --- a/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php +++ b/src/Plugin/Field/FieldWidget/Select2EntityReferenceWidget.php @@ -182,7 +182,6 @@ protected function getSelectionSettings() { $label_field = $this->entityTypeManager->getDefinition($this->getFieldSetting('target_type'))->getKey('label') ?: '_none'; return [ 'match_operator' => $this->getSetting('match_operator'), - 'match_limit' => 10, 'sort' => ['field' => $label_field], ] + $this->getFieldSetting('handler_settings'); }