Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.357
diff -u -r1.357 search.module
--- modules/search/search.module	13 Aug 2010 01:05:36 -0000	1.357
+++ modules/search/search.module	17 Aug 2010 16:44:11 -0000
@@ -114,12 +114,12 @@
       'template' => 'search-block-form',
     ),
     'search_result' => array(
-      'variables' => array('result' => NULL, 'type' => NULL),
+      'variables' => array('result' => NULL, 'module' => NULL),
       'file' => 'search.pages.inc',
       'template' => 'search-result',
     ),
     'search_results' => array(
-      'variables' => array('results' => NULL, 'type' => NULL),
+      'variables' => array('results' => NULL, 'module' => NULL),
       'file' => 'search.pages.inc',
       'template' => 'search-results',
     ),
@@ -1074,8 +1074,8 @@
  *   Optional array of additional search conditions.
  *
  * @return
- *   Formatted search results. No return value if $keys are not supplied or
- *   if the given search module is not active.
+ *   Renderable array of search results. No return value if $keys are not
+ *   supplied or if the given search module is not active.
  */
 function search_data($keys, $module, $conditions = NULL) {
   if (module_hook($module, 'search_execute')) {
@@ -1084,7 +1084,11 @@
       return module_invoke($module, 'search_page', $results);
     }
     else {
-      return theme('search_results', array('results' => $results, 'type' => $module));
+      return array(
+        '#theme' => 'search_results',
+        '#results' => $results,
+        '#module' => $module,
+      );
     }
   }
 }
Index: modules/search/search.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.pages.inc,v
retrieving revision 1.22
diff -u -r1.22 search.pages.inc
--- modules/search/search.pages.inc	11 Aug 2010 14:21:39 -0000	1.22
+++ modules/search/search.pages.inc	17 Aug 2010 16:44:11 -0000
@@ -44,7 +44,8 @@
     drupal_goto($path);
   }
 
-  $results = '';
+  // Default results output is an empty string.
+  $results = array('#markup' => '');
   // Process the search form. Note that if there is $_POST data,
   // search_form_submit() will cause a redirect to search/[module path]/[keys],
   // which will get us back to this page callback. In other words, the search
@@ -67,7 +68,7 @@
   }
   // The form may be altered based on whether the search was run.
   $build['search_form'] = drupal_get_form('search_form', NULL, $keys, $info['module']);
-  $build['search_results'] = array('#markup' => $results);
+  $build['search_results'] = $results;
 
   return $build;
 }
@@ -83,11 +84,14 @@
  */
 function template_preprocess_search_results(&$variables) {
   $variables['search_results'] = '';
+  if (!empty($variables['module'])) {
+    $variables['module'] = check_plain($variables['module']);
+  }
   foreach ($variables['results'] as $result) {
-    $variables['search_results'] .= theme('search_result', array('result' => $result, 'type' => $variables['type']));
+    $variables['search_results'] .= theme('search_result', array('result' => $result, 'module' => $variables['module']));
   }
   $variables['pager'] = theme('pager', array('tags' => NULL));
-  $variables['theme_hook_suggestions'][] = 'search_results__' . $variables['type'];
+  $variables['theme_hook_suggestions'][] = 'search_results__' . $variables['module'];
 }
 
 /**
@@ -105,8 +109,8 @@
   $variables['title'] = check_plain($result['title']);
 
   $info = array();
-  if (!empty($result['type'])) {
-    $info['type'] = check_plain($result['type']);
+  if (!empty($result['module'])) {
+    $info['module'] = check_plain($result['module']);
   }
   if (!empty($result['user'])) {
     $info['user'] = $result['user'];
@@ -122,7 +126,7 @@
   // Provide separated and grouped meta information..
   $variables['info_split'] = $info;
   $variables['info'] = implode(' - ', $info);
-  $variables['theme_hook_suggestions'][] = 'search_result__' . $variables['type'];
+  $variables['theme_hook_suggestions'][] = 'search_result__' . $variables['module'];
 }
 
 /**
Index: modules/search/search-result.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search-result.tpl.php,v
retrieving revision 1.6
diff -u -r1.6 search-result.tpl.php
--- modules/search/search-result.tpl.php	29 May 2010 07:50:33 -0000	1.6
+++ modules/search/search-result.tpl.php	17 Aug 2010 16:44:11 -0000
@@ -16,7 +16,7 @@
  * - $info: String of all the meta information ready for print. Does not apply
  *   to user searches.
  * - $info_split: Contains same data as $info, split into a keyed array.
- * - $type: The type of search, e.g., "node" or "user".
+ * - $module: The module searching, e.g., "node" or "user".
  *
  * Default keys within $info_split:
  * - $info_split['type']: Node type.
Index: modules/search/search-results.tpl.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search-results.tpl.php,v
retrieving revision 1.6
diff -u -r1.6 search-results.tpl.php
--- modules/search/search-results.tpl.php	28 May 2010 11:53:57 -0000	1.6
+++ modules/search/search-results.tpl.php	17 Aug 2010 16:44:11 -0000
@@ -15,7 +15,7 @@
  * Available variables:
  * - $search_results: All results as it is rendered through
  *   search-result.tpl.php
- * - $type: The type of search, e.g., "node" or "user".
+ * - $module: The module searching, e.g., "node" or "user".
  *
  *
  * @see template_preprocess_search_results()
@@ -23,7 +23,7 @@
 ?>
 <?php if ($search_results) : ?>
   <h2><?php print t('Search results');?></h2>
-  <ol class="search-results <?php print $type; ?>-results">
+  <ol class="search-results <?php print $module; ?>-results">
     <?php print $search_results; ?>
   </ol>
   <?php print $pager; ?>
Index: modules/search/search.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.test,v
retrieving revision 1.71
diff -u -r1.71 search.test
--- modules/search/search.test	13 Aug 2010 01:05:36 -0000	1.71
+++ modules/search/search.test	17 Aug 2010 16:44:11 -0000
@@ -1050,7 +1050,7 @@
 
 
 /**
- * Test config page.
+ * Tests keywords and conditions.
  */
 class SearchKeywordsConditions extends DrupalWebTestCase {
 
@@ -1523,3 +1523,37 @@
     $this->submit_count = $count;
   }
 }
+
+/**
+ * Tests that hook_search_page runs.
+ */
+class SearchPageOverride extends DrupalWebTestCase {
+  public $search_user;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Search page override',
+      'description' => 'Verify that hook_search_page can override search page display.',
+      'group' => 'Search',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('search', 'search_extra_type');
+
+    // Login as a user that can create and search content.
+    $this->search_user = $this->drupalCreateUser(array('search content', 'administer search'));
+    $this->drupalLogin($this->search_user);
+
+    // Enable the extra type module for searching.
+    variable_set('search_active_modules', array('node' => 'node', 'user' => 'user', 'search_extra_type' => 'search_extra_type'));
+    menu_rebuild();
+  }
+
+  function testSearchPageHook() {
+    $keys = 'bike shed ' . $this->randomName();
+    $this->drupalGet("search/dummy_path/{$keys}");
+    $this->assertText('Dummy search snippet', 'Dummy search snippet is shown');
+    $this->assertText('Test page text is here', 'Page override is working');
+  }
+}
Index: modules/search/search.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.api.php,v
retrieving revision 1.28
diff -u -r1.28 search.api.php
--- modules/search/search.api.php	11 Aug 2010 14:21:39 -0000	1.28
+++ modules/search/search.api.php	17 Aug 2010 16:44:11 -0000
@@ -25,9 +25,11 @@
  * hook_update_index(). If your search type has settings, you can implement
  * hook_search_admin() to add them to the search settings page. You can also
  * alter the display of your module's search results by implementing
- * hook_search_page(). And you can use hook_form_FORM_ID_alter(), with
- * FORM_ID set to 'search', to add fields to the search form. See
- * node_form_search_form_alter() for an example.
+ * hook_search_page(). You can use hook_form_FORM_ID_alter(), with
+ * FORM_ID set to 'search', to add fields to the search form (see
+ * node_form_search_form_alter() for an example). You can use
+ * hook_search_access() to limit access to searching, and hook_search_page() to
+ * override how search results are displayed.
  *
  * @return
  *   Array with optional keys:
@@ -248,7 +250,7 @@
 /**
  * Override the rendering of search results.
  *
- * A module that implements hook_search() to define a type of search
+ * A module that implements hook_search_info() to define a type of search
  * may implement this hook in order to override the default theming of
  * its search results, which is otherwise themed using theme('search_results').
  *
@@ -262,17 +264,20 @@
  *   An array of search results.
  *
  * @return
- *   An HTML string containing the formatted search results, with
+ *   A renderable array, which will render the formatted search results with
  *   a pager included.
  */
 function hook_search_page($results) {
-  $output = '<ol class="search-results">';
+  $output['prefix']['#markup'] = '<ol class="search-results">';
 
   foreach ($results as $entry) {
-    $output .= theme('search_result', $entry, $type);
+    $output[] = array(
+      '#theme' => 'search_result', 
+      '#result' => $entry, 
+      '#module' => 'my_module_name',
+    );
   }
-  $output .= '</ol>';
-  $output .= theme('pager', NULL);
+  $output['suffix']['#markup'] = '</ol>' . theme('pager');
 
   return $output;
 }
Index: modules/search/tests/search_extra_type.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/tests/search_extra_type.module,v
retrieving revision 1.2
diff -u -r1.2 search_extra_type.module
--- modules/search/tests/search_extra_type.module	11 Aug 2010 14:21:39 -0000	1.2
+++ modules/search/tests/search_extra_type.module	17 Aug 2010 16:44:11 -0000
@@ -17,6 +17,9 @@
   );
 }
 
+/**
+ * Test conditions callback for hook_search_info().
+ */
 function search_extra_type_conditions() {
   $conditions = array();
 
@@ -45,3 +48,23 @@
     ),
   );
 }
+
+/**
+ * Implements hook_search_page().
+ *
+ * Adds some text to the search page so we can verify that it runs.
+ */
+function search_extra_type_search_page($results) {
+  $output['prefix']['#markup'] = '<h2>Test page text is here</h2> <ol class="search-results">';
+
+  foreach ($results as $entry) {
+    $output[] = array(
+      '#theme' => 'search_result', 
+      '#result' => $entry, 
+      '#module' => 'search_extra_type',
+    );
+  }
+  $output['suffix']['#markup'] =  '</ol>' . theme('pager');
+
+  return $output;
+}
