You are here

function search_api_ranges_minmax in Search API ranges 7

Find the lowest/highest valuse for the active facets

Parameters

array $variables: An array with at least the following keys => values:

  • (string) range_field: the name of the slider range field
  • (array) query: the Search API query object

string $order: Either ASC (for min) or DESC (for max)

Return value

string|null The rounded integer value for min/max, or NULL.

1 call to search_api_ranges_minmax()
SearchApiRangesWidgetUISlider::_buildUISliderForm in plugins/facetapi/widget_slider.inc
Builds a UI slider themed form. Performs min/max queries through Search API.

File

./search_api_ranges.module, line 101
Performs min/max queries through Search API and provides UI Slider display widget for Facet API

Code

function search_api_ranges_minmax($variables, $order = 'ASC') {

  // Allow the other modules to modify the query parameters.
  drupal_alter('search_api_ranges_minmax', $variables, $order);

  // If query is empty, ignore sending the query.
  // This allows other modules to decide
  // whenever we want to perform the query.
  if (empty($variables['query'])) {
    return isset($variables['result']) ? $variables['result'] : NULL;
  }

  /** @var SearchApiQuery $query */
  $query = $variables['query'];

  /** @var SearchApiIndex $index */
  $index = $variables['index'];
  $order_lower = strtolower($order);

  // Generate a facet tag using the base field.
  $tag = 'facet:' . $variables['range_field'];

  // Check if min or max values are indexed for multiple fields.
  if (search_api_is_list_type($index->options['fields'][$variables['range_field']]['type'])) {
    $field_name = str_replace(':', '_', $variables['range_field']) . '_' . $order_lower;
    if (isset($index->options['fields'][$field_name])) {
      $variables['range_field'] = $field_name;
    }
  }

  // Alter sort.
  $sort =& $query
    ->getSort();
  $sort = array(
    $variables['range_field'] => $order,
  );

  // Alter options.
  $options =& $query
    ->getOptions();
  $options['limit'] = 1;
  $options['search id'] = 'search_api_ranges:' . $variables['range_field'] . ':minmax/' . $order;

  // For performance, we don't need to return any facets.
  $options['search_api_facets'] = array();

  // Do not take into account pager query.
  $options['offset'] = 0;

  // Set some metadata to allow modules to alter based on that information.
  $query
    ->setOption('search_api_ranges', array(
    'range_field' => $variables['range_field'],
  ));

  // Remove current range field from the filters
  // otherwise our min/max would always equal user input.
  $filters =& $query
    ->getFilter()
    ->getFilters();
  foreach ($filters as $key => $filter) {
    if (isset($filter->tags) && is_array($filter->tags) && in_array($tag, $filter->tags)) {
      unset($filters[$key]);
    }
  }

  // Filter out results with no values for that field.
  $query
    ->condition($variables['range_field'], NULL, '<>');

  // Execute the query and process results.
  $results = search_api_ranges_minmax_execute($query);
  foreach ($filters as $key => $filter) {

    // Remove $query->condition($variables['range_field'], NULL, '<>'); to prevent this condition influence on other facets
    if (is_array($filter)) {
      if ($filter[0] == $variables['range_field']) {
        unset($filters[$key]);
      }
    }
  }

  // Return current filter with digital ranges to the query
  if (isset($current_filter) && is_array($current_filter)) {
    if ($current_filter[1] != NULL && $current_filter[2] != '<>') {
      $query
        ->condition($variables['range_field'], $current_filter[1], $current_filter[2]);
    }
    if ($current_filter[1] != NULL && $current_filter[2] != '<>') {
      $query
        ->condition($variables['range_field'], $current_filter[1], $current_filter[2]);
    }
  }
  if (!$results['results']) {
    return NULL;
  }
  $result_ids = array();
  foreach ($results['results'] as $result) {

    // Support search_api_et module (multilingual indexes)
    if (strpos($index->item_type, 'search_api_et_') !== FALSE) {

      // search_api_et prefixes the entity id with a language code, so we'll
      // just remove any non-numeric characters to get the entity id
      $result_ids[] = preg_replace('/[^0-9]/', '', $result['id']);
    }
    else {
      $result_ids[] = $result['id'];
    }
  }
  $entities = entity_load($index
    ->getEntityType(), $result_ids);
  $index
    ->dataAlter($entities);
  $orphan_ids = array();
  foreach ($result_ids as $id) {
    if (!isset($entities[$id])) {
      $orphan_ids[] = $id;
    }
    else {
      $entity = $entities[$id];
      $wrapper = $index
        ->entityWrapper($entity);
    }
  }
  if (!empty($orphan_ids)) {
    $warning = t('Orphan ids detected in search index: @orphan_ids.' . "\n" . 'Re-indexing is recommended.', array(
      '@orphan_ids' => implode(', ', $orphan_ids),
    ));
    drupal_set_message($warning, 'warning');
  }
  if (!isset($wrapper)) {
    return NULL;
  }
  $fields[$variables['range_field']]['type'] = 'integer';
  $round_precision = isset($variables['round-precision']) ? $variables['round-precision'] : 0;
  if ($round_precision == 0) {
    $fields[$variables['range_field']]['type'] = 'integer';
  }
  else {
    $fields[$variables['range_field']]['type'] = 'float';
  }
  $fields = search_api_extract_fields($wrapper, $fields);

  // We have to round because jQuery slider cannot handle decimals.
  $return = $fields[$variables['range_field']]['value'];
  switch ($order) {
    case 'DESC':
      if ($round_precision == 0) {
        $return = ceil($return);
      }
      elseif ($round_precision > 0) {
        $return = round($return, $round_precision, PHP_ROUND_HALF_UP);
      }
      break;
    default:
      if ($round_precision == 0) {
        $return = floor($return);
      }
      elseif ($round_precision > 0) {
        $return = round($return, $round_precision, PHP_ROUND_HALF_DOWN);
      }
  }
  return $return;
}