1
|
|
|
<?php |
2
|
|
|
namespace Netdudes\DataSourceryBundle\Tests\Query; |
3
|
|
|
|
4
|
|
|
use Netdudes\DataSourceryBundle\DataSource\Configuration\Field; |
5
|
|
|
use Netdudes\DataSourceryBundle\DataType\BooleanDataType; |
6
|
|
|
use Netdudes\DataSourceryBundle\DataType\DataTypeInterface; |
7
|
|
|
use Netdudes\DataSourceryBundle\DataType\DateDataType; |
8
|
|
|
use Netdudes\DataSourceryBundle\DataType\EntityDataType; |
9
|
|
|
use Netdudes\DataSourceryBundle\DataType\NumberDataType; |
10
|
|
|
use Netdudes\DataSourceryBundle\DataType\PercentDataType; |
11
|
|
|
use Netdudes\DataSourceryBundle\DataType\StringDataType; |
12
|
|
|
use Netdudes\DataSourceryBundle\Query\Filter; |
13
|
|
|
use Netdudes\DataSourceryBundle\Query\FilterCondition; |
14
|
|
|
use Netdudes\DataSourceryBundle\Query\SearchTextFilterReducer; |
15
|
|
|
|
16
|
|
|
class SearchTextFilterReducerTest extends \PHPUnit_Framework_TestCase |
17
|
|
|
{ |
18
|
|
|
public function testReducingDoesNotAffectFilterWithoutSearchTextFilterCondition() |
19
|
|
|
{ |
20
|
|
|
$fields = [ |
21
|
|
|
$this->buildField('Field1', new NumberDataType(), 'field1'), |
22
|
|
|
$this->buildField('Field2', new StringDataType(), 'field2'), |
23
|
|
|
$this->buildField('Field3', new DateDataType(), 'field3'), |
24
|
|
|
$this->buildField('Field4', new BooleanDataType(), 'field4'), |
25
|
|
|
]; |
26
|
|
|
|
27
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
28
|
|
|
$this->createFilterCondition('column_string', FilterCondition::METHOD_STRING_LIKE, 'test', false), |
29
|
|
|
$this->createFilterCondition('column_datetime', FilterCondition::METHOD_DATETIME_EQ, 'now', false), |
30
|
|
|
$this->createFilterCondition('column_numeric', FilterCondition::METHOD_NUMERIC_NEQ, 123, false), |
31
|
|
|
$this->createFilter(Filter::CONDITION_TYPE_AND, [ |
32
|
|
|
$this->createFilterCondition('column_bool', FilterCondition::METHOD_BOOLEAN, true, false), |
33
|
|
|
$this->createFilterCondition('column_set', FilterCondition::METHOD_IN, [1, 2, 3], false), |
34
|
|
|
]), |
35
|
|
|
]); |
36
|
|
|
|
37
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
38
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
39
|
|
|
|
40
|
|
|
$this->assertEquals($filterToReduce->toUQL(), $reducedFilter->toUQL()); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
public function testReducesSearchTextFilterWithFilterConditions() |
44
|
|
|
{ |
45
|
|
|
$fields = [ |
46
|
|
|
$this->buildField('Field1', new StringDataType(), 'field1'), |
47
|
|
|
$this->buildField('Field2', new StringDataType(), 'field2'), |
48
|
|
|
$this->buildField('Field3', new StringDataType(), 'field3'), |
49
|
|
|
]; |
50
|
|
|
|
51
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
52
|
|
|
$this->createFilterCondition('column_datetime', FilterCondition::METHOD_DATETIME_EQ, 'now', false), |
53
|
|
|
$this->createFilterCondition('column_numeric', FilterCondition::METHOD_NUMERIC_NEQ, 123, false), |
54
|
|
|
$this->createFilter(Filter::CONDITION_TYPE_AND, [ |
55
|
|
|
$this->createFilterCondition('column_bool', FilterCondition::METHOD_BOOLEAN, true, false), |
56
|
|
|
$this->createFilterCondition('column_set', FilterCondition::METHOD_IN, [1, 2, 3], false), |
57
|
|
|
]), |
58
|
|
|
$this->createFilterCondition('column_search_text', FilterCondition::METHOD_STRING_EQ, 'test', true), |
59
|
|
|
]); |
60
|
|
|
|
61
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
62
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
63
|
|
|
|
64
|
|
|
$this->assertEquals(count($filterToReduce), count($reducedFilter)); |
65
|
|
|
$this->assertEquals($filterToReduce[0]->toUQL(), $reducedFilter[0]->toUQL()); |
66
|
|
|
$this->assertEquals($filterToReduce[1]->toUQL(), $reducedFilter[1]->toUQL()); |
67
|
|
|
$this->assertEquals($filterToReduce[2]->toUQL(), $reducedFilter[2]->toUQL()); |
68
|
|
|
$this->assertEquals('column_search_text = "test"', $filterToReduce[3]->toUQL()); |
69
|
|
|
$this->assertEquals('Field1 = "test" or Field2 = "test" or Field3 = "test"', $reducedFilter[3]->toUQL()); |
70
|
|
|
} |
71
|
|
|
|
72
|
|
View Code Duplication |
public function testReducesSearchTextFilterWithFilterConditionsAndUsesWildcardForLikeComparisonMethod() |
|
|
|
|
73
|
|
|
{ |
74
|
|
|
$fields = [ |
75
|
|
|
$this->buildField('Field1', new StringDataType(), 'field1'), |
76
|
|
|
$this->buildField('Field2', new StringDataType(), 'field2'), |
77
|
|
|
$this->buildField('Field3', new StringDataType(), 'field3'), |
78
|
|
|
]; |
79
|
|
|
|
80
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
81
|
|
|
$this->createFilterCondition('column_search_text', FilterCondition::METHOD_STRING_LIKE, 'test', true), |
82
|
|
|
]); |
83
|
|
|
|
84
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
85
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
86
|
|
|
|
87
|
|
|
$this->assertEquals('Field1 ~ "%test%" or Field2 ~ "%test%" or Field3 ~ "%test%"', $reducedFilter[0]->toUQL()); |
88
|
|
|
} |
89
|
|
|
|
90
|
|
|
public function testReducesSearchTextFilterWithFilterConditionsButSkipsFieldsThatDoNotSupportGivenMethod() |
91
|
|
|
{ |
92
|
|
|
$fields = [ |
93
|
|
|
$this->buildField('StringField', new StringDataType(), 'string_field'), |
94
|
|
|
$this->buildField('BooleanField', new BooleanDataType(), 'boolean_field'), |
95
|
|
|
$this->buildField('DateField', new DateDataType(), 'date_field'), |
96
|
|
|
$this->buildField('NumberField', new NumberDataType(), 'number_field'), |
97
|
|
|
$this->buildField('PercentField', new PercentDataType(), 'percent_field'), |
98
|
|
|
$this->buildField('EntityField', new EntityDataType(), 'entity_field'), |
99
|
|
|
$this->buildField('AnotherStringField', new StringDataType(), 'another_string_field'), |
100
|
|
|
]; |
101
|
|
|
|
102
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
103
|
|
|
$this->createFilterCondition('column_search_text', FilterCondition::METHOD_STRING_EQ, 'test', true), |
104
|
|
|
]); |
105
|
|
|
|
106
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
107
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
108
|
|
|
|
109
|
|
|
$this->assertEquals('StringField = "test" or AnotherStringField = "test"', $reducedFilter[0]->toUQL()); |
110
|
|
|
} |
111
|
|
|
|
112
|
|
View Code Duplication |
public function testReducesSearchTextFilterWithFilterConditionsButSkipsFieldsThatDoNotDefineDatabaseFilterQueryField() |
|
|
|
|
113
|
|
|
{ |
114
|
|
|
$fields = [ |
115
|
|
|
$this->buildField('FieldWithDbQueryField', new StringDataType(), 'field_with_db_field'), |
116
|
|
|
$this->buildField('FieldWithoutDbQueryField', new StringDataType(), null), |
117
|
|
|
$this->buildField('AnotherFieldWithDbQueryField', new StringDataType(), 'another_field_with_db_field'), |
118
|
|
|
]; |
119
|
|
|
|
120
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
121
|
|
|
$this->createFilterCondition('column_search_text', FilterCondition::METHOD_STRING_EQ, 'test', true), |
122
|
|
|
]); |
123
|
|
|
|
124
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
125
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
126
|
|
|
|
127
|
|
|
$this->assertEquals('FieldWithDbQueryField = "test" or AnotherFieldWithDbQueryField = "test"', $reducedFilter[0]->toUQL()); |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
public function testReducesSearchTextFilterWithFilterConditionsButSkipsFieldsThatDefineDatabaseSelectAliasAsArray() |
131
|
|
|
{ |
132
|
|
|
$fields = [ |
133
|
|
|
$this->buildField('FieldWithoutSelectAlias', new StringDataType(), 'field_without_select_alias'), |
134
|
|
|
$this->buildField('FieldWithSimpleSelectAlias', new StringDataType(), 'field_with_simple_select_alias', 'simple_alias'), |
135
|
|
|
$this->buildField('FieldWithSelectAliasAsAnArray', new StringDataType(), 'field_with_select_alias_as_an_array', ['alias1', 'alias2']), |
136
|
|
|
]; |
137
|
|
|
|
138
|
|
|
$filterToReduce = $this->createFilter(Filter::CONDITION_TYPE_OR, [ |
139
|
|
|
$this->createFilterCondition('column_search_text', FilterCondition::METHOD_STRING_EQ, 'test', true), |
140
|
|
|
]); |
141
|
|
|
|
142
|
|
|
$searchTextFilterReducer = new SearchTextFilterReducer($fields); |
143
|
|
|
$reducedFilter = $searchTextFilterReducer->reduceToFilterCondition($filterToReduce); |
144
|
|
|
|
145
|
|
|
$this->assertEquals('FieldWithoutSelectAlias = "test" or FieldWithSimpleSelectAlias = "test"', $reducedFilter[0]->toUQL()); |
146
|
|
|
} |
147
|
|
|
|
148
|
|
|
/** |
149
|
|
|
* @param string $conditionType |
150
|
|
|
* @param array $filterConditions |
151
|
|
|
* |
152
|
|
|
* @return Filter |
153
|
|
|
*/ |
154
|
|
|
private function createFilter($conditionType, array $filterConditions = []) |
155
|
|
|
{ |
156
|
|
|
$filter = new Filter(); |
157
|
|
|
$filter->setConditionType($conditionType); |
158
|
|
|
|
159
|
|
|
foreach ($filterConditions as $filterCondition) { |
160
|
|
|
$filter[] = $filterCondition; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
return $filter; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* @param string $columnIdentifier |
168
|
|
|
* @param string $method |
169
|
|
|
* @param mixed $value |
170
|
|
|
* @param bool $isSearchText |
171
|
|
|
* |
172
|
|
|
* @return FilterCondition |
173
|
|
|
*/ |
174
|
|
|
private function createFilterCondition($columnIdentifier, $method, $value, $isSearchText) |
175
|
|
|
{ |
176
|
|
|
$filterCondition = new FilterCondition($columnIdentifier, $method, $value, $value); |
177
|
|
|
$filterCondition->setIsSearchText($isSearchText); |
178
|
|
|
|
179
|
|
|
return $filterCondition; |
180
|
|
|
} |
181
|
|
|
|
182
|
|
|
/** |
183
|
|
|
* @param string $uniqueName |
184
|
|
|
* @param DataTypeInterface $dataType |
185
|
|
|
* @param string|null $databaseFilterQueryField |
186
|
|
|
* @param string|string[]|null $databaseSelectAlias |
187
|
|
|
* |
188
|
|
|
* @return Field |
189
|
|
|
*/ |
190
|
|
|
private function buildField( |
191
|
|
|
$uniqueName, |
192
|
|
|
DataTypeInterface $dataType, |
193
|
|
|
$databaseFilterQueryField = null, |
194
|
|
|
$databaseSelectAlias = null |
195
|
|
|
) { |
196
|
|
|
$field = $this->prophesize(Field::class); |
197
|
|
|
$field->getUniqueName()->willReturn($uniqueName); |
198
|
|
|
$field->getDataType()->willReturn($dataType); |
199
|
|
|
$field->getDatabaseFilterQueryField()->willReturn($databaseFilterQueryField); |
200
|
|
|
$field->getDatabaseSelectAlias()->willReturn($databaseSelectAlias); |
201
|
|
|
|
202
|
|
|
return $field->reveal(); |
203
|
|
|
} |
204
|
|
|
} |
205
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.