You are here

public function CoreViewsFacetsFilterType::prepareQuery in Core Views Facets 8

Alters the facet query before execution.

Parameters

\Drupal\views\ViewExecutable $view: The views executable the facet applies to.

\Drupal\views\Plugin\views\HandlerBase $handler: The loaded views contextual filter handler.

\Drupal\facets\FacetInterface $facet: The facet being executed.

Return value

null|\Drupal\Core\Database\Query\Select The altered query object to be executed.

Overrides CoreViewsFacetsFilterTypeInterface::prepareQuery

3 calls to CoreViewsFacetsFilterType::prepareQuery()
Boolean::prepareQuery in src/Plugin/facets/processor/exposed_filter_type/Boolean.php
Alters the facet query before execution.
Generic::prepareQuery in src/Plugin/facets/processor/contextual_filter_type/Generic.php
Alters the facet query before execution.
Generic::prepareQuery in src/Plugin/facets/processor/exposed_filter_type/Generic.php
Alters the facet query before execution.
3 methods override CoreViewsFacetsFilterType::prepareQuery()
Boolean::prepareQuery in src/Plugin/facets/processor/exposed_filter_type/Boolean.php
Alters the facet query before execution.
Generic::prepareQuery in src/Plugin/facets/processor/contextual_filter_type/Generic.php
Alters the facet query before execution.
Generic::prepareQuery in src/Plugin/facets/processor/exposed_filter_type/Generic.php
Alters the facet query before execution.

File

src/CoreViewsFacetsFilterType.php, line 78

Class

CoreViewsFacetsFilterType
Base class for Core views facets filter type plugins.

Namespace

Drupal\core_views_facets

Code

public function prepareQuery(ViewExecutable $view, HandlerBase $handler, FacetInterface $facet) {
  $filter_table_alias = [];
  $relationship = NULL;
  if (!empty($handler->options['relationship']) && $handler->options['relationship'] !== 'none') {

    /** @var \Drupal\views\Plugin\views\relationship\RelationshipPluginBase $relationship_handler */
    $relationship_handler = $view
      ->getDisplay()
      ->getHandler('relationship', $handler->options['relationship']);
    if ($relationship_handler) {
      $relationship = $relationship_handler->alias;
    }
  }

  /** @var \Drupal\views\Plugin\views\query\Sql $view_query */
  $view_query = $view->query;
  $filter_table_alias[] = $view_query
    ->ensureTable($handler->table, $relationship);

  /** @var \Drupal\Core\Database\Query\Select $query */
  $query = $view_query
    ->query();

  // The countQuery() method removes everything from the query, that doesn't
  // alter the result count. Such as all the SELECT x,y,z stuff and LEFT joins
  // not in the where clause etc.
  // The countQuery itself though, only counts the whole view, so it's not
  // useful as such, but the subquery can be combined with the facet
  // conditions.
  $query = $query
    ->countQuery();

  // The better alternative $query->prepareCountQuery() is protected, so work
  // around it.
  $query = $query
    ->getTables()['subquery']['table'];
  $select_table_alias = $filter_table_alias[0];
  $select_field = $handler->realField;
  $query
    ->addField($select_table_alias, $select_field, 'facetrawvalue');
  $fields =& $query
    ->getFields();
  $expressions =& $query
    ->getExpressions();

  // Make sure to only group by facetrawvalue.
  $group_by =& $query
    ->getGroupBy();
  foreach ($group_by as $alias => $group_entry) {
    unset($fields[$alias], $expressions[$alias]);
  }
  $group_by = [];
  $query
    ->groupBy('facetrawvalue');

  // Remove unnecessary orders.
  $orders =& $query
    ->getOrderBy();
  foreach ($orders as $alias => $order) {
    unset($fields[$alias], $expressions[$alias]);
  }
  $orders = [];
  $query
    ->addExpression('COUNT(DISTINCT ' . $view->storage
    ->get('base_table') . '.' . $view->storage
    ->get('base_field') . ')', 'facetcount');
  if (!empty($facet
    ->getHardLimit())) {
    $query
      ->orderBy('facetcount', 'DESC');
    $query
      ->range(0, $facet
      ->getHardLimit());
  }

  // The INNER JOIN should reduce the result set to only the actually
  // available facet values. So we're overriding the default LEFT JOIN.
  foreach ($filter_table_alias as $alias) {
    $tables =& $query
      ->getTables();
    if (!empty($tables[$alias]['join type'])) {
      $tables[$alias]['join type'] = 'INNER';
    }
  }
  return $query;
}