Spotlightish search result grouping
Here's a fun, albeit hackish search theme snippet for Drupal.
It takes advantage of the fact that the temporary tables for search stay around, to present results grouped by node type à la Apple Spotlight. Note that it does not simply reformat a single search result page, but regroups results across all pages.
In fact, it's really just a hackish way of doing N separate queries that contain a type:something
restriction, one for each node type. To see more results, it presents you with a link to a normal type:something
query.
It's a bit inefficient in that the presentational work for the normal results is thrown away (loading nodes, filtering content, extracting a summary). But it's a start ;).
<?php
define('SEARCH_TYPE_ITEMS', 5);
function _node_search_result($nid) {
$node = node_load($nid);
// Get node output (filtered and with module-specific fields).
if (node_hook($node, 'view')) {
node_invoke($node, 'view', false, false);
}
else {
$node = node_prepare($node, false);
}
// Allow modules to change $node->body before viewing.
node_invoke_nodeapi($node, 'view', false, false);
// Fetch comments for snippet
$node->body .= module_invoke('comment', 'nodeapi', $node, 'update index');
// Fetch terms for snippet
$node->body .= module_invoke('taxonomy', 'nodeapi', $node, 'update index');
$extra = node_invoke_nodeapi($node, 'search result');
return array('link' => url('node/'. $nid),
'type' => node_get_name($node),
'title' => $node->title,
'user' => theme('username', $node),
'date' => $node->changed,
'node' => $node,
'extra' => $extra,
'snippet' => search_excerpt($keys, $node->body));
}
function phptemplate_search_page($results, $type) {
// Only kick in for type-agnostic node searches
if ($type == 'node' && !search_query_extract($keys = search_get_keys(), 'type')) {
// Get all types used in results
$result = db_query("SELECT DISTINCT(n.type) FROM temp_search_results s LEFT JOIN node n ON s.sid = n.nid");
while ($node = db_fetch_object($result)) {
$types[] = $node->type;
}
$output = '';
foreach ($types as $type) {
// Fetch results of one particular type from the 2nd search pass results
$result = db_query_range("SELECT n.nid FROM temp_search_results s LEFT JOIN node n ON s.sid = n.nid WHERE n.type = '%s'", $type, 0, SEARCH_TYPE_ITEMS + 1);
$output .= '<h2>'. check_plain($type) .'</h2>';
$i = 0;
$output .= '<dl class="search-results">';
while (($node = db_fetch_object($result)) && $i++ < SEARCH_TYPE_ITEMS) {
$output .= theme('search_item', _node_search_result($node->nid), $type);
}
$output .= '</dl>';
if (db_num_rows($result) > SEARCH_TYPE_ITEMS) {
$output .= l(t('More results'), 'search/node/'. search_query_insert(search_get_keys(), 'type', $type));
}
}
return $output;
}
}
// Otherwise present the default page
return theme_search_page($results, $type);
}