You are here

protected function SearchApiSolrBackend::flattenKeys in Search API Solr 8.2

Same name and namespace in other branches
  1. 8 src/Plugin/search_api/backend/SearchApiSolrBackend.php \Drupal\search_api_solr\Plugin\search_api\backend\SearchApiSolrBackend::flattenKeys()

Flattens keys and fields into a single search string.

Parameters

array|string $keys: The keys array to flatten, formatted as specified by \Drupal\search_api\Query\QueryInterface::getKeys() or a phrase string.

array $fields:

string $parse_mode_id:

Return value

string A Solr query string representing the same keys.

Throws

\Drupal\search_api_solr\SearchApiSolrException

3 calls to SearchApiSolrBackend::flattenKeys()
AbstractSearchApiSolrMultilingualBackend::preQuery in src/Plugin/search_api/backend/AbstractSearchApiSolrMultilingualBackend.php
Modify the query before it is sent to solr.
SearchApiSolrBackend::createFilterQueries in src/Plugin/search_api/backend/SearchApiSolrBackend.php
Recursively transforms conditions into a flat array of Solr filter queries.
SearchApiSolrBackend::search in src/Plugin/search_api/backend/SearchApiSolrBackend.php
Options on $query prefixed by 'solr_param_' will be passed natively to Solr as query parameter without the prefix. For example you can set the "Minimum Should Match" parameter 'mm' to '75%' like this:

File

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

Class

SearchApiSolrBackend
Apache Solr backend for search api.

Namespace

Drupal\search_api_solr\Plugin\search_api\backend

Code

protected function flattenKeys($keys, array $fields = [], string $parse_mode_id = 'phrase') {
  $k = [];
  $pre = '+';
  $neg = '';
  if (is_array($keys)) {
    if (isset($keys['#conjunction']) && $keys['#conjunction'] == 'OR') {
      $pre = '';
    }
    if (!empty($keys['#negation'])) {
      $neg = '-';
    }
    $escaped = isset($keys['#escaped']) ? $keys['#escaped'] : FALSE;
    foreach ($keys as $key_nr => $key) {

      // We cannot use \Drupal\Core\Render\Element::children() anymore because
      // $keys is not a valid render array.
      if ($key_nr[0] === '#' || !$key) {
        continue;
      }
      if (is_array($key)) {
        if ($subkeys = $this
          ->flattenKeys($key, $fields, $parse_mode_id)) {
          $k[] = $subkeys;
        }
      }
      elseif ($escaped) {
        $k[] = trim($key);
      }
      else {
        switch ($parse_mode_id) {
          case 'phrase':
            $k[] = $this->queryHelper
              ->escapePhrase(trim($key));
            break;
          case 'terms':
            $k[] = $this->queryHelper
              ->escapeTerm(trim($key));
            break;
          default:
            throw new SearchApiSolrException('Incompatible parse mode.');
        }
      }
    }
  }
  elseif (is_string($keys)) {
    switch ($parse_mode_id) {
      case 'direct':
        $k[] = '(' . trim($keys) . ')';
        break;
      default:
        throw new SearchApiSolrException('Incompatible parse mode.');
    }
  }
  if (!$k) {
    return '';
  }

  // Formatting the keys into a Solr query can be a bit complex. Keep in mind
  // that the default operator is OR. The following code will produce filters
  // that look like this:
  //
  // #conjunction | #negation | fields | return value
  // ----------------------------------------------------------------
  // AND          | FALSE     | []     | (+A +B)
  // AND          | TRUE      | []     | -(+A +B)
  // OR           | FALSE     | []     | (A B)
  // OR           | TRUE      | []     | -(A B)
  // AND          | FALSE     | [x]    | (+x:A +x:B)
  // AND          | TRUE      | [x]    | -(+x:A +x:B)
  // OR           | FALSE     | [x]    | (x:A x:B)
  // OR           | TRUE      | [x]    | -(x:A x:B)
  // AND          | FALSE     | [x,y]  | (+(x:A y:A) +(x:B y:B))
  // AND          | TRUE      | [x,y]  | -(+(x:A y:A) +(x:B y:B))
  // OR           | FALSE     | [x,y]  | ((x:A y:A) (x:B y:B))
  // OR           | TRUE      | [x,y]  | -((x:A y:A) (x:B y:B))
  if ($fields) {
    foreach ($k as &$l) {
      if ('direct' == $parse_mode_id || strpos($l, '"') === 0 || strpos($l, '(') !== 0 && strpos($l, '+') !== 0 && strpos($l, '-') !== 0 && !preg_match('/^[^:]+(?<!\\\\):/', $l)) {
        $v = [];
        foreach ($fields as $f) {
          if (strpos($f, '^') !== FALSE) {
            list($field, $boost) = explode('^', $f);
            $v[] = $field . ':' . $l . '^' . $boost;
          }
          else {
            $v[] = $f . ':' . $l;
          }
        }
        if (count($v) > 1) {
          $l = '(' . implode(' ', $v) . ')';
        }
        else {
          $l = reset($v);
        }
      }
    }
  }
  if (count($k) == 1) {
    return $neg . reset($k);
  }
  foreach ($k as &$j) {
    if (strpos($j, '-') !== 0) {
      $j = $pre . $j;
    }
  }
  return $neg . '(' . implode(' ', $k) . ')';
}