From 4d4facb2db823e5bff488784f68fa945ac2c1f59 Mon Sep 17 00:00:00 2001
From: catch <catch@35733.no-reply.drupal.org>
Date: Tue, 12 Feb 2013 12:39:08 +0000
Subject: [PATCH] Issue #1914180 by amateescu: Unbreak and cleanup the
 autocomplete widgets.

---
 .../entity_reference/entity_reference.module  | 40 ++++++++-----------
 .../field/widget/AutocompleteTagsWidget.php   |  2 +-
 .../Tests/EntityReferenceAutocompleteTest.php | 16 +++++---
 3 files changed, 28 insertions(+), 30 deletions(-)

diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 4e98d15ff0dc..fd51ff62f09d 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -469,23 +469,28 @@ function entity_reference_autocomplete_access_callback($type, $field_name, $enti
 function entity_reference_autocomplete_callback($type, $field_name, $entity_type, $bundle_name, $entity_id = '') {
   $field = field_info_field($field_name);
   $instance = field_info_instance($entity_type, $field_name, $bundle_name);
+  $prefix = '';
 
   // Get the typed string, if exists from the URL.
   $tags_typed = drupal_container()->get('request')->query->get('q');
   $tags_typed = drupal_explode_tags($tags_typed);
   $string = drupal_strtolower(array_pop($tags_typed));
 
-  return entity_reference_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id, $string);
+  // The user entered a comma-separated list of entity labels, so we generate a
+  // prefix.
+  if ($type == 'tags' && !empty($string)) {
+    $prefix = count($tags_typed) ? drupal_implode_tags($tags_typed) . ', ' : '';
+  }
+
+  return entity_reference_autocomplete_callback_get_matches($field, $instance, $entity_type, $entity_id, $prefix, $string);
 }
 
 /**
  * Returns JSON data based on a given field, instance and search string.
  *
  * This function can be used by other modules that wish to pass a mocked
- * definition of the field on instance.
+ * definition of the field or instance.
  *
- * @param string $type
- *   The widget type (i.e. 'single' or 'tags').
  * @param array $field
  *   The field array definition.
  * @param array $instance
@@ -495,14 +500,16 @@ function entity_reference_autocomplete_callback($type, $field_name, $entity_type
  * @param string $entity_id
  *   (optional) The entity ID the entity reference field is attached to.
  *   Defaults to ''.
+ * @param string $prefix
+ *   (optional) A prefix for all the keys returned by this function.
  * @param string $string
- *   The label of the entity to query by.
+ *   (optional) The label of the entity to query by.
  *
  * @return \Symfony\Component\HttpFoundation\JsonResponse
  *
  * @see entity_reference_autocomplete_callback()
  */
-function entity_reference_autocomplete_callback_get_matches($type, $field, $instance, $entity_type, $entity_id = '', $string = '') {
+function entity_reference_autocomplete_callback_get_matches($field, $instance, $entity_type, $entity_id = '', $prefix = '', $string = '') {
   $target_type = $field['settings']['target_type'];
   $matches = array();
   $entity = NULL;
@@ -517,27 +524,12 @@ function entity_reference_autocomplete_callback_get_matches($type, $field, $inst
   }
   $handler = entity_reference_get_selection_handler($field, $instance, $entity);
 
-  if ($type == 'tags') {
-    // The user enters a comma-separated list of tags. We only autocomplete the
-    // last tag.
-    $tags_typed = drupal_explode_tags($string);
-    $tag_last = drupal_strtolower(array_pop($tags_typed));
-    if (!empty($tag_last)) {
-      $prefix = count($tags_typed) ? implode(', ', $tags_typed) . ', ' : '';
-    }
-  }
-  else {
-    // The user enters a single tag.
-    $prefix = '';
-    $tag_last = $string;
-  }
-
-  if (isset($tag_last)) {
+  if (isset($string)) {
     // Get an array of matching entities.
     $match_operator = !empty($instance['widget']['settings']['match_operator']) ? $instance['widget']['settings']['match_operator'] : 'CONTAINS';
-    $entity_labels = $handler->getReferencableEntities($tag_last, $match_operator, 10);
+    $entity_labels = $handler->getReferencableEntities($string, $match_operator, 10);
 
-    // Loop through the products and convert them into autocomplete output.
+    // Loop through the entities and convert them into autocomplete output.
     foreach ($entity_labels as $values) {
       foreach ($values as $entity_id => $label) {
         $key = "$label ($entity_id)";
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
index 2887af6909d8..cb7b40b16a7a 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
@@ -28,7 +28,7 @@
  *     "autocomplete_path" = "entity_reference/autocomplete/tags",
  *     "placeholder" = ""
  *   },
- *   multiple_values = FIELD_BEHAVIOR_CUSTOM
+ *   multiple_values = TRUE
  * )
  */
 class AutocompleteTagsWidget extends AutocompleteWidgetBase {
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php
index 3d94c04486fb..70961b0fa353 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceAutocompleteTest.php
@@ -83,26 +83,32 @@ function testTermAutocompletion() {
     taxonomy_term_save($third_term);
 
     // Set the path prefix to point to entity reference's autocomplete path.
-    $path_prefix = 'entity_reference/autocomplete/single/' . $this->field_name . '/node/article/NULL';
+    $path_prefix_single = 'entity_reference/autocomplete/single/' . $this->field_name . '/node/article/NULL';
+    $path_prefix_tags = 'entity_reference/autocomplete/tags/' . $this->field_name . '/node/article/NULL';
 
     // Try to autocomplete a term name that matches both terms.
     // We should get both terms in a JSON encoded string.
     $input = '10/';
-    $result = $this->drupalGet($path_prefix, array('query' => array('q' => $input)));
-    $data = drupal_json_decode($result);
+    $data = $this->drupalGetAJAX($path_prefix_single, array('query' => array('q' => $input)));
     $this->assertEqual(strip_tags($data[$first_term->name. ' (1)']), check_plain($first_term->name), 'Autocomplete returned the first matching term');
     $this->assertEqual(strip_tags($data[$second_term->name. ' (2)']), check_plain($second_term->name), 'Autocomplete returned the second matching term');
 
     // Try to autocomplete a term name that matches the first term.
     // We should only get the first term in a JSON encoded string.
     $input = '10/16';
-    $this->drupalGet($path_prefix, array('query' => array('q' => $input)));
+    $this->drupalGet($path_prefix_single, array('query' => array('q' => $input)));
     $target = array($first_term->name . ' (1)' => '<div class="reference-autocomplete">' . check_plain($first_term->name) . '</div>');
     $this->assertRaw(drupal_json_encode($target), 'Autocomplete returns only the expected matching term.');
 
+    // Try to autocomplete a term name that matches the second term, and the
+    // first term is already typed in the autocomplete (tags) widget.
+    $input = $first_term->name . ' (1), 10/17';
+    $data = $this->drupalGetAJAX($path_prefix_tags, array('query' => array('q' => $input)));
+    $this->assertEqual(strip_tags($data[$first_term->name . ' (1), ' . $second_term->name . ' (2)']), check_plain($second_term->name), 'Autocomplete returned the second matching term');
+
     // Try to autocomplete a term name with both a comma and a slash.
     $input = '"term with, comma and / a';
-    $this->drupalGet($path_prefix, array('query' => array('q' => $input)));
+    $this->drupalGet($path_prefix_single, array('query' => array('q' => $input)));
     $n = $third_term->name;
     // Term names containing commas or quotes must be wrapped in quotes.
     if (strpos($third_term->name, ',') !== FALSE || strpos($third_term->name, '"') !== FALSE) {
-- 
GitLab