diff --git a/core/modules/views/src/Plugin/views/filter/NumericFilter.php b/core/modules/views/src/Plugin/views/filter/NumericFilter.php index d2a6ab099718f7d699924f56dfb0a9d3a50cc79f..e82c46fcaaf423ade19e36b2a68658b1cc9af5c2 100644 --- a/core/modules/views/src/Plugin/views/filter/NumericFilter.php +++ b/core/modules/views/src/Plugin/views/filter/NumericFilter.php @@ -316,12 +316,24 @@ public function query() { } } + /** + * Filters by operator between. + * + * @param object $field + * The views field. + */ protected function opBetween($field) { - if ($this->operator == 'between') { - $this->query->addWhere($this->options['group'], $field, [$this->value['min'], $this->value['max']], 'BETWEEN'); + if (is_numeric($this->value['min']) && is_numeric($this->value['max'])) { + $operator = $this->operator == 'between' ? 'BETWEEN' : 'NOT BETWEEN'; + $this->query->addWhere($this->options['group'], $field, [$this->value['min'], $this->value['max']], $operator); } - else { - $this->query->addWhere($this->options['group'], $field, [$this->value['min'], $this->value['max']], 'NOT BETWEEN'); + elseif (is_numeric($this->value['min'])) { + $operator = $this->operator == 'between' ? '>=' : '<'; + $this->query->addWhere($this->options['group'], $field, $this->value['min'], $operator); + } + elseif (is_numeric($this->value['max'])) { + $operator = $this->operator == 'between' ? '<=' : '>'; + $this->query->addWhere($this->options['group'], $field, $this->value['max'], $operator); } } diff --git a/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php b/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php index e1093e47f7c2757ec660b03f8916a7f75b561222..bc135bb85b8eb540e68324dec3c9151eb2713b6c 100644 --- a/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php +++ b/core/modules/views/tests/src/Kernel/Handler/FilterNumericTest.php @@ -87,73 +87,107 @@ public function testFilterNumericExposedGroupedSimple() { $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } - public function testFilterNumericBetween() { + /** + * Tests the between operator. + * + * @param string $operator + * The operator to test ('between' or 'not between'). + * @param string $min + * The min value. + * @param string $max + * The max value. + * @param array $expected_result + * The expected results. + * + * @dataProvider providerTestFilterNumericBetween + */ + public function testFilterNumericBetween($operator, $min, $max, array $expected_result) { $view = Views::getView('test_view'); $view->setDisplay(); - // Change the filtering $view->displayHandlers->get('default')->overrideOption('filters', [ 'age' => [ 'id' => 'age', 'table' => 'views_test_data', 'field' => 'age', 'relationship' => 'none', - 'operator' => 'between', + 'operator' => $operator, 'value' => [ - 'min' => 26, - 'max' => 29, + 'min' => $min, + 'max' => $max, ], ], ]); $this->executeView($view); - $resultset = [ - [ - 'name' => 'George', - 'age' => 27, + $this->assertIdenticalResultset($view, $expected_result, $this->columnMap); + } + + /** + * Provides data for self::testFilterNumericBetween(). + * + * @return array + * An array of arrays, each containing the parameters for + * self::testFilterNumericBetween(). + */ + public function providerTestFilterNumericBetween() { + $all_result = [ + ['name' => 'John', 'age' => 25], + ['name' => 'George', 'age' => 27], + ['name' => 'Ringo', 'age' => 28], + ['name' => 'Paul', 'age' => 26], + ['name' => 'Meredith', 'age' => 30], + ]; + + return [ + // Each test case is operator, min, max, expected result. + 'Test between' => [ + 'between', 26, 29, [ + ['name' => 'George', 'age' => 27], + ['name' => 'Ringo', 'age' => 28], + ['name' => 'Paul', 'age' => 26], + ], ], - [ - 'name' => 'Ringo', - 'age' => 28, + 'Test between with just min' => [ + 'between', 28, '', [ + ['name' => 'Ringo', 'age' => 28], + ['name' => 'Meredith', 'age' => 30], + ], ], - [ - 'name' => 'Paul', - 'age' => 26, + 'Test between with just max' => [ + 'between', '', 26, + [ + ['name' => 'John', 'age' => 25], + ['name' => 'Paul', 'age' => 26], + ], ], - ]; - $this->assertIdenticalResultset($view, $resultset, $this->columnMap); - - // test not between - $view->destroy(); - $view->setDisplay(); - - // Change the filtering - $view->displayHandlers->get('default')->overrideOption('filters', [ - 'age' => [ - 'id' => 'age', - 'table' => 'views_test_data', - 'field' => 'age', - 'relationship' => 'none', - 'operator' => 'not between', - 'value' => [ - 'min' => 26, - 'max' => 29, + 'Test between with empty min and max' => [ + 'between', '', '', $all_result, + ], + 'Test not between' => [ + 'not between', 26, 29, [ + ['name' => 'John', 'age' => 25], + ['name' => 'Meredith', 'age' => 30], ], ], - ]); - - $this->executeView($view); - $resultset = [ - [ - 'name' => 'John', - 'age' => 25, + 'Test not between with just min' => [ + 'not between', 28, '', [ + ['name' => 'John', 'age' => 25], + ['name' => 'George', 'age' => 27], + ['name' => 'Paul', 'age' => 26], + ], ], - [ - 'name' => 'Meredith', - 'age' => 30, + 'Test not between with just max' => [ + 'not between', '', 26, [ + ['name' => 'George', 'age' => 27], + ['name' => 'Ringo', 'age' => 28], + ['name' => 'Meredith', 'age' => 30], + ], + ], + 'Test not between with empty min and max' => [ + 'not between', '', '', $all_result, ], ]; - $this->assertIdenticalResultset($view, $resultset, $this->columnMap); } public function testFilterNumericExposedGroupedBetween() {