You are here

public function Views::createQuery in Search API Autocomplete 8

Creates a search query based on this search.

Parameters

string $keys: The keywords to set on the query, if possible. Otherwise, this parameter can also be ignored.

array $data: (optional) Additional data passed to the callback.

Return value

\Drupal\search_api\Query\QueryInterface The created query.

Throws

\Drupal\search_api_autocomplete\SearchApiAutocompleteException Thrown if the query couldn't be created.

Overrides SearchPluginInterface::createQuery

File

src/Plugin/search_api_autocomplete/search/Views.php, line 138

Class

Views
Provides autocomplete support for Views search.

Namespace

Drupal\search_api_autocomplete\Plugin\search_api_autocomplete\search

Code

public function createQuery($keys, array $data = []) {
  $views_id = $this
    ->getDerivativeId();
  $view = $this
    ->getEntityTypeManager()
    ->getStorage('view')
    ->load($views_id);
  if ($view instanceof ViewEntityInterface) {
    $view = $this
      ->getViewsExecutableFactory()
      ->get($view);
  }
  if (!$view) {
    $vars['@view'] = $views_id;
    throw new SearchApiAutocompleteException($this
      ->t('Could not load view @view.', $vars));
  }
  $data += [
    'display' => NULL,
    'arguments' => [],
  ];
  $view
    ->setDisplay($data['display']);
  $view
    ->setArguments($data['arguments']);

  // Set the keys via the exposed input, to get the correct handling for the
  // filter in question.
  $single_field_filter = !empty($data['field']);
  if (!empty($data['filter'])) {
    $input = $keys;

    // The Views filter for individual fulltext fields uses a nested "value"
    // field for the real input, due to Views internals.
    if ($single_field_filter) {
      $input = [
        'value' => $keys,
      ];
    }
    $view
      ->setExposedInput([
      $data['filter'] => $input,
    ]);
  }
  $view
    ->preExecute();

  // Since we only have a single value in the exposed input, any exposed
  // filters set to "Required" might cause problems – especially "Search:
  // Fulltext search", which aborts the query when validation fails (instead
  // of relying on the Form API "#required" validation). The normal filters
  // which use the Form API actually don't seem to cause problems, but it's
  // still better to be on the safe side here and just disabled "Required" for
  // all filters. (It also makes the code simpler.)

  /** @var \Drupal\views\Plugin\views\filter\FilterPluginBase $filter */
  foreach ($view->display_handler
    ->getHandlers('filter') as $filter) {
    $filter->options['expose']['required'] = FALSE;
  }
  $view
    ->build();
  $query_plugin = $view
    ->getQuery();
  if (!$query_plugin instanceof SearchApiQuery) {
    $views_label = $view->storage
      ->label() ?: $views_id;
    throw new SearchApiAutocompleteException("Could not create search query for view '{$views_label}': view is not based on Search API.");
  }
  $query = $query_plugin
    ->getSearchApiQuery();
  if (!$query) {
    $views_label = $view->storage
      ->label() ?: $views_id;
    throw new SearchApiAutocompleteException("Could not create search query for view '{$views_label}'.");
  }
  if ($single_field_filter) {
    $query
      ->setFulltextFields([
      $data['field'],
    ]);
  }
  return $query;
}