From df698b3153453bca25e13293341eb9b0c3010710 Mon Sep 17 00:00:00 2001
From: Axel Rutz <axel.rutz@clever-systems.net>
Date: Sun, 8 Apr 2012 18:09:10 +0200
Subject: [PATCH] fixed #1389238: entityref autocomplete

---
 entityreference.module                             |   16 +++++++++-
 ...ityReference_SelectionHandler_Generic.class.php |   31 ++++++++++++++++++++
 plugins/selection/abstract.inc                     |   18 +++++++++++
 3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/entityreference.module b/entityreference.module
index 18b329e..af14510 100644
--- a/entityreference.module
+++ b/entityreference.module
@@ -714,9 +714,14 @@ function _entityreference_autocomplete_validate($element, &$form_state, $form) {
     // Take "label (entity id)', match the id from parenthesis.
     if (preg_match("/.+\((\d+)\)/", $element['#value'], $matches)) {
       $value = $matches[1];
+    } else {
+      // Try to get a match from the input string when the user didn't use the
+      // autocomplete but filled in a value manually.
+      $field = field_info_field($element['#field_name']);
+      $handler = entityreference_get_selection_handler($field);
+      $value = $handler->validateAutocompleteInput($element['#value'], $element, $form_state, $form);
     }
   }
-
   // Update the value of this element so the field can validate the product IDs.
   form_set_value($element, $value, $form_state);
 }
@@ -733,10 +738,17 @@ function _entityreference_autocomplete_tags_validate($element, &$form_state, $fo
         $value[] = array(
           'target_id' => $matches[1],
         );
+      } else {
+        // Try to get a match from the input string when the user didn't use the
+        // autocomplete but filled in a value manually.
+        $field = field_info_field($element['#field_name']);
+        $handler = entityreference_get_selection_handler($field);
+        $value[] = array(
+          'target_id' => $handler->validateAutocompleteInput($entity, $element, $form_state, $form),
+        );
       }
     }
   }
-
   // Update the value of this element so the field can validate the product IDs.
   form_set_value($element, $value, $form_state);
 }
diff --git a/plugins/selection/EntityReference_SelectionHandler_Generic.class.php b/plugins/selection/EntityReference_SelectionHandler_Generic.class.php
index 0d24580..f52e143 100644
--- a/plugins/selection/EntityReference_SelectionHandler_Generic.class.php
+++ b/plugins/selection/EntityReference_SelectionHandler_Generic.class.php
@@ -177,6 +177,37 @@ class EntityReference_SelectionHandler_Generic implements EntityReference_Select
   }
 
   /**
+   * Implements EntityReferenceHandler::validateAutocompleteInput().
+   */
+  public function validateAutocompleteInput($input, &$element, &$form_state, $form) {
+      $entities = $this->getReferencableEntities($input, '=', 6);
+      if (empty($entities)) {
+        // Error if there are no entities available for a required field.
+        form_error($element, t('There are no entities matching "%value"', array('%value' => $input)));
+      }
+      elseif (count($entities) > 5) {
+        // Error if there are more than 5 matching entities.
+        form_error($element, t('Many entities are called %value. Specify the one you want by appending the id in parentheses, like "@value (@id)"', array(
+          '%value' => $input,
+          '@value' => $input,
+          '@id' => key($entities),
+        )));
+      }
+      elseif (count($entities) > 1) {
+        // More helpful error if there are only a few matching entities.
+        $multiples = array();
+        foreach ($entities as $id => $name) {
+          $multiples[] = $name . ' (' . $id . ')';
+        }
+        form_error($element, t('Multiple entities match this reference; "%multiple"', array('%multiple' => implode('", "', $multiples))));
+      }
+      else {
+        // Take the one and only matching entity.
+        return key($entities);
+      }
+  }
+
+  /**
    * Build an EntityFieldQuery to get referencable entities.
    */
   protected function buildEntityFieldQuery($match = NULL, $match_operator = 'CONTAINS') {
diff --git a/plugins/selection/abstract.inc b/plugins/selection/abstract.inc
index 75743e4..c3e2c61 100644
--- a/plugins/selection/abstract.inc
+++ b/plugins/selection/abstract.inc
@@ -35,6 +35,20 @@ interface EntityReference_SelectionHandler {
   public function validateReferencableEntities(array $ids);
 
   /**
+   * Validate Input from autocomplete widget that has no Id.
+   *
+   * @see _entityreference_autocomplete_validate()
+   *
+   * @param $input
+   * 	 Single string from autocomplete widget.
+   * @param $element
+   *   The form element to set a form error.
+   * @return
+   *   Value of a matching entity id, or NULL if none.
+   */
+  public function validateAutocompleteInput($input, &$element, &$form_state, $form);
+
+  /**
    * Give the handler a chance to alter the SelectQuery generated by EntityFieldQuery.
    */
   public function entityFieldQueryAlter(SelectQueryInterface $query);
@@ -82,6 +96,10 @@ class EntityReference_SelectionHandler_Broken implements EntityReference_Selecti
     return array();
   }
 
+  public function validateAutocompleteInput($input, &$element, &$form_state, $form) {
+    return NULL;
+  }
+
   public function entityFieldQueryAlter(SelectQueryInterface $query) {}
 
   public function getLabel($entity) {
-- 
1.7.5.4

