You are here

QueryTypeRangeBase.php in Facets 8

File

src/QueryType/QueryTypeRangeBase.php
View source
<?php

namespace Drupal\facets\QueryType;

use Drupal\facets\Result\Result;

/**
 * A base class for query type plugins adding range.
 */
abstract class QueryTypeRangeBase extends QueryTypePluginBase {

  /**
   * {@inheritdoc}
   */
  public function execute() {
    $query = $this->query;

    // Alter the query here.
    if (!empty($query)) {
      $options =& $query
        ->getOptions();
      $operator = $this->facet
        ->getQueryOperator();
      $field_identifier = $this->facet
        ->getFieldIdentifier();
      $exclude = $this->facet
        ->getExclude();
      $options['search_api_facets'][$field_identifier] = $this
        ->getFacetOptions();

      // Add the filter to the query if there are active values.
      $active_items = $this->facet
        ->getActiveItems();
      $filter = $query
        ->createConditionGroup($operator, [
        'facet:' . $field_identifier,
      ]);
      if (count($active_items)) {
        foreach ($active_items as $value) {
          $range = $this
            ->calculateRange($value);
          $conjunction = $exclude ? 'OR' : 'AND';
          $item_filter = $query
            ->createConditionGroup($conjunction, [
            'facet:' . $field_identifier,
          ]);
          $item_filter
            ->addCondition($this->facet
            ->getFieldIdentifier(), $range['start'], $exclude ? '<' : '>=');
          $item_filter
            ->addCondition($this->facet
            ->getFieldIdentifier(), $range['stop'], $exclude ? '>' : '<=');
          $filter
            ->addConditionGroup($item_filter);
        }
        $query
          ->addConditionGroup($filter);
      }
    }
  }

  /**
   * Calculate the range for a given facet filter value.
   *
   * Used when adding active items in self::execute() to $this->query to include
   * the range conditions for the value.
   *
   * @param string $value
   *   The raw value for the facet filter.
   *
   * @return array
   *   Keyed with 'start' and 'stop' values.
   */
  public abstract function calculateRange($value);

  /**
   * {@inheritdoc}
   */
  public function build() {

    // If there were no results or no query object, we can't do anything.
    if (empty($this->results)) {
      return $this->facet;
    }
    $query_operator = $this->facet
      ->getQueryOperator();
    $facet_results = [];
    foreach ($this->results as $result) {

      // Go through the results and add facet results grouped by filters
      // defined by self::calculateResultFilter().
      if ($result['count'] || $query_operator == 'or') {
        $count = $result['count'];
        if ($result_filter = $this
          ->calculateResultFilter(trim($result['filter'], '"'))) {
          if (isset($facet_results[$result_filter['raw']])) {
            $facet_results[$result_filter['raw']]
              ->setCount($facet_results[$result_filter['raw']]
              ->getCount() + $count);
          }
          else {
            $facet_results[$result_filter['raw']] = new Result($this->facet, $result_filter['raw'], $result_filter['display'], $count);
          }
        }
      }
    }
    $this->facet
      ->setResults($facet_results);
    return $this->facet;
  }

  /**
   * Calculate the grouped facet filter for a given value.
   *
   * @param string $value
   *   The raw value for the facet before grouping.
   *
   * @return array
   *   Keyed by 'display' value to be shown to the user, and 'raw' to be used
   *   for the url.
   */
  public abstract function calculateResultFilter($value);

}

Classes

Namesort descending Description
QueryTypeRangeBase A base class for query type plugins adding range.