You are here

public function Search::query in Drupal 9

Same name in this branch
  1. 9 core/modules/search/src/Plugin/views/filter/Search.php \Drupal\search\Plugin\views\filter\Search::query()
  2. 9 core/modules/search/src/Plugin/views/argument/Search.php \Drupal\search\Plugin\views\argument\Search::query()
Same name and namespace in other branches
  1. 8 core/modules/search/src/Plugin/views/argument/Search.php \Drupal\search\Plugin\views\argument\Search::query()

Set up the query for this argument.

The argument sent may be found at $this->argument.

Overrides ArgumentPluginBase::query

File

core/modules/search/src/Plugin/views/argument/Search.php, line 60

Class

Search
Argument handler for search keywords.

Namespace

Drupal\search\Plugin\views\argument

Code

public function query($group_by = FALSE) {
  $required = FALSE;
  $this
    ->queryParseSearchExpression($this->argument);
  if (!isset($this->searchQuery)) {
    $required = TRUE;
  }
  else {
    $words = $this->searchQuery
      ->words();
    if (empty($words)) {
      $required = TRUE;
    }
  }
  if ($required) {
    if ($this->operator == 'required') {
      $this->query
        ->addWhere(0, 'FALSE');
    }
  }
  else {
    $search_index = $this
      ->ensureMyTable();
    $search_condition = $this->view->query
      ->getConnection()
      ->condition('AND');

    // Create a new join to relate the 'search_total' table to our current 'search_index' table.
    $definition = [
      'table' => 'search_total',
      'field' => 'word',
      'left_table' => $search_index,
      'left_field' => 'word',
    ];
    $join = Views::pluginManager('join')
      ->createInstance('standard', $definition);
    $search_total = $this->query
      ->addRelationship('search_total', $join, $search_index);

    // Add the search score field to the query.
    $this->search_score = $this->query
      ->addField('', "{$search_index}.score * {$search_total}.count", 'score', [
      'function' => 'sum',
    ]);

    // Add the conditions set up by the search query to the views query.
    $search_condition
      ->condition("{$search_index}.type", $this->searchType);
    $search_dataset = $this->query
      ->addTable('node_search_dataset');
    $conditions = $this->searchQuery
      ->conditions();
    $condition_conditions =& $conditions
      ->conditions();
    foreach ($condition_conditions as $key => &$condition) {

      // Make sure we just look at real conditions.
      if (is_numeric($key)) {

        // Replace the conditions with the table alias of views.
        $this->searchQuery
          ->conditionReplaceString('d.', "{$search_dataset}.", $condition);
      }
    }
    $search_conditions =& $search_condition
      ->conditions();
    $search_conditions = array_merge($search_conditions, $condition_conditions);

    // Add the keyword conditions, as is done in
    // SearchQuery::prepareAndNormalize(), but simplified because we are
    // only concerned with relevance ranking so we do not need to normalize.
    $or = $this->view->query
      ->getConnection()
      ->condition('OR');
    foreach ($words as $word) {
      $or
        ->condition("{$search_index}.word", $word);
    }
    $search_condition
      ->condition($or);

    // Add the GROUP BY and HAVING expressions to the query.
    $this->query
      ->addWhere(0, $search_condition);
    $this->query
      ->addGroupBy("{$search_index}.sid");
    $matches = $this->searchQuery
      ->matches();
    $placeholder = $this
      ->placeholder();
    $this->query
      ->addHavingExpression(0, "COUNT(*) >= {$placeholder}", [
      $placeholder => $matches,
    ]);
  }

  // Set to NULL to prevent PDO exception when views object is cached
  // and to clear out memory.
  $this->searchQuery = NULL;
}