You are here

protected function SearchApiSolrService::extractFacets in Search API Solr 7

Extract facets from a Solr response.

Parameters

object $response: A response object from SolrPhpClient.

Return value

array An array describing facets that apply to the current results.

1 call to SearchApiSolrService::extractFacets()
SearchApiSolrService::search in includes/service.inc
Executes a search on the server represented by this object.

File

includes/service.inc, line 1644

Class

SearchApiSolrService
Search service class using Solr server.

Code

protected function extractFacets(SearchApiQueryInterface $query, $response) {
  $facets = array();
  if (!isset($response->facet_counts)) {
    return $facets;
  }
  $index = $query
    ->getIndex();
  $fields = $this
    ->getFieldNames($index);
  $extract_facets = $query
    ->getOption('search_api_facets', array());
  $facet_fields = array();
  $facet_queries = array();
  if (isset($response->facet_counts->facet_fields)) {
    $facet_fields = $response->facet_counts->facet_fields;
  }
  if (isset($response->facet_counts->facet_queries)) {
    $facet_queries = $response->facet_counts->facet_queries;
  }

  // The key for the "missing" facet (empty string in the JSON). This will
  // be either "" or "_empty_", depending on the PHP version.
  $empty_key = key((array) json_decode('{"":5}'));
  foreach ($extract_facets as $delta => $info) {
    $field = $fields[$info['field']];

    // Fields that have solr facet queries set need special handling.
    if (!empty($info['solr_facet_query'])) {
      if (!empty($facet_queries)) {
        foreach ($facet_queries as $term => $count) {

          // Strip a leading local param so we can correctly detect the
          // field. E.g. "{!ex=...}" might have been set in getFacetParams()
          // for OR facets.
          $term = preg_replace('/^{[^}]+}/', '', $term);
          if (strpos($term, $field . ':') === 0) {
            $term = substr($term, strlen($field) + 1);
            if (!preg_match('/^(?:[(\\[][^ ]+ .*[)\\]]|".*"|!)$/', $term)) {
              $term = "\"{$term}\"";
            }
            $facets[$delta][] = array(
              'filter' => $term,
              'count' => $count,
              'solr_facet_query' => TRUE,
            );
          }
        }
      }
    }
    elseif (!empty($facet_fields->{$field})) {
      $min_count = $info['min_count'];
      $terms = $facet_fields->{$field};
      if ($info['missing']) {

        // We have to correctly incorporate the "missing" term ($empty_key).
        // This will ensure that the term with the least results is dropped,
        // if the limit would be exceeded.
        if (isset($terms->{$empty_key})) {
          if ($terms->{$empty_key} < $min_count) {
            unset($terms->{$empty_key});
          }
          else {
            $terms = (array) $terms;
            arsort($terms);
            if ($info['limit'] > 0 && count($terms) > $info['limit']) {
              array_pop($terms);
            }
          }
        }
      }
      elseif (isset($terms->{$empty_key})) {
        $terms = clone $terms;
        unset($terms->{$empty_key});
      }
      $type = isset($index->options['fields'][$info['field']]['type']) ? search_api_extract_inner_type($index->options['fields'][$info['field']]['type']) : 'string';
      foreach ($terms as $term => $count) {
        if ($count >= $min_count) {
          if ($term === $empty_key) {
            $term = '!';
          }
          elseif ($type == 'boolean') {
            if ($term == 'true') {
              $term = '"1"';
            }
            elseif ($term == 'false') {
              $term = '"0"';
            }
          }
          elseif ($type == 'date') {
            $term = $term ? '"' . strtotime($term) . '"' : NULL;
          }
          else {
            $term = "\"{$term}\"";
          }
          if ($term) {
            $facets[$delta][] = array(
              'filter' => $term,
              'count' => $count,
            );
          }
        }
      }
      if (empty($facets[$delta])) {
        unset($facets[$delta]);
      }
    }
  }
  if ($facet_queries && $query
    ->getOption('search_api_location')) {
    foreach ($facet_queries as $key => $count) {
      if (!preg_match('/^spatial-(.*)-(\\d+(?:\\.\\d+)?)$/', $key, $m)) {
        continue;
      }
      if (empty($extract_facets[$m[1]])) {
        continue;
      }
      $facet = $extract_facets[$m[1]];
      if ($count >= $facet['min_count']) {
        $facets[$m[1]][] = array(
          'filter' => "[* {$m[2]}]",
          'count' => $count,
        );
      }
    }
  }
  return $facets;
}