You are here

public function SearchApiSolrBackend::getAutocompleteSuggestions in Search API Solr 8

Same name and namespace in other branches
  1. 8.3 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::getAutocompleteSuggestions()
  2. 8.2 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::getAutocompleteSuggestions()
  3. 4.x src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::getAutocompleteSuggestions()

Implements autocomplete compatible to AutocompleteBackendInterface.

Parameters

\Drupal\search_api\Query\QueryInterface $query: A query representing the completed user input so far.

\Drupal\search_api_autocomplete\SearchInterface $search: An object containing details about the search the user is on, and settings for the autocompletion. See the class documentation for details. Especially $search->options should be checked for settings, like whether to try and estimate result counts for returned suggestions.

string $incomplete_key: The start of another fulltext keyword for the search, which should be completed. Might be empty, in which case all user input up to now was considered completed. Then, additional keywords for the search could be suggested.

string $user_input: The complete user input for the fulltext search keywords so far.

Return value

\Drupal\search_api_autocomplete\Suggestion\SuggestionInterface[] An array of suggestions.

See also

\Drupal\search_api_autocomplete\AutocompleteBackendInterface

File

src/Plugin/search_api/backend/SearchApiSolrBackend.php, line 2084

Class

SearchApiSolrBackend
Apache Solr backend for search api.

Namespace

Drupal\search_api_solr\Plugin\search_api\backend

Code

public function getAutocompleteSuggestions(QueryInterface $query, SearchInterface $search, $incomplete_key, $user_input) {
  $suggestions = [];
  $factory = NULL;
  if (class_exists(SuggestionFactory::class)) {
    $factory = new SuggestionFactory($user_input);
  }
  if ($this->configuration['suggest_suffix'] || $this->configuration['suggest_corrections'] || $this->configuration['suggest_words']) {
    $connector = $this
      ->getSolrConnector();
    $solr_version = $connector
      ->getSolrVersion();
    if (version_compare($solr_version, '6.5', '=')) {
      \Drupal::logger('search_api_solr')
        ->error('Solr 6.5.x contains a bug that breaks the autocomplete feature. Downgrade to 6.4.x or upgrade to 6.6.x.');
      return [];
    }
    $solarium_query = $connector
      ->getTermsQuery();
    $schema_version = $connector
      ->getSchemaVersion();
    if (version_compare($schema_version, '5.4', '>=')) {
      $solarium_query
        ->setHandler('autocomplete');
    }
    else {
      $solarium_query
        ->setHandler('terms');
    }
    try {
      $fl = [];
      if (version_compare($schema_version, '5.4', '>=')) {
        $fl = $this
          ->getAutocompleteFields($query, $search);
      }
      else {
        $fl[] = 'spell';
      }

      // Make the input lowercase as the indexed data is (usually) also all
      // lowercase.
      $incomplete_key = mb_strtolower($incomplete_key);
      $user_input = mb_strtolower($user_input);
      $solarium_query
        ->setFields($fl);
      $solarium_query
        ->setPrefix($incomplete_key);
      $solarium_query
        ->setLimit(10);
      if ($this->configuration['suggest_corrections']) {
        $solarium_query
          ->addParam('q', $user_input);
        $solarium_query
          ->addParam('spellcheck', 'true');
        $solarium_query
          ->addParam('spellcheck.count', 1);
      }

      /** @var \Solarium\QueryType\Terms\Result $terms_result */
      $terms_result = $connector
        ->execute($solarium_query);
      $autocomplete_terms = [];
      foreach ($terms_result as $terms) {
        foreach ($terms as $term => $count) {
          if ($term != $incomplete_key) {
            $autocomplete_terms[$term] = $count;
          }
        }
      }
      if ($this->configuration['suggest_suffix']) {
        foreach ($autocomplete_terms as $term => $count) {
          $suggestion_suffix = mb_substr($term, mb_strlen($incomplete_key));
          if ($factory) {
            $suggestions[] = $factory
              ->createFromSuggestionSuffix($suggestion_suffix, $count);
          }
          else {
            $suggestions[] = Suggestion::fromSuggestionSuffix($suggestion_suffix, $count, $user_input);
          }
        }
      }
      if ($this->configuration['suggest_corrections']) {
        if (version_compare($schema_version, '5.4', '<')) {
          $solarium_query
            ->setHandler('select');
          $terms_result = $connector
            ->execute($solarium_query);
        }

        // this executes the query and returns the result
        $suggester_result = new SuggesterResult(new SuggesterQuery(), $terms_result
          ->getResponse());
        $suggestion_data = $suggester_result
          ->getData();
        if (isset($suggestion_data['spellcheck']['suggestions'])) {

          // Suggestion spell check alternates between term and suggestions
          $suggestion_string = '';
          foreach ($suggestion_data['spellcheck']['suggestions'] as $key => $sg) {
            if (isset($suggestion_data['spellcheck']['suggestions'][$key + 1]) && is_array($suggestion_data['spellcheck']['suggestions'][$key + 1])) {
              $correction = array_pop($suggestion_data['spellcheck']['suggestions'][$key + 1]);
              $suggestion_string .= implode(' ', $correction) . ' ';
            }
          }

          // Don't add the string if we're just getting a suffix.
          if (isset($suggestion_suffix) && (string) ($user_input . $suggestion_suffix) == trim($suggestion_string)) {
            return $suggestions;
          }
          if ($factory) {
            $suggestions[] = $factory
              ->createFromSuggestedKeys(trim($suggestion_string));
          }
          else {
            $suggestions[] = Suggestion::fromSuggestedKeys(trim($suggestion_string), $user_input);
          }
        }
      }
    } catch (SearchApiException $e) {
      watchdog_exception('search_api_solr', $e);
      return [];
    }
  }
  return $suggestions;
}