From 829f1685e8d57058995a6ff5425572eed917ca10 Mon Sep 17 00:00:00 2001 From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org> Date: Fri, 11 Dec 2015 22:42:36 +0000 Subject: [PATCH] Issue #2595169 by mikeker, claudiu.cristea: Operator 'Is not equal' of BooleanOperator doesn't work --- .../Plugin/views/filter/BooleanOperator.php | 53 +++++++++++++++---- .../Handler/FilterBooleanOperatorTest.php | 49 +++++++++++++++++ 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/core/modules/views/src/Plugin/views/filter/BooleanOperator.php b/core/modules/views/src/Plugin/views/filter/BooleanOperator.php index e936ac9ddbfc..a4cded4acd68 100644 --- a/core/modules/views/src/Plugin/views/filter/BooleanOperator.php +++ b/core/modules/views/src/Plugin/views/filter/BooleanOperator.php @@ -7,6 +7,7 @@ namespace Drupal\views\Plugin\views\filter; +use Drupal\Core\Database\Query\Condition; use Drupal\Core\Form\FormStateInterface; use Drupal\views\Plugin\views\display\DisplayPluginBase; use Drupal\views\ViewExecutable; @@ -31,6 +32,20 @@ */ class BooleanOperator extends FilterPluginBase { + /** + * The equal query operator. + * + * @var string + */ + const EQUAL = '='; + + /** + * The non equal query operator. + * + * @var string + */ + const NOT_EQUAL = '<>'; + // exposed filter options protected $alwaysMultiple = TRUE; // Don't display empty space where the operator would be. @@ -64,12 +79,14 @@ protected function operators() { 'method' => 'queryOpBoolean', 'short' => $this->t('='), 'values' => 1, + 'query_operator' => static::EQUAL, ), '!=' => array( 'title' => $this->t('Is not equal to'), 'method' => 'queryOpBoolean', 'short' => $this->t('!='), 'values' => 1, + 'query_operator' => static::NOT_EQUAL, ), ); } @@ -185,7 +202,7 @@ public function adminSummary() { // human-readable label based on the current value. The valueOptions // array is keyed with either 0 or 1, so if the current value is not // empty, use the label for 1, and if it's empty, use the label for 0. - return $this->valueOptions[!empty($this->value)]; + return $this->operator . ' ' . $this->valueOptions[!empty($this->value)]; } public function defaultExposeOptions() { @@ -204,7 +221,7 @@ public function query() { $info = $this->operators(); if (!empty($info[$this->operator]['method'])) { - call_user_func(array($this, $info[$this->operator]['method']), $field); + call_user_func(array($this, $info[$this->operator]['method']), $field, $info[$this->operator]['query_operator']); } } @@ -213,25 +230,41 @@ public function query() { * * @param string $field * The field name to add the where condition for. + * @param string $query_operator + * (optional) Either static::EQUAL or static::NOT_EQUAL. Defaults to + * static::EQUAL. */ - protected function queryOpBoolean($field) { + protected function queryOpBoolean($field, $query_operator = EQUAL) { if (empty($this->value)) { if ($this->accept_null) { - $or = db_or() - ->condition($field, 0, '=') - ->condition($field, NULL, 'IS NULL'); - $this->query->addWhere($this->options['group'], $or); + if ($query_operator == static::EQUAL) { + $condition = (new Condition('OR')) + ->condition($field, 0, $query_operator) + ->isNull($field); + } + else { + $condition = (new Condition('AND')) + ->condition($field, 0, $query_operator) + ->isNotNull($field); + } + $this->query->addWhere($this->options['group'], $condition); } else { - $this->query->addWhere($this->options['group'], $field, 0, '='); + $this->query->addWhere($this->options['group'], $field, 0, $query_operator); } } else { if (!empty($this->definition['use_equal'])) { - $this->query->addWhere($this->options['group'], $field, 1, '='); + // Forces an '=' operator instead of a '<>' for performance reasons. + if ($query_operator == static::EQUAL) { + $this->query->addWhere($this->options['group'], $field, 1, static::EQUAL); + } + else { + $this->query->addWhere($this->options['group'], $field, 0, static::EQUAL); + } } else { - $this->query->addWhere($this->options['group'], $field, 0, '<>'); + $this->query->addWhere($this->options['group'], $field, 1, $query_operator); } } } diff --git a/core/modules/views/src/Tests/Handler/FilterBooleanOperatorTest.php b/core/modules/views/src/Tests/Handler/FilterBooleanOperatorTest.php index 049d439dbe8f..7e6c3104a3a3 100644 --- a/core/modules/views/src/Tests/Handler/FilterBooleanOperatorTest.php +++ b/core/modules/views/src/Tests/Handler/FilterBooleanOperatorTest.php @@ -95,6 +95,30 @@ public function testFilterBooleanOperator() { $this->assertEqual(3, count($view->result)); $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); + + $view->destroy(); + $view->setDisplay(); + + // Testing the same scenario but using the reverse status and operation. + $view->displayHandlers->get('default')->overrideOption('filters', array( + 'status' => array( + 'id' => 'status', + 'field' => 'status', + 'table' => 'views_test_data', + 'value' => 0, + 'operator' => '!=', + ), + )); + $this->executeView($view); + + $expected_result = array( + array('id' => 1), + array('id' => 3), + array('id' => 5), + ); + + $this->assertEqual(3, count($view->result)); + $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); } /** @@ -133,6 +157,24 @@ public function testFilterGroupedExposed() { $this->assertEqual(2, count($view->result)); $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); + + $view->destroy(); + + // Expecting the same results as for ['status' => 1]. + $view->setExposedInput(['status' => 3]); + $view->setDisplay(); + $view->displayHandlers->get('default')->overrideOption('filters', $filters); + + $this->executeView($view); + + $expected_result = array( + array('id' => 1), + array('id' => 3), + array('id' => 5), + ); + + $this->assertEqual(3, count($view->result)); + $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); } /** @@ -169,6 +211,13 @@ protected function getGroupedExposedFilters() { 'operator' => '=', 'value' => '0', ), + // This group should return the same results as group 1, because it + // is the negation of group 2. + 3 => array( + 'title' => 'Active (reverse)', + 'operator' => '!=', + 'value' => '0', + ), ), ), ), -- GitLab