Skip to content

Commit e76e17f

Browse files
author
Mantas Urnieža
committed
Merge pull request #98 from GrandLTU/inclusive-range-filter
Inclusive range filter
2 parents eef2438 + a0358a2 commit e76e17f

File tree

10 files changed

+171
-85
lines changed

10 files changed

+171
-85
lines changed

DependencyInjection/Configuration.php

+10
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,16 @@ function ($v) {
238238
->end()
239239
->end();
240240
break;
241+
case 'range':
242+
case 'date_range':
243+
$node
244+
->children()
245+
->booleanNode('inclusive')
246+
->info('Whether filter should match range ends.')
247+
->defaultFalse()
248+
->end()
249+
->end();
250+
break;
241251
default:
242252
// Should not happen.
243253
break;

DependencyInjection/Filter/RangeFilterFactory.php

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ protected function configure(Definition $definition, array $configuration)
2626
parent::configure($definition, $configuration);
2727

2828
$definition->addMethodCall('setField', [$configuration['field']]);
29+
if (array_key_exists('inclusive', $configuration)) {
30+
$definition->addMethodCall('setInclusive', [$configuration['inclusive']]);
31+
}
2932
}
3033

3134
/**
+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the ONGR package.
5+
*
6+
* (c) NFQ Technologies UAB <info@nfq.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace ONGR\FilterManagerBundle\Filters\Widget\Range;
13+
14+
use ONGR\ElasticsearchBundle\DSL\Filter\RangeFilter;
15+
use ONGR\ElasticsearchBundle\DSL\Search;
16+
use ONGR\FilterManagerBundle\Filters\FilterState;
17+
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareInterface;
18+
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareTrait;
19+
use ONGR\FilterManagerBundle\Filters\Helper\ViewDataFactoryInterface;
20+
use ONGR\FilterManagerBundle\Filters\ViewData\RangeAwareViewData;
21+
use ONGR\FilterManagerBundle\Filters\Widget\AbstractSingleRequestValueFilter;
22+
use ONGR\FilterManagerBundle\Search\SearchRequest;
23+
24+
/**
25+
* Class AbstractRangeFilter.
26+
*/
27+
abstract class AbstractRange extends AbstractSingleRequestValueFilter implements
28+
FieldAwareInterface,
29+
ViewDataFactoryInterface
30+
{
31+
use FieldAwareTrait;
32+
33+
/**
34+
* @var bool
35+
*/
36+
private $inclusive = false;
37+
38+
/**
39+
* @param bool $inclusive
40+
*
41+
* @return $this
42+
*/
43+
public function setInclusive($inclusive)
44+
{
45+
$this->inclusive = $inclusive;
46+
47+
return $this;
48+
}
49+
50+
/**
51+
* @return bool
52+
*/
53+
public function isInclusive()
54+
{
55+
return $this->inclusive;
56+
}
57+
58+
/**
59+
* {@inheritdoc}
60+
*/
61+
public function createViewData()
62+
{
63+
return new RangeAwareViewData();
64+
}
65+
66+
/**
67+
* {@inheritdoc}
68+
*/
69+
public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
70+
{
71+
if ($state && $state->isActive()) {
72+
$filter = new RangeFilter($this->getField(), $state->getValue());
73+
$search->addPostFilter($filter);
74+
}
75+
}
76+
}

Filters/Widget/Range/DateRange.php

+8-31
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,18 @@
1212
namespace ONGR\FilterManagerBundle\Filters\Widget\Range;
1313

1414
use ONGR\ElasticsearchBundle\DSL\Aggregation\StatsAggregation;
15-
use ONGR\ElasticsearchBundle\DSL\Filter\RangeFilter;
1615
use ONGR\ElasticsearchBundle\DSL\Search;
1716
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
1817
use ONGR\FilterManagerBundle\Filters\FilterState;
19-
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareInterface;
20-
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareTrait;
21-
use ONGR\FilterManagerBundle\Filters\Helper\ViewDataFactoryInterface;
2218
use ONGR\FilterManagerBundle\Filters\ViewData;
23-
use ONGR\FilterManagerBundle\Filters\Widget\AbstractSingleRequestValueFilter;
24-
use ONGR\FilterManagerBundle\Search\SearchRequest;
19+
use ONGR\FilterManagerBundle\Filters\ViewData\RangeAwareViewData;
2520
use Symfony\Component\HttpFoundation\Request;
2621

2722
/**
2823
* Date range filter, selects documents from lower date to upper date.
2924
*/
30-
class DateRange extends AbstractSingleRequestValueFilter implements FieldAwareInterface, ViewDataFactoryInterface
25+
class DateRange extends AbstractRange
3126
{
32-
use FieldAwareTrait;
33-
3427
/**
3528
* {@inheritdoc}
3629
*/
@@ -40,8 +33,11 @@ public function getState(Request $request)
4033

4134
if ($state->getValue()) {
4235
$values = explode(';', $state->getValue(), 2);
43-
$normalized['gt'] = $values[0];
44-
$normalized['lt'] = $values[1];
36+
$gt = $this->isInclusive() ? 'gte' : 'gt';
37+
$lt = $this->isInclusive() ? 'lte' : 'lt';
38+
39+
$normalized[$gt] = $values[0];
40+
$normalized[$lt] = $values[1];
4541

4642
$state->setValue($normalized);
4743
}
@@ -59,31 +55,12 @@ public function preProcessSearch(Search $search, Search $relatedSearch, FilterSt
5955
$search->addAggregation($stateAgg);
6056
}
6157

62-
/**
63-
* {@inheritdoc}
64-
*/
65-
public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
66-
{
67-
if ($state && $state->isActive()) {
68-
$filter = new RangeFilter($this->getField(), $state->getValue());
69-
$search->addPostFilter($filter);
70-
}
71-
}
72-
73-
/**
74-
* {@inheritdoc}
75-
*/
76-
public function createViewData()
77-
{
78-
return new ViewData\RangeAwareViewData();
79-
}
80-
8158
/**
8259
* {@inheritdoc}
8360
*/
8461
public function getViewData(DocumentIterator $result, ViewData $data)
8562
{
86-
/** @var $data ViewData\RangeAwareViewData */
63+
/** @var $data RangeAwareViewData */
8764
$data->setMinBounds(
8865
new \DateTime(
8966
date(

Filters/Widget/Range/Range.php

+6-30
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,17 @@
1212
namespace ONGR\FilterManagerBundle\Filters\Widget\Range;
1313

1414
use ONGR\ElasticsearchBundle\DSL\Aggregation\StatsAggregation;
15-
use ONGR\ElasticsearchBundle\DSL\Filter\RangeFilter;
1615
use ONGR\ElasticsearchBundle\DSL\Search;
1716
use ONGR\ElasticsearchBundle\Result\DocumentIterator;
1817
use ONGR\FilterManagerBundle\Filters\FilterState;
19-
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareInterface;
20-
use ONGR\FilterManagerBundle\Filters\Helper\FieldAwareTrait;
21-
use ONGR\FilterManagerBundle\Filters\Helper\ViewDataFactoryInterface;
2218
use ONGR\FilterManagerBundle\Filters\ViewData;
23-
use ONGR\FilterManagerBundle\Filters\Widget\AbstractSingleRequestValueFilter;
24-
use ONGR\FilterManagerBundle\Search\SearchRequest;
2519
use Symfony\Component\HttpFoundation\Request;
2620

2721
/**
2822
* Range filter, selects documents from lower limit to upper limit.
2923
*/
30-
class Range extends AbstractSingleRequestValueFilter implements FieldAwareInterface, ViewDataFactoryInterface
24+
class Range extends AbstractRange
3125
{
32-
use FieldAwareTrait;
33-
3426
/**
3527
* {@inheritdoc}
3628
*/
@@ -50,25 +42,17 @@ public function getState(Request $request)
5042
return $state;
5143
}
5244

53-
$normalized['gt'] = floatval($values[0]);
54-
$normalized['lt'] = floatval($values[1]);
45+
$gt = $this->isInclusive() ? 'gte' : 'gt';
46+
$lt = $this->isInclusive() ? 'lte' : 'lt';
47+
48+
$normalized[$gt] = floatval($values[0]);
49+
$normalized[$lt] = floatval($values[1]);
5550

5651
$state->setValue($normalized);
5752

5853
return $state;
5954
}
6055

61-
/**
62-
* {@inheritdoc}
63-
*/
64-
public function modifySearch(Search $search, FilterState $state = null, SearchRequest $request = null)
65-
{
66-
if ($state && $state->isActive()) {
67-
$filter = new RangeFilter($this->getField(), $state->getValue());
68-
$search->addPostFilter($filter);
69-
}
70-
}
71-
7256
/**
7357
* {@inheritdoc}
7458
*/
@@ -79,14 +63,6 @@ public function preProcessSearch(Search $search, Search $relatedSearch, FilterSt
7963
$search->addAggregation($stateAgg);
8064
}
8165

82-
/**
83-
* {@inheritdoc}
84-
*/
85-
public function createViewData()
86-
{
87-
return new ViewData\RangeAwareViewData();
88-
}
89-
9066
/**
9167
* {@inheritdoc}
9268
*/

Search/FiltersContainer.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function buildSearchRequest(Request $request)
8383
* @param SearchRequest $request
8484
* @param FilterInterface[]|null $filters
8585
*
86-
* @return \ElasticsearchBundle\DSL\Search
86+
* @return Search
8787
*/
8888
public function buildSearch(SearchRequest $request, $filters = null)
8989
{

Tests/Functional/DependencyInjection/Compiler/FilterPassTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public function filterTestProvider()
5151
'filters' => [
5252
'bar_range' => $fooRangeClass,
5353
'sort' => 'ONGR\FilterManagerBundle\Filters\Widget\Sort\Sort',
54+
'inclusive_range' => 'ONGR\FilterManagerBundle\Filters\Widget\Range\Range',
5455
],
5556
],
5657
// Case #1. foo_filters.

Tests/Functional/Filters/Widget/Range/RangeTest.php

+59-20
Original file line numberDiff line numberDiff line change
@@ -76,45 +76,78 @@ public function getTestResultsData()
7676
$managers = $this->getFilterManager();
7777
// Case #0 range includes everything.
7878
$out[] = [
79-
new Request(['range' => '0;50', 'sort' => '0', 'mode' => null]),
80-
['1', '2', '3', '4', '5'],
81-
true,
82-
$managers,
79+
'request' => new Request(['range' => '0;50', 'sort' => '0', 'mode' => null]),
80+
'ids' => ['1', '2', '3', '4', '5'],
81+
'assertOrder' => true,
82+
'managers' => $managers,
8383
];
8484

8585
// Case #1 two elements.
86-
$out[] = [new Request(['range' => '1;4', 'sort' => '0', 'mode' => null]), ['2', '3'], true, $managers];
86+
$out[] = [
87+
'request' => new Request(['range' => '1;4', 'sort' => '0', 'mode' => null]),
88+
'ids' => ['2', '3'],
89+
'assertOrder' => true,
90+
'managers' => $managers,
91+
];
8792

8893
// Case #2 no elements.
89-
$out[] = [new Request(['range' => '2;3', 'sort' => '0', 'mode' => null]), [], true, $managers];
94+
$out[] = [
95+
'request' => new Request(['range' => '2;3', 'sort' => '0', 'mode' => null]),
96+
'ids' => [],
97+
'assertOrder' => true,
98+
'managers' => $managers,
99+
];
90100

91101
// Case #3 invalid range specified.
92102
$out[] = [
93-
new Request(['range' => '2', 'sort' => '0', 'mode' => null]),
103+
'request' => new Request(['range' => '2', 'sort' => '0', 'mode' => null]),
104+
'ids' => ['1', '2', '3', '4', '5'],
105+
'assertOrder' => true,
106+
'managers' => $managers,
107+
];
108+
109+
// Case #4 no range specified.
110+
$out[] = [
111+
new Request(['sort' => '0', 'mode' => null]),
94112
['1', '2', '3', '4', '5'],
95113
true,
96114
$managers,
97115
];
98116

99-
// Case #4 no range specified.
100-
$out[] = [new Request(['sort' => '0', 'mode' => null]), ['1', '2', '3', '4', '5'], true, $managers];
101-
102117
// Case #5 test with float shouldn't list anything.
103-
$out[] = [new Request(['range' => '4.3;50', 'sort' => '0', 'mode' => null]), [], true, $managers];
118+
$out[] = [
119+
'request' => new Request(['range' => '4.3;50', 'sort' => '0', 'mode' => null]),
120+
'ids' => [],
121+
'assertOrder' => true,
122+
'managers' => $managers,
123+
];
104124

105125
// Case #6 test with float should list.
106-
$out[] = [new Request(['range' => '4.1;50', 'sort' => '0', 'mode' => null]), ['5'], true, $managers];
126+
$out[] = [
127+
'request' => new Request(['range' => '4.1;50', 'sort' => '0', 'mode' => null]),
128+
'ids' => ['5'],
129+
'assertOrder' => true,
130+
'managers' => $managers,
131+
];
132+
133+
// Case #7 Inclusive filter.
134+
$out[] = [
135+
'request' => new Request(['inclusive_range' => '1;2', 'sort' => '0', 'mode' => null]),
136+
'ids' => ['1', '2'],
137+
'assertOrder' => true,
138+
'managers' => $managers,
139+
];
107140

108141
return $out;
109142
}
110143

111144
/**
112145
* Check if view data returned is correct.
113146
*
114-
* @param Request $request Http request.
115-
* @param array $ids Array of document ids to assert.
116-
* @param bool $assertOrder Set true if order of results lso should be asserted.
117-
* @param array $managers Set of filter managers to test.
147+
* @param Request $request Http request.
148+
* @param array $ids Array of document ids to assert.
149+
* @param bool $assertOrder Set true if order of results lso should be asserted.
150+
* @param FiltersManager[] $managers Set of filter managers to test.
118151
*
119152
* @dataProvider getTestResultsData()
120153
*/
@@ -149,6 +182,12 @@ protected function getFilterManager()
149182
$filter->setField('price');
150183
$container->set('range', $filter);
151184

185+
$filter = new Range();
186+
$filter->setRequestField('inclusive_range');
187+
$filter->setField('price');
188+
$filter->setInclusive(true);
189+
$container->set('inclusive_range', $filter);
190+
152191
$sort = new Sort();
153192
$sort->setRequestField('sort');
154193
$sort->setChoices($choices);
@@ -167,10 +206,10 @@ protected function getFilterManager()
167206
/**
168207
* This method asserts if search request gives expected results.
169208
*
170-
* @param Request $request Http request.
171-
* @param array $ids Array of document ids to assert.
172-
* @param bool $assertOrder Set true if order of results lso should be asserted.
173-
* @param array $managers Set of filter managers to test.
209+
* @param Request $request Http request.
210+
* @param array $ids Array of document ids to assert.
211+
* @param bool $assertOrder Set true if order of results lso should be asserted.
212+
* @param FiltersManager[] $managers Set of filter managers to test.
174213
*
175214
* @dataProvider getTestResultsData()
176215
*/

0 commit comments

Comments
 (0)