From da37e2d9037286d2f97e8b7c9f4281e3df466823 Mon Sep 17 00:00:00 2001
From: solotandem <jim@boombatower.com>
Date: Tue, 17 Nov 2015 16:27:10 -0600
Subject: [PATCH] Issue #2617608 by solotandem: Add entity label as search
 field for an entityreference field.

  The label is useful for sorting compared to the entity_type:target_id string
    of the existing search field.
---
 apachesolr.index.inc | 29 +++++++++++++++++++++--------
 apachesolr.module    | 38 +++++++++++++++++++++++++++++++++++---
 2 files changed, 56 insertions(+), 11 deletions(-)

diff --git a/apachesolr.index.inc b/apachesolr.index.inc
index 94588ef..4e95d22 100644
--- a/apachesolr.index.inc
+++ b/apachesolr.index.inc
@@ -1371,27 +1371,40 @@ function apachesolr_userreference_indexing_callback($entity, $field_name, $index
  * @param string $field_name
  * @param string $index_key
  * @param array $field_info
- * @return array $fields
  *
+ * @return array
+ *  The list of fields.
  */
 function apachesolr_entityreference_indexing_callback($entity, $field_name, $index_key, $field_info) {
   $fields = array();
   if (!empty($entity->{$field_name}) && array_key_exists(LANGUAGE_NONE, $entity->$field_name)) {
-
-    // Gets entity type and index key. We need to prefix the ID with the entity
-    // type so we know what entity we are dealing with in the mapping callback.
+    // Get entity type and index key.
     $entity_type = $field_info['field']['settings']['target_type'];
     $index_key = apachesolr_index_key($field_info);
 
-    // Iterates over all references and adds them to the fields.
+    $ids = array();
     foreach ($entity->{$field_name}[LANGUAGE_NONE] as $reference) {
-      if ($id = (!empty($reference['target_id'])) ? $reference['target_id'] : FALSE) {
+      if (!empty($reference['target_id'])) {
+        // Gather target entity ids.
+        $ids[] = $reference['target_id'];
+
+        // Add field for the target_id.
+        // Include the entity type for use in the facet mapping callback.
         $fields[] = array(
-          'key' => $index_key,
-          'value' => $entity_type . ':' . $id,
+          'key' => $index_key . '_target_id',
+          'value' => $entity_type . ':' . $reference['target_id'],
         );
       }
     }
+    // Load entities and add fields.
+    $entities = entity_load($entity_type, $ids);
+    foreach ($entities as $id => $entity) {
+      // Add field for the label of the target entity.
+      $fields[] = array(
+        'key' => $index_key,
+        'value' => entity_label($entity_type, $entity),
+      );
+    }
   }
   return $fields;
 }
diff --git a/apachesolr.module b/apachesolr.module
index 0865412..07dd41c 100644
--- a/apachesolr.module
+++ b/apachesolr.module
@@ -2445,11 +2445,19 @@ function apachesolr_userreference_map_callback($facets, $options) {
  */
 function apachesolr_entityreference_facet_map_callback(array $values, array $options) {
   $map = array();
-  // Gathers entity ids so we can load multiple entities at a time.
   $entity_ids = array();
   foreach ($values as $value) {
-    list($entity_type, $id) = explode(':', $value);
-    $entity_ids[$entity_type][] = $id;
+    if (strpos($value, ':') !== FALSE) {
+      // This is a target_id field.
+      list($entity_type, $id) = explode(':', $value);
+      // Gather target entity ids.
+      $entity_ids[$entity_type][] = $id;
+    }
+    else {
+      // This is a target label field.
+      $map[$value]['#markup'] = field_filter_xss($value);
+      $map[$value]['#html'] = TRUE;
+    }
   }
   // Loads and maps entities.
   foreach ($entity_ids as $entity_type => $ids) {
@@ -2781,6 +2789,15 @@ function user_reference_apachesolr_field_mappings() {
  * @see http://drupal.org/node/1572722
  */
 function entityreference_apachesolr_field_mappings() {
+  // The entity label is the current facet value and is arguably much more
+  // useful for filtering and sorting than the target_id. Switch the default
+  // entityreference mapping to agree with the facet.
+
+  // While the apachesolr API allows multiple callback routines for the indexing
+  // portion, the facet API does not for its portion. As the indexing code will
+  // do similar processing for each field mapping (label and target_id), use one
+  // callback. This is consistent with the taxonomy term fields.
+
   $mappings = array(
     'entityreference' => array(
       'indexing_callback' => array('apachesolr_entityreference_indexing_callback'),
@@ -2790,6 +2807,21 @@ function entityreference_apachesolr_field_mappings() {
       'query types' => array('term'),
       'facet missing allowed' => TRUE,
     ),
+    // @todo Although the api.php file would suggest being able to define
+    // another field mapping, this does not appear to work as
+    // apachesolr_entity_fields() only considers $field['type'] as a key in the
+    // $mappings array.
+    // If the target_id is desirable to retain, then it needs to be handled in
+    // the various callback routines.
+    // The following entry is not used, but added for illustration.
+    'entityreference_target_id' => array(
+      'indexing_callback' => array('apachesolr_entityreference_target_id_indexing_callback'),
+      'map callback' => 'apachesolr_entityreference_target_id_facet_map_callback',
+      'index_type' => 'integer',
+      'facets' => TRUE,
+      'query types' => array('term'),
+      'facet missing allowed' => TRUE,
+    ),
   );
 
   return $mappings;
-- 
2.1.4

