Index: modules/ds_search/ds_search.module
===================================================================
--- modules/ds_search/ds_search.module	(revision 15)
+++ modules/ds_search/ds_search.module	(working copy)
@@ -191,7 +191,9 @@
   $ds_search_type = variable_get('ds_search_type', 'node') . '_ds_search_execute';
 
   // We're not going to babysit here, so call directly.
-  return $ds_search_type($keys, $conditions);
+  if (function_exists($ds_search_type)) {
+    return $ds_search_type($keys, $conditions);
+  }
 }
 
 /**
@@ -236,6 +238,33 @@
 }
 
 /**
+ * DS entity view callback. Straight copy from Entity API module.
+ */
+function ds_fake_entity_view($entity_type, $entities, $view_mode = 'full', $langcode = NULL, $page = NULL) {
+  $info = entity_get_info($entity_type);
+  if (isset($info['view callback'])) {
+    $entities = ds_entity_key_array_by_property($entities, $info['entity keys']['id']);
+    return $info['view callback']($entities, $view_mode, $langcode, $entity_type);
+  }
+  elseif (in_array('EntityAPIControllerInterface', class_implements($info['controller class']))) {
+    return entity_get_controller($entity_type)->view($entities, $view_mode, $langcode, $page);
+  }
+  return FALSE;
+}
+
+/**
+ * DS entity key array by property.
+ */
+function ds_entity_key_array_by_property(array $entities, $property) {
+  $ret = array();
+  foreach ($entities as $entity) {
+    $key = isset($entity->$property) ? $entity->$property : NULL;
+    $ret[$key] = $entity;
+  }
+  return $ret;
+}
+
+/**
  * Implements hook_search_page().
  */
 function ds_search_search_page($results) {
@@ -249,8 +278,10 @@
     $build['search_results'] = $results;
   }
   else {
-    $render_nodes = node_view_multiple($results, variable_get('ds_search_view_mode', 'search_result'));
-    $build['search_results'] = $render_nodes['nodes'];
+    foreach ($results as $result) {
+      // We rely on the on the view callback.
+      $build['search_results'][] = reset(ds_fake_entity_view($result->entity_type, array($result), variable_get('ds_search_view_mode', 'search_result')));
+    }
     unset($build['search_results']['#sorted']);
   }
 
@@ -523,9 +554,9 @@
 }
 
 /**
- * Implements hook_apachesolr_update_index().
+ * Implements hook_apachesolr_index_document_build().
  */
-function ds_search_apachesolr_update_index(&$document, $node) {
+function ds_search_apachesolr_index_document_build(ApacheSolrDocument $document, $entity) {
   // Apache Solr multisite support. Render the node already here.
   if (variable_get('ds_search_apachesolr_multisite')) {
     ob_start();
@@ -536,7 +567,16 @@
   }
   // Creme de la creme: Put the full node object in the index,
   // so no node_loads are needed for results in the Apache Solr engine.
-  $document->addField('tm_node', urlencode(serialize(node_load($node->nid))));
+  //
+  // We are using xs_node because this field is not indexed by apachesolr and it
+  // is a single.
+  // @todo It takes 33% more space in the database of solr and is more
+  // processor demanding, maybe add a new field to schema.xml?
+  $entity_type = $document->getField('entity_type');
+  $entity_id = $document->getField('entity_id');
+  $entity_type = $entity_type['value'];
+  $entity_id = $entity_id['value'];
+  $document->addField('xs_entity', base64_encode(serialize(entity_load($entity_type, array($entity_id)))));
 }
 
 /**
@@ -545,7 +585,7 @@
 function ds_search_apachesolr_query_alter($query) {
 
   // Get the node from the index.
-  $query->addParam('fl', 'tm_node');
+  $query->addParam('fl', 'xs_entity');
 
   // Apache Solr multisite support.
   if (variable_get('ds_search_apachesolr_multisite') && variable_get('ds_search_type', 'node') == 'apachesolr_search') {
@@ -607,6 +647,7 @@
   $results = array();
   foreach ($find as $item) {
     $node = node_load($item->sid);
+    $node->entity_type = 'node';
     $node->search_extra = module_invoke_all('node_search_result', $node);
     $results[$item->sid] = $node;
   }
@@ -614,51 +655,60 @@
 }
 
 /**
- * Search on behalf of Apache Solr.
+ * Process results on behalf of Apache Solr.
  */
-function apachesolr_search_ds_search_execute($keys = NULL, $conditions = NULL) {
-  $find = apachesolr_search_search_execute($keys, $conditions);
-  $results = array();
+function ds_search_process_results($results) {
 
-  // Make sure apachesolr_search_browse is not rendered.
-  if (isset($find['apachesolr_search_browse'])) {
-    unset($find['apachesolr_search_browse']);
-  }
+  if (is_array($results) && !empty($results)) {
+    $processed_results = array();
+    foreach ($results as $result) {
 
-  if (empty($find)) {
-    return array();
-  }
+      // Unserialize xs_node field.
+      $entity = @unserialize(@base64_decode($result['fields']['xs_entity']));
+      if (empty($entity)) {
+        $entity = entity_load($result['fields']['entity_type'], array($result['fields']['entity_id']));
+      }
+      else {
+        $entity = reset($entity);
+      }
 
-  foreach ($find as $item) {
+      // Add the snippet, url and extra info on the object.
+      $entity->search_snippet = $result['snippet'];
+      $entity->search_extra = $result['extra'];
+      $entity->search_as_url = $result['fields']['url'];
+      $entity->entity_type = $result['fields']['entity_type'];
 
-    // Unserialize tm_node field.
-    $node = @unserialize(urldecode($item['fields']['tm_node'][0]));
-    if (!isset($node->nid)) {
-      $node = node_load($item['node']->entity_id);
-    }
+      // Apache Solr multisite support.
+      if (variable_get('ds_search_apachesolr_multisite')) {
 
-    // Add the snippet, url and extra info on the object.
-    $node->search_snippet = $item['snippet'];
-    $node->search_extra = $item['extra'];
-    $node->search_as_url = $item['fields']['url'];
+        // Pass along the uri path in case some people want to
+        // do cool stuff themselves.
+        $entity->uri['path'] = $entity->search_as_url;
+        $entity->uri['options'] = array();
 
-    // Apache Solr multisite support.
-    if (variable_get('ds_search_apachesolr_multisite')) {
-      // Pass along the uri path in case some people want to
-      // do cool stuff themselves.
-      $node->uri['path'] = $node->search_as_url;
-      $node->uri['options'] = array();
-      // Prefix with site hash so we don't override same id's.
-      $markup = $item['fields']['tm_ds_search_result'][0];
-      $results[$item['fields']['id'] . '-' . $item['node']->entity_id] = array(
-       '#markup' => $markup,
-        '#site_hash' => $item['fields']['hash'],
-      );
+        // Prefix with site hash so we don't override same id's.
+        $markup = $result['fields']['tm_ds_search_result'][0];
+        $processed_results[$result['fields']['id'] . '-' . $result['fields']['entity_id']] = array(
+         '#markup' => $markup,
+          '#site_hash' => $result['fields']['hash'],
+        );
+      }
+      else {
+        $processed_results[$result['fields']['id'] . '-' . $result['fields']['entity_id']] = $entity;
+      }
     }
-    else {
-      $results[$item['node']->entity_id] = $node;
-    }
   }
 
-  return $results;
+  return $processed_results;
 }
+
+/**
+ * Implements hook_apachesolr_search_page_alter(&$build, $search_page).
+ */
+function ds_search_apachesolr_search_page_alter(&$build, $search_page) {
+  if (!empty($build['search_results']['#results'])) {
+    $results = $build['search_results']['#results'];
+    $results = ds_search_process_results($results);
+    $build['search_results'] = ds_search_search_page($results);
+  }
+}
