apachesolr_autocomplete.module in Apache Solr Autocomplete 7
Same filename and directory in other branches
Alters search forms to suggest terms using Apache Solr using AJAX. Thanks to: robertDouglass who contributed some of the code. sch4lly for contributing to D7 version
File
apachesolr_autocomplete.moduleView source
<?php
/**
* @file
* Alters search forms to suggest terms using Apache Solr using AJAX.
* Thanks to:
* robertDouglass who contributed some of the code.
* sch4lly for contributing to D7 version
*/
/**
* Implementation of hook_init().
*/
function apachesolr_autocomplete_init() {
drupal_add_css(drupal_get_path('module', 'apachesolr_autocomplete') . '/apachesolr_autocomplete.css');
// If using custom JS widget, include its files and settings.
if (apachesolr_autocomplete_variable_get_widget() == 'custom') {
// Add custom autocomplete files
drupal_add_js(drupal_get_path('module', 'apachesolr_autocomplete') . '/apachesolr_autocomplete.js');
drupal_add_js(drupal_get_path('module', 'apachesolr_autocomplete') . '/jquery-autocomplete/jquery.autocomplete.js');
drupal_add_css(drupal_get_path('module', 'apachesolr_autocomplete') . '/jquery-autocomplete/jquery.autocomplete.css');
// Specify path to autocomplete handler.
drupal_add_js(array(
'apachesolr_autocomplete' => array(
'path' => url('apachesolr_autocomplete'),
),
), 'setting');
}
// If using jQuery UI autocomplete, include its files and settings.
if (apachesolr_autocomplete_variable_get_widget() == 'jqueryui') {
drupal_add_library('system', 'ui.autocomplete');
drupal_add_js(drupal_get_path('module', 'apachesolr_autocomplete') . '/apachesolr_autocomplete_jqueryui.js');
}
}
/**
* Implementation of hook_form_alter().
*/
function apachesolr_autocomplete_form_alter(&$form, $form_state, $form_id) {
switch ($form_id) {
case 'search_form':
if ($form['module']['#value'] == 'apachesolr_search' || $form['module']['#value'] == 'apachesolr_multisitesearch') {
$element =& $form['basic']['keys'];
$context_id = 'apachesolr_search_page:' . apachesolr_search_default_search_page();
}
break;
case 'search_block_form':
$element =& $form['search_block_form'];
$context_id = 'apachesolr_search_page:' . apachesolr_search_default_search_page();
break;
case 'apachesolr_search_custom_page_search_form':
$element =& $form['basic']['keys'];
$context_id = 'apachesolr_search_page:' . $form['#search_page']['page_id'];
break;
}
// Do the actual form altering.
if (isset($context_id) && isset($element)) {
apachesolr_autocomplete_do_alter($element, $form, $context_id);
}
}
/**
* Helper function to do the actual altering of search forms.
*
* @param $element
* The element to alter. Should be passed by reference so that original form
* element will be altered.
* E.g.: apachesolr_autocomplete_do_alter(&$form['xyz'])
* @param $form
* The form being altered.
* @param $context_id
* A string identifying the form. For example: apachesolr_search_page:core_search
*/
function apachesolr_autocomplete_do_alter(&$element, $form, $context_id) {
// The unique element ID for this form's keyword search element.
$autocomplete_element_id = $form['#id'];
// Specify path to autocomplete handler.
$autocomplete_path = 'apachesolr_autocomplete_callback/' . $context_id;
// Custom & jQuery UI widgets
if (apachesolr_autocomplete_variable_get_widget() != 'drupal') {
// Create elements if they do not exist.
if (!isset($element['#attributes'])) {
$element['#attributes'] = array();
}
if (!isset($element['#attributes']['class'])) {
$element['#attributes']['class'] = array();
}
array_push($element['#attributes']['class'], 'apachesolr-autocomplete');
// Add data-apachesolr-autocomplete attribute to element.
$element['#attributes']['data-apachesolr-autocomplete-id'] = array(
$autocomplete_element_id,
);
// Build a settings for this $autocomplete_element_id
$settings = array(
'apachesolr_autocomplete' => array(
'forms' => array(
$autocomplete_element_id => array(
'id' => $autocomplete_element_id,
// helps identify the element on jQuery
'path' => url($autocomplete_path),
),
),
),
);
drupal_add_js($settings, 'setting');
}
else {
// Drupal stock autocomplete handler.
$element['#autocomplete_path'] = $autocomplete_path;
}
}
/**
* Implementation of hook_menu().
*/
function apachesolr_autocomplete_menu() {
$items = array();
// Pattern is: apachesolr_autocomplete_callback/[context_id]
$items['apachesolr_autocomplete_callback/%'] = array(
'page callback' => 'apachesolr_autocomplete_callback',
'page arguments' => array(
1,
),
'access callback' => 'user_access',
'access arguments' => array(
'search content',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Callback for url apachesolr_autocomplete/autocomplete.
*
* @param $context_id
* A string identifying the form. For example: apachesolr_search_page:core_search
*/
function apachesolr_autocomplete_callback($context_id) {
// Get search page.
if (strpos($context_id, 'apachesolr_search_page:') === 0) {
$search_page_id = substr($context_id, 23);
}
else {
$search_page_id = 'core_search';
}
if ($search_page_id && function_exists('apachesolr_search_page_load')) {
$search_page = apachesolr_search_page_load($search_page_id);
if (!$search_page) {
$search_page = 0;
}
}
else {
$search_page = 0;
}
// TODO: Get more user entry, like state of 'retain current filters' and current filters, etc.
// Get terms
if (apachesolr_autocomplete_variable_get_widget() == 'custom') {
// Keys for custom widget come from $_GET.
$keys = isset($_GET['query']) ? $_GET['query'] : '';
}
elseif (apachesolr_autocomplete_variable_get_widget() == 'jqueryui') {
// Keys for custom widget come from $_GET.
$keys = isset($_GET['term']) ? $_GET['term'] : '';
}
elseif (apachesolr_autocomplete_variable_get_widget() == 'drupal') {
// Keys for custom widget come from $_GET.
$keys = arg(2);
}
if (!$keys) {
// Exit quickly when there are no keys.
drupal_json_output(array());
exit;
}
$suggestions = array();
$suggestions = array_merge($suggestions, apachesolr_autocomplete_suggest_word_completion($keys, 5, $search_page));
if (apachesolr_autocomplete_variable_get_suggest_keywords() || apachesolr_autocomplete_variable_get_suggest_spellcheck()) {
$suggestions = array_merge($suggestions, apachesolr_autocomplete_suggest_additional_term($keys, 5, $search_page));
}
// Allow other modules to alter the suggestions.
drupal_alter("apachesolr_autocomplete_suggestions", $suggestions, $keys);
$result = array();
$show_counts = apachesolr_autocomplete_variable_get_counts();
if (apachesolr_autocomplete_variable_get_widget() == 'custom') {
// Place suggestions into new array for returning as JSON.
foreach ($suggestions as $key => $suggestion) {
$display = theme($suggestion['theme'], array(
'suggestion' => $suggestion,
'show_counts' => $show_counts,
));
$result[] = array(
"key" => substr($key, 1),
"display" => $display,
);
}
}
elseif (apachesolr_autocomplete_variable_get_widget() == 'jqueryui') {
foreach ($suggestions as $key => $suggestion) {
$display = theme($suggestion['theme'], array(
'suggestion' => $suggestion,
'show_counts' => $show_counts,
));
$result[] = array(
"label" => '<a>' . $display . '</a>',
"value" => $suggestion['suggestion'],
);
}
if (count($result) == 0) {
$result[] = array(
"label" => '<span class="apachesolr_autocomplete message">' . t('No suggestions.') . '</span>',
);
}
}
elseif (apachesolr_autocomplete_variable_get_widget() == 'drupal') {
foreach ($suggestions as $key => $suggestion) {
$display = theme($suggestion['theme'], array(
'suggestion' => $suggestion,
'show_counts' => $show_counts,
));
$result[substr($key, 1)] = $display;
}
}
// Add caching headers.
// The cache lifetime will be:
// * apachesolr_autocomplete_cache_maximum_age if it's set and >0
// * else, use page_cache_maximum_age.
$cache_max_age = variable_get('apachesolr_autocomplete_cache_maximum_age', -1);
if ($cache_max_age == -1) {
$cache_max_age = variable_get('page_cache_maximum_age', 0);
}
if ($cache_max_age > 0) {
// Only add the caching headers if necessary.
drupal_add_http_header('Cache-Control', 'public, max-age=' . $cache_max_age);
}
// Send the output.
drupal_json_output($result);
exit;
}
/**
* Implementation of hook_theme().
*/
function apachesolr_autocomplete_theme() {
return array(
'apachesolr_autocomplete_highlight' => array(
'file' => 'apachesolr_autocomplete.module',
'arguments' => array(
'keys' => NULL,
'suggestion' => NULL,
'count' => NULL,
),
),
'apachesolr_autocomplete_spellcheck' => array(
'file' => 'apachesolr_autocomplete.module',
'arguments' => array(
'suggestion' => NULL,
),
),
);
}
/**
* Themes each returned suggestion.
*/
function theme_apachesolr_autocomplete_highlight($variables) {
static $first = true;
$keys = $variables['suggestion']['keys'];
$suggestion_string = $variables['suggestion']['suggestion'];
$count = $variables['suggestion']['count'];
$show_counts = $variables['show_counts'];
$html = '';
$html .= '<div class="apachesolr_autocomplete suggestion">';
$html .= '<strong>' . drupal_substr($suggestion_string, 0, strlen($keys)) . '</strong>' . drupal_substr($suggestion_string, strlen($keys));
$html .= '</div>';
if ($count && $show_counts) {
if ($first) {
$html .= "<div class='apachesolr_autocomplete message' style='float:right'>";
$html .= t('!count results', array(
'!count' => $count,
));
$html .= "</div><br style='clear:both'>";
$first = false;
}
else {
$html .= "<div class='apachesolr_autocomplete message count'>{$count}</div><br style='clear:both'>";
}
}
return $html;
}
/**
* Themes the spellchecker's suggestion.
*/
function theme_apachesolr_autocomplete_spellcheck($variables) {
$suggestion_string = $variables['suggestion']['suggestion'];
return '<span class="apachesolr_autocomplete message">' . t('Did you mean') . ':</span> ' . $suggestion_string;
}
/**
* Return the basic set of parameters for the Solr query.
*
* @param $suggestions_to_return
* Number of facets to return.
* @param array $search_page
* Search page.
* @return array
* Solr query parameters array.
*/
function apachesolr_autocomplete_basic_params($suggestions_to_return, $search_page = NULL) {
// Include any settings provided by apachesolr_search, if defined.
if (!empty($search_page) && function_exists("apachesolr_search_conditions_default")) {
$params = apachesolr_search_conditions_default($search_page);
}
else {
$params = array();
}
return array_merge($params, array(
'facet' => 'true',
'facet.field' => array(
'spell',
),
// We ask for $suggestions_to_return * 5 facets, because we want
// not-too-frequent terms (will be filtered below). 5 is just my best guess.
'facet.limit' => $suggestions_to_return * 5,
'facet.mincount' => 1,
'start' => 0,
'rows' => 0,
));
}
/**
* Helper function that suggests ways to complete partial words.
*
* For example, if $keys = "learn", this might return suggestions like:
* learn, learning, learner, learnability.
* The suggested terms are returned in order of frequency (most frequent first).
*
* @param string $keys
* Keys to search for.
* @param int $suggestions_to_return
* Number of suggestions to return.
* @param array $search_page
* Search page.
* @return array
* Suggestions array.
*/
function apachesolr_autocomplete_suggest_word_completion($keys, $suggestions_to_return = 5, $search_page = NULL) {
/**
* Split $keys into two:
* $first_part will contain all complete words (delimited by spaces). Can be empty.
* $last_part is the (assumed incomplete) last word. If this is empty, don't suggest.
* Example:
* $keys = "learning dis" : $first_part = "learning", $last_part = "dis"
*/
preg_match('/^(:?(.* |))([^ ]+)$/', $keys, $matches);
$first_part = @$matches[2];
// Make sure $last_part contains meaningful characters
$last_part = preg_replace('/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/u', '', @$matches[3]);
if ($last_part == '') {
return array();
}
// Ask Solr to return facets that begin with $last_part; these will be the suggestions.
$params = apachesolr_autocomplete_basic_params($suggestions_to_return, $search_page);
$params['facet.prefix'] = strtolower($last_part);
// Get array of themed suggestions.
$result = apachesolr_autocomplete_suggest($first_part, $params, $keys, $suggestions_to_return, $search_page);
if ($result && $result['suggestions']) {
return $result['suggestions'];
}
else {
return array();
}
}
/**
* Helper function that suggests additional terms to search for.
*
* For example, if $keys = "learn", this might return suggestions like:
* learn student, learn school, learn mathematics.
* The suggested terms are returned in order of frequency (most frequent first).
*
* @param string $keys
* Keys to search for.
* @param int $suggestions_to_return
* Number of suggestions to return.
* @param array $search_page
* Search page.
* @return array
* Suggestions array.
*/
function apachesolr_autocomplete_suggest_additional_term($keys, $suggestions_to_return = 5, $search_page = NULL) {
$keys = trim($keys);
$keys = check_plain($keys);
if ($keys == '') {
return array();
}
// Return no suggestions when $keys consists of only word delimiters
if (drupal_strlen(preg_replace('/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/u', '', $keys)) < 1) {
return array();
}
// Ask Solr to return facets from the 'spell' field to use as suggestions.
$params = apachesolr_autocomplete_basic_params($suggestions_to_return, $search_page);
// Initialize arrays
$suggestions = array();
$replacements = array();
// Get array of themed suggestions.
$result = apachesolr_autocomplete_suggest($keys, $params, $keys, $suggestions_to_return, $search_page);
if ($result && apachesolr_autocomplete_variable_get_suggest_keywords()) {
if (isset($result['suggestions']) && sizeof($result['suggestions'])) {
$suggestions = array_merge($suggestions, $result['suggestions']);
}
}
// Suggest using the spellchecker
if (apachesolr_autocomplete_variable_get_suggest_spellcheck()) {
if (isset($result['response']->spellcheck) && isset($result['response']->spellcheck->suggestions)) {
$spellcheck_suggestions = get_object_vars($result['response']->spellcheck->suggestions);
foreach ($spellcheck_suggestions as $word => $value) {
$replacements[$word] = $value->suggestion[0];
}
if (count($replacements)) {
$new_keywords = strtr($keys, $replacements);
if ($new_keywords != $keys) {
// Place spellchecker suggestion before others
$suggestion = array(
'theme' => 'apachesolr_autocomplete_spellcheck',
'suggestion' => $new_keywords,
);
$suggestions = array_merge(array(
'*' . $new_keywords => $suggestion,
), $suggestions);
}
}
}
}
return $suggestions;
}
/**
* Helper function to get suggestions from Solr.
*
* @param string $keys
* Keys to search for.
* @param $params
* Solr query parameters array.
* @param $orig_keys
* User-typed query.
* @param int $suggestions_to_return
* Number of suggestions to return.
* @param array $search_page
* Search page.
* @return array Suggestions array.
* Suggestions array.
*/
function apachesolr_autocomplete_suggest($keys, $params, $orig_keys, $suggestions_to_return = 5, $search_page = NULL) {
$matches = array();
$suggestions = array();
$keys = trim($keys);
// We need the keys array to make sure we don't suggest words that are already
// in the search terms.
$keys_array = explode(' ', $keys);
$keys_array = array_filter($keys_array);
// If $search_page is defined, use the environment for that
if (isset($search_page['env_id'])) {
$solr = apachesolr_get_solr($search_page['env_id']);
}
else {
$solr = apachesolr_get_solr();
}
// Query Solr for $keys so that suggestions will always return results.
$context = array(
'page_id' => $search_page['page_id'],
'search_type' => 'apachesolr_autocomplete',
);
$query = apachesolr_drupal_query('apachesolr_autocomplete', $params, '', '', $solr, $context);
if (!$query) {
return array();
}
apachesolr_search_add_spellcheck_params($query);
foreach ($params as $param => $paramValue) {
$query
->addParam($param, $paramValue);
}
apachesolr_search_add_boost_params($query);
// This hook allows modules to modify the query and params objects.
drupal_alter('apachesolr_query', $query);
// If the alter hook removed the query, we should abort!
if (!$query) {
return array();
}
// Query Solr
$response = $query
->search($keys);
// Loop through requested fields and get suggestions.
$facet_field = $query
->getParam('facet.field');
foreach ($facet_field as $field) {
foreach ($response->facet_counts->facet_fields->{$field} as $terms => $count) {
$terms = preg_replace('/[_-]+/', ' ', $terms);
foreach (explode(' ', $terms) as $term) {
if ($term = trim(preg_replace('/[' . PREG_CLASS_UNICODE_WORD_BOUNDARY . ']+/u', '', $term))) {
if (isset($matches[$term])) {
$matches[$term] += $count;
}
else {
$matches[$term] = $count;
}
}
}
}
}
if (sizeof($matches) > 0) {
// Eliminate suggestions that are stopwords or are already in the query.
$matches_clone = $matches;
$stopwords = apachesolr_autocomplete_get_stopwords($solr);
foreach ($matches_clone as $term => $count) {
if (strlen($term) > 3 && !in_array($term, $stopwords) && !array_search($term, $keys_array)) {
// Longer strings get higher ratings.
#$matches_clone[$term] += strlen($term);
}
else {
unset($matches_clone[$term]);
unset($matches[$term]);
}
}
// Don't suggest terms that are too frequent (in >90% of results).
$max_occurrence = $response->response->numFound * 0.9;
foreach ($matches_clone as $match => $count) {
if ($count > $max_occurrence) {
unset($matches_clone[$match]);
}
}
// The $count in this array is actually a score. We want the highest ones first.
arsort($matches_clone);
// Shorten the array to the right ones.
$matches_clone = array_slice($matches_clone, 0, $suggestions_to_return, TRUE);
// Add current search as suggestion if results > 0
if ($response->response->numFound > 0 && $keys != '') {
// Add * to array element key to force into a string, else PHP will
// renumber keys that look like numbers on the returned array.
$suggestions['*' . $keys] = array(
'theme' => 'apachesolr_autocomplete_highlight',
'keys' => $keys,
'suggestion' => $keys,
'count' => $response->response->numFound,
);
}
// Build suggestions using returned facets
foreach ($matches_clone as $match => $count) {
if ($keys != $match) {
$suggestion = trim($keys . ' ' . $match);
// On cases where there are more than 3 keywords, omit displaying
// the count because of the mm settings in solrconfig.xml
if (substr_count($suggestion, ' ') >= 2) {
$count = 0;
}
if ($suggestion != '') {
// Add * to array element key to force into a string, else PHP will
// renumber keys that look like numbers on the returned array.
$suggestions['*' . $suggestion] = array(
'theme' => 'apachesolr_autocomplete_highlight',
'keys' => $orig_keys,
'suggestion' => $suggestion,
'count' => $count,
);
}
}
}
}
return array(
'suggestions' => $suggestions,
'response' => &$response,
);
}
/**
* Gets the current stopwords list configured in Solr.
*/
function apachesolr_autocomplete_get_stopwords($solr = NULL) {
static $static_cache = array();
if (!$solr) {
$env_id = apachesolr_default_environment();
$solr = apachesolr_get_solr($env_id);
}
else {
$env_id = $solr
->getId();
}
// Try static cache.
if (isset($static_cache[$env_id])) {
return $static_cache[$env_id];
}
// Try Drupal cache.
$cid = 'apachesolr_autocomplete_stopwords:' . $env_id;
$cached = cache_get($cid);
if ($cached && $cached->expire > REQUEST_TIME) {
return $cached->data;
}
try {
$response = $solr
->makeServletRequest('admin/file', array(
'file' => 'stopwords.txt',
));
} catch (Exception $e) {
$static_cache[$env_id] = array();
return array();
}
$words = array();
foreach (explode("\n", $response->data) as $line) {
if (drupal_substr($line, 0, 1) == "#") {
continue;
}
if ($word = trim($line)) {
$words[] = $word;
}
}
// Cache in Drupal cache for 10 minutes.
cache_set($cid, $words, 'cache', REQUEST_TIME + 600);
$static_cache[$env_id] = $words;
return $words;
}
/**
* Wrapper around variable_get() for variable apachesolr_autocomplete_widget.
*/
function apachesolr_autocomplete_variable_get_widget() {
return variable_get('apachesolr_autocomplete_widget', 'jqueryui');
}
/**
* Wrapper around variable_get() for variable apachesolr_autocomplete_suggest_keywords.
*/
function apachesolr_autocomplete_variable_get_suggest_keywords() {
return variable_get('apachesolr_autocomplete_suggest_keywords', 1);
}
/**
* Wrapper around variable_get() for variable apachesolr_autocomplete_suggest_spellcheck.
*/
function apachesolr_autocomplete_variable_get_suggest_spellcheck() {
return variable_get('apachesolr_autocomplete_suggest_spellcheck', 1);
}
/**
* Wrapper around variable_get() for variable apachesolr_autocomplete_counts.
*/
function apachesolr_autocomplete_variable_get_counts() {
return variable_get('apachesolr_autocomplete_counts', TRUE);
}
/**
* Alter the apachesolr.module "advanced settings" form.
*/
function apachesolr_autocomplete_form_apachesolr_settings_alter(&$form, $form_state) {
$form['advanced']['apachesolr_autocomplete_widget'] = array(
'#type' => 'radios',
'#title' => t('Autocomplete widget to use'),
'#description' => t('The custom widget provides instant search upon selection, whereas the Drupal widget needs the user to hit Enter or click on the Search button. If you are having problems, try switching to the default Drupal autocomplete widget.'),
'#options' => array(
'jqueryui' => t('jQuery UI Autocomplete'),
'custom' => t('Custom autocomplete widget'),
'drupal' => t('Drupal core autocomplete widget'),
),
'#default_value' => apachesolr_autocomplete_variable_get_widget(),
);
$form['advanced']['apachesolr_autocomplete_suggest_keywords'] = array(
'#type' => 'checkbox',
'#title' => t('Enable additional keyword suggestions on the autocomplete widget'),
'#description' => t('Suggest words to add to the currently typed-in words. E.g.: typing "blue" might suggest "blue bike" or "blue shirt".'),
'#default_value' => apachesolr_autocomplete_variable_get_suggest_keywords(),
);
$form['advanced']['apachesolr_autocomplete_suggest_spellcheck'] = array(
'#type' => 'checkbox',
'#title' => t('Enable spellchecker suggestions on the autocomplete widget'),
'#description' => t('Suggest corrections to the currently typed-in words. E.g.: typing "rec" or "redd" might suggest "red".'),
'#default_value' => apachesolr_autocomplete_variable_get_suggest_spellcheck(),
);
$form['advanced']['apachesolr_autocomplete_counts'] = array(
'#type' => 'checkbox',
'#title' => t('Enable counts in autocomplete widget suggestions'),
'#description' => t('WARNING: Counts shown alongside suggestions might be lower than the actual result count due to stemming and minimum match (mm) settings in solrconfig.xml.'),
'#default_value' => apachesolr_autocomplete_variable_get_counts(),
);
}
Functions
Name | Description |
---|---|
apachesolr_autocomplete_basic_params | Return the basic set of parameters for the Solr query. |
apachesolr_autocomplete_callback | Callback for url apachesolr_autocomplete/autocomplete. |
apachesolr_autocomplete_do_alter | Helper function to do the actual altering of search forms. |
apachesolr_autocomplete_form_alter | Implementation of hook_form_alter(). |
apachesolr_autocomplete_form_apachesolr_settings_alter | Alter the apachesolr.module "advanced settings" form. |
apachesolr_autocomplete_get_stopwords | Gets the current stopwords list configured in Solr. |
apachesolr_autocomplete_init | Implementation of hook_init(). |
apachesolr_autocomplete_menu | Implementation of hook_menu(). |
apachesolr_autocomplete_suggest | Helper function to get suggestions from Solr. |
apachesolr_autocomplete_suggest_additional_term | Helper function that suggests additional terms to search for. |
apachesolr_autocomplete_suggest_word_completion | Helper function that suggests ways to complete partial words. |
apachesolr_autocomplete_theme | Implementation of hook_theme(). |
apachesolr_autocomplete_variable_get_counts | Wrapper around variable_get() for variable apachesolr_autocomplete_counts. |
apachesolr_autocomplete_variable_get_suggest_keywords | Wrapper around variable_get() for variable apachesolr_autocomplete_suggest_keywords. |
apachesolr_autocomplete_variable_get_suggest_spellcheck | Wrapper around variable_get() for variable apachesolr_autocomplete_suggest_spellcheck. |
apachesolr_autocomplete_variable_get_widget | Wrapper around variable_get() for variable apachesolr_autocomplete_widget. |
theme_apachesolr_autocomplete_highlight | Themes each returned suggestion. |
theme_apachesolr_autocomplete_spellcheck | Themes the spellchecker's suggestion. |