'Content', 'path' => 'node', 'conditions_callback' => 'callback_search_conditions', ); } /** * Define access to a custom search routine. * * This hook allows a module to define permissions for a search tab. * * @ingroup search */ function hook_search_access() { return user_access('access content'); } /** * Take action when the search index is going to be rebuilt. * * Modules that use hook_update_index() should update their indexing * bookkeeping so that it starts from scratch the next time * hook_update_index() is called. * * @ingroup search */ function hook_search_reset() { db_update('search_dataset') ->fields(array('reindex' => REQUEST_TIME)) ->condition('type', 'node') ->execute(); } /** * Report the status of indexing. * * The core search module only invokes this hook on active modules. * Implementing modules do not need to check whether they are active when * calculating their return values. * * @return * An associative array with the key-value pairs: * - 'remaining': The number of items left to index. * - 'total': The total number of items to index. * * @ingroup search */ function hook_search_status() { $total = db_query('SELECT COUNT(*) FROM {node} WHERE status = 1')->fetchField(); $remaining = db_query("SELECT COUNT(*) FROM {node} n LEFT JOIN {search_dataset} d ON d.type = 'node' AND d.sid = n.nid WHERE n.status = 1 AND d.sid IS NULL OR d.reindex <> 0")->fetchField(); return array('remaining' => $remaining, 'total' => $total); } /** * Add elements to the search settings form. * * @return * Form array for the Search settings page at admin/config/search/settings. * * @ingroup search */ function hook_search_admin() { // Output form for defining rank factor weights. $form['content_ranking'] = array( '#type' => 'fieldset', '#title' => t('Content ranking'), ); $form['content_ranking']['#theme'] = 'node_search_admin'; $form['content_ranking']['info'] = array( '#value' => '' . t('The following numbers control which properties the content search should favor when ordering the results. Higher numbers mean more influence, zero means the property is ignored. Changing these numbers does not require the search index to be rebuilt. Changes take effect immediately.') . '' ); // Note: reversed to reflect that higher number = higher ranking. $options = drupal_map_assoc(range(0, 10)); foreach (module_invoke_all('ranking') as $var => $values) { $form['content_ranking']['factors']['node_rank_' . $var] = array( '#title' => $values['title'], '#type' => 'select', '#options' => $options, '#default_value' => variable_get('node_rank_' . $var, 0), ); } return $form; } /** * Execute a search for a set of key words. * * Use database API with the 'PagerDefault' query extension to perform your * search. * * If your module uses hook_update_index() and search_index() to index its * items, use table 'search_index' aliased to 'i' as the main table in your * query, with the 'SearchQuery' extension. You can join to your module's table * using the 'i.sid' field, which will contain the $sid values you provided to * search_index(). Add the main keywords to the query by using method * searchExpression(). The functions search_expression_extract() and * search_expression_insert() may also be helpful for adding custom search * parameters to the search expression. * * See node_search_execute() for an example of a module that uses the search * index, and user_search_execute() for an example that doesn't use the search * index. * * @param $keys * The search keywords as entered by the user. * @param $conditions * An optional array of additional conditions, such as filters. * * @return * An array of search results. To use the default search result * display, each item should have the following keys': * - 'link': Required. The URL of the found item. * - 'type': The type of item (such as the content type). * - 'title': Required. The name of the item. * - 'user': The author of the item. * - 'date': A timestamp when the item was last modified. * - 'extra': An array of optional extra information items. * - 'snippet': An excerpt or preview to show with the result (can be * generated with search_excerpt()). * - 'language': Language code for the item (usually two characters). * * @ingroup search */ function hook_search_execute($keys = NULL, $conditions = NULL) { // Build matching conditions $query = db_select('search_index', 'i', array('target' => 'slave'))->extend('SearchQuery')->extend('PagerDefault'); $query->join('node', 'n', 'n.nid = i.sid'); $query ->condition('n.status', 1) ->addTag('node_access') ->searchExpression($keys, 'node'); // Insert special keywords. $query->setOption('type', 'n.type'); $query->setOption('language', 'n.language'); if ($query->setOption('term', 'ti.tid')) { $query->join('taxonomy_index', 'ti', 'n.nid = ti.nid'); } // Only continue if the first pass query matches. if (!$query->executeFirstPass()) { return array(); } // Add the ranking expressions. _node_rankings($query); // Load results. $find = $query ->limit(10) ->execute(); $results = array(); foreach ($find as $item) { // Build the node body. $node = node_load($item->sid); node_build_content($node, 'search_result'); $node->body = drupal_render($node->content); // Fetch comments for snippet. $node->rendered .= ' ' . module_invoke('comment', 'node_update_index', $node); // Fetch terms for snippet. $node->rendered .= ' ' . module_invoke('taxonomy', 'node_update_index', $node); $extra = module_invoke_all('node_search_result', $node); $results[] = array( 'link' => url('node/' . $item->sid, array('absolute' => TRUE)), 'type' => check_plain(node_type_get_name($node)), 'title' => $node->title, 'user' => theme('username', array('account' => $node)), 'date' => $node->changed, 'node' => $node, 'extra' => $extra, 'score' => $item->calculated_score, 'snippet' => search_excerpt($keys, $node->body), ); } return $results; } /** * Override the rendering of search results. * * 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'). * * Note that by default, theme('search_results') and theme('search_result') * work together to create an ordered list (OL). So your hook_search_page() * implementation should probably do this as well. * * @param $results * An array of search results. * * @return * A renderable array, which will render the formatted search results with a * pager included. * * @see search-result.tpl.php * @see search-results.tpl.php */ function hook_search_page($results) { $output['prefix']['#markup'] = '