You are here

protected function SearchApiSolrBackend::createFilterQueries in Search API Solr 4.x

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::createFilterQueries()
  2. 8 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::createFilterQueries()
  3. 8.2 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::createFilterQueries()

Recursively transforms conditions into a flat array of Solr filter queries.

Parameters

\Drupal\search_api\Query\ConditionGroupInterface $condition_group: The group of conditions.

array $options: The query options.

\Drupal\search_api\Query\QueryInterface $query: The query to apply the filter queries to.

array $language_ids: (optional) The language IDs required for recursion. Should be empty on initial call!

Return value

array Array of filter query strings.

Throws

\Drupal\search_api\SearchApiException

1 call to SearchApiSolrBackend::createFilterQueries()
SearchApiSolrBackend::getFilterQueries in src/Plugin/search_api/backend/SearchApiSolrBackend.php
Serializes a query's conditions as Solr filter queries.

File

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

Class

SearchApiSolrBackend
Apache Solr backend for search api.

Namespace

Drupal\search_api_solr\Plugin\search_api\backend

Code

protected function createFilterQueries(ConditionGroupInterface $condition_group, array &$options, QueryInterface $query, array $language_ids = []) {
  static $index_fields = [];
  static $index_fulltext_fields = [];
  $index = $query
    ->getIndex();
  $index_id = $index
    ->id();
  if (empty($language_ids)) {

    // Reset.
    unset($index_fields[$index_id]);
    unset($index_fulltext_fields[$index_id]);
  }
  if (!isset($index_fields[$index_id])) {
    $index_fields[$index_id] = $index
      ->getFields(TRUE) + $this
      ->getSpecialFields($index);
  }
  if (!isset($index_fulltext_fields[$index_id])) {
    $index_fulltext_fields[$index_id] = $index
      ->getFulltextFields();
  }

  // If there's a language condition take this one anfd keep it for nested
  // conditions until we get a new language condition.
  $conditions = $condition_group
    ->getConditions();
  foreach ($conditions as $condition) {
    if ($condition instanceof ConditionInterface) {
      if ('search_api_language' === $condition
        ->getField()) {
        $language_ids = $condition
          ->getValue();
        if (!is_array($language_ids)) {
          $language_ids = [
            $language_ids,
          ];
        }
      }
    }
  }

  // If there's no language condition on the first level, take the one from
  // the query.
  if (!$language_ids) {
    $language_ids = $this
      ->ensureLanguageCondition($query);
  }
  if (!$language_ids) {
    throw new SearchApiSolrException('Unable to create filter queries if no language is set on any condition or the query itself.');
  }
  $solr_fields = $this
    ->getSolrFieldNamesKeyedByLanguage($language_ids, $index);
  $fq = [];
  foreach ($conditions as $condition) {
    if ($condition instanceof ConditionInterface) {

      // Nested condition.
      $field = $condition
        ->getField();
      if (!isset($solr_fields[$field])) {
        throw new SearchApiException("Filter term on unknown or unindexed field {$field}.");
      }
      $value = $condition
        ->getValue();
      $filter_query = '';
      if (in_array($field, $index_fulltext_fields[$index_id])) {
        if ($value) {
          if (empty($language_ids)) {
            throw new SearchApiException('Conditon on fulltext field without corresponding condition on search_api_language detected.');
          }

          // Fulltext fields.
          $parse_mode_id = $query
            ->getParseMode()
            ->getPluginId();
          $keys = [
            '#conjunction' => 'OR',
            '#negation' => $condition
              ->getOperator() === '<>',
          ];
          switch ($parse_mode_id) {

            // This is a hack. We assume that the user filters for any term /
            // phrase. But this prevents an explicit selection of all terms.
            // @see https://www.drupal.org/project/search_api/issues/2991134
            case 'terms':
            case 'phrase':
            case 'sloppy_phrase':
            case 'sloppy_terms':
            case 'fuzzy_terms':
            case 'edismax':
              if (is_array($value)) {
                $keys += $value;
              }
              else {
                $keys[] = $value;
              }
              break;
            case 'direct':
              $keys = $value;
              break;
            default:
              throw new SearchApiSolrException('Incompatible parse mode.');
          }
          $settings = Utility::getIndexSolrSettings($index);
          $filter_query = Utility::flattenKeys($keys, $solr_fields[$field], $parse_mode_id, $settings['term_modifiers']);
        }
        else {

          // Fulltext fields checked against NULL.
          $nested_fqs = [];
          foreach ($solr_fields[$field] as $solr_field) {
            $nested_fqs[] = [
              'query' => $this
                ->createFilterQuery($solr_field, $value, $condition
                ->getOperator(), $index_fields[$index_id][$field], $options),
              'tags' => $condition_group
                ->getTags(),
            ];
          }
          $fq[] = $this
            ->reduceFilterQueries($nested_fqs, new ConditionGroup('=' === $condition
            ->getOperator() ? 'AND' : 'OR', $condition_group
            ->getTags()));
        }
      }
      else {

        // Non-fulltext fields.
        $filter_query = $this
          ->createFilterQuery(reset($solr_fields[$field]), $value, $condition
          ->getOperator(), $index_fields[$index_id][$field], $options);
      }
      if ($filter_query) {
        $fq[] = [
          [
            'query' => $filter_query,
            'tags' => $condition_group
              ->getTags(),
          ],
        ];
      }
    }
    else {

      // Nested condition group.
      $nested_fqs = $this
        ->createFilterQueries($condition, $options, $query, $language_ids);
      $fq[] = $this
        ->reduceFilterQueries($nested_fqs, $condition);
    }
  }
  if ($fq) {
    return array_merge(...$fq);
  }
  return [];
}