You are here

public function LiveResults::getAutocompleteSuggestions in Search API Autocomplete 8

Retrieves autocompletion suggestions for some user input.

For example, when given the user input "teach us", with "us" being considered incomplete, \Drupal\search_api_autocomplete\SuggestionInterface objects representing the following suggestions might be returned:

[
  [
    'prefix' => t('Did you mean:'),
    'user_input' => 'reach us',
  ],
  [
    'user_input' => 'teach us',
    'suggestion_suffix' => 'ers',
  ],
  [
    'user_input' => 'teach us',
    'suggestion_suffix' => ' swimming',
  ],
];

Parameters

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

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 autocomplete suggestions.

Overrides SuggesterInterface::getAutocompleteSuggestions

File

src/Plugin/search_api_autocomplete/suggester/LiveResults.php, line 282

Class

LiveResults
Provides a suggester plugin that displays live results.

Namespace

Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\suggester

Code

public function getAutocompleteSuggestions(QueryInterface $query, $incomplete_key, $user_input) {
  $fulltext_fields = $this->configuration['fields'];
  $index = $query
    ->getIndex();
  if ($fulltext_fields) {

    // Take care only to set fields that are still indexed fulltext fields.
    $index_fields = $index
      ->getFulltextFields();
    $fulltext_fields = array_intersect($fulltext_fields, $index_fields);
    if ($fulltext_fields) {
      $query
        ->setFulltextFields($fulltext_fields);
    }
    else {
      $args = [
        '@suggester' => $this
          ->label(),
        '@search' => $this
          ->getSearch()
          ->label(),
        '@index' => $index
          ->label(),
      ];
      $this
        ->getLogger()
        ->warning('Only invalid fulltext fields set for suggester "@suggester" in autocomplete settings for search "@search" on index "@index".', $args);
    }
  }
  $query
    ->keys($user_input);
  try {
    $results = $query
      ->execute();
  } catch (SearchApiException $e) {

    // If the query fails, there's nothing we can do about that.
    return [];
  }

  // Pre-load the result items for performance reasons.
  $item_ids = array_keys($results
    ->getResultItems());
  $objects = $index
    ->loadItemsMultiple($item_ids);
  $factory = new SuggestionFactory($user_input);
  $suggestions = [];
  $view_modes = $this->configuration['view_modes'];
  $highlight_field = NULL;
  if ($this
    ->isHighlightingEnabled()) {
    $highlight_field = $this->configuration['highlight']['field'];
  }
  foreach ($results
    ->getResultItems() as $item_id => $item) {

    // If the result object could not be loaded, there's little we can do
    // here.
    if (empty($objects[$item_id])) {
      continue;
    }
    $object = $objects[$item_id];
    $item
      ->setOriginalObject($object);
    try {
      $datasource = $item
        ->getDatasource();
    } catch (SearchApiException $e) {

      // This should almost never happen, but theoretically it could, so we
      // just skip the item if this happens.
      continue;
    }

    // Check whether the user has access to this item.
    if (!$item
      ->getAccessResult()
      ->isAllowed()) {
      continue;
    }

    // Can't include results that don't have a URL.
    $url = $datasource
      ->getItemUrl($object);
    if (!$url) {
      continue;
    }
    $datasource_id = $item
      ->getDatasourceId();
    $bundle = $datasource
      ->getItemBundle($object);

    // Use highlighted field, if configured.
    if ($highlight_field) {
      $highlighted_fields = $item
        ->getExtraData('highlighted_fields');
      if (isset($highlighted_fields[$highlight_field][0])) {
        $highlighted_field = [
          '#type' => 'markup',
          '#markup' => Xss::filterAdmin($highlighted_fields[$highlight_field][0]),
        ];
        $suggestions[] = $factory
          ->createUrlSuggestion($url, NULL, $highlighted_field);
        continue;
      }
    }

    // If no view mode was selected for this bundle, just use the label.
    if (empty($view_modes[$datasource_id][$bundle])) {
      $label = $datasource
        ->getItemLabel($object);
      $suggestions[] = $factory
        ->createUrlSuggestion($url, $label);
    }
    else {
      $view_mode = $view_modes[$datasource_id][$bundle];
      $render = $datasource
        ->viewItem($object, $view_mode);
      if ($render) {

        // Add the excerpt to the render array to allow adding it to view
        // modes.
        $render['#search_api_excerpt'] = $item
          ->getExcerpt();
        $suggestions[] = $factory
          ->createUrlSuggestion($url, NULL, $render);
      }
    }
  }
  return $suggestions;
}