1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace OpenSkill\Datatable\Queries\Parser; |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
use OpenSkill\Datatable\Columns\ColumnConfiguration; |
7
|
|
|
use OpenSkill\Datatable\DatatableException; |
8
|
|
|
use OpenSkill\Datatable\Queries\QueryConfiguration; |
9
|
|
|
use OpenSkill\Datatable\Queries\QueryConfigurationBuilder; |
10
|
|
|
use Symfony\Component\HttpFoundation\JsonResponse; |
11
|
|
|
use Symfony\Component\HttpFoundation\ParameterBag; |
12
|
|
|
use Symfony\Component\HttpFoundation\Request; |
13
|
|
|
|
14
|
|
|
class Datatable19QueryParser extends QueryParser |
15
|
|
|
{ |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Method to determine if this parser can handle the query parameters. If so then the parser should return true |
19
|
|
|
* and be able to return a DTQueryConfiguration |
20
|
|
|
* |
21
|
|
|
* @param Request $request The current request, that should be investigated |
22
|
|
|
* @return bool true if the parser is able to parse the query parameters and to return a DTQueryConfiguration |
23
|
|
|
*/ |
24
|
|
|
public function canParse(Request $request) |
25
|
|
|
{ |
26
|
|
|
return $request->query->has("sEcho"); |
27
|
|
|
} |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* Method that should parse the request and return a DTQueryConfiguration |
31
|
|
|
* |
32
|
|
|
* @param Request $request The current request that should be investigated |
33
|
|
|
* @param ColumnConfiguration[] $columnConfiguration The configuration of the columns |
34
|
|
|
* @return QueryConfiguration the configuration the provider can use to prepare the data |
35
|
|
|
*/ |
36
|
|
View Code Duplication |
public function parse(Request $request, array $columnConfiguration) |
|
|
|
|
37
|
|
|
{ |
38
|
|
|
$query = $request->query; |
39
|
|
|
$builder = QueryConfigurationBuilder::create(); |
40
|
|
|
|
41
|
|
|
$this->getDrawCall($query, $builder); |
42
|
|
|
|
43
|
|
|
$this->getStart($query, $builder); |
44
|
|
|
|
45
|
|
|
$this->getLength($query, $builder); |
46
|
|
|
|
47
|
|
|
$this->getSearch($query, $builder); |
48
|
|
|
|
49
|
|
|
$this->determineSortableColumns($query, $builder, $columnConfiguration); |
50
|
|
|
|
51
|
|
|
$this->getRegex($query, $builder); |
52
|
|
|
|
53
|
|
|
$this->getSearchColumns($query, $builder, $columnConfiguration); |
54
|
|
|
|
55
|
|
|
return $builder->build(); |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* Helper function that will check if a variable is empty |
60
|
|
|
* @param mixed $string |
61
|
|
|
* @return bool true if empty, false otherwise |
62
|
|
|
*/ |
63
|
|
|
private function isEmpty($string) |
64
|
|
|
{ |
65
|
|
|
return empty($string); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
/** |
69
|
|
|
* Helper function that will check if a variable has a value |
70
|
|
|
* |
71
|
|
|
* NOTE: (this is almost the opposite of isEmpty, but it is *not* the same) |
72
|
|
|
* |
73
|
|
|
* @param mixed $string |
74
|
|
|
* @return bool true if empty, false otherwise |
75
|
|
|
*/ |
76
|
|
|
private function hasValue($string) |
77
|
|
|
{ |
78
|
|
|
return isset($string) && (strlen($string) > 0); |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* @param ParameterBag $query |
83
|
|
|
* @param QueryConfigurationBuilder $builder |
84
|
|
|
*/ |
85
|
|
|
public function getDrawCall($query, $builder) |
86
|
|
|
{ |
87
|
|
|
if ($query->has('sEcho')) { |
88
|
|
|
$builder->drawCall($query->get('sEcho')); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* @param ParameterBag $query |
94
|
|
|
* @param QueryConfigurationBuilder $builder |
95
|
|
|
*/ |
96
|
|
|
public function getStart($query, $builder) |
97
|
|
|
{ |
98
|
|
|
if ($query->has('iDisplayStart')) { |
99
|
|
|
$builder->start($query->get('iDisplayStart')); |
100
|
|
|
} |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* @param ParameterBag $query |
105
|
|
|
* @param QueryConfigurationBuilder $builder |
106
|
|
|
*/ |
107
|
|
|
public function getLength($query, $builder) |
108
|
|
|
{ |
109
|
|
|
if ($query->has('iDisplayLength')) { |
110
|
|
|
$builder->length($query->get('iDisplayLength')); |
111
|
|
|
} |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param ParameterBag $query |
116
|
|
|
* @param QueryConfigurationBuilder $builder |
117
|
|
|
*/ |
118
|
|
|
public function getSearch($query, $builder) |
119
|
|
|
{ |
120
|
|
|
if ($query->has('sSearch') && !$this->isEmpty($query->get('sSearch'))) { |
121
|
|
|
$builder->searchValue($query->get('sSearch')); |
122
|
|
|
} |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* @param ParameterBag $query |
127
|
|
|
* @param QueryConfigurationBuilder $builder |
128
|
|
|
* @param ColumnConfiguration[] $columnConfiguration |
129
|
|
|
*/ |
130
|
|
|
public function getSearchColumns($query, $builder, array $columnConfiguration) |
131
|
|
|
{ |
132
|
|
|
// for each column we need to see if there is a search value |
133
|
|
|
foreach ($columnConfiguration as $i => $c) { |
134
|
|
|
// check if there is something search related |
135
|
|
|
if ($c->getSearch()->isSearchable() && $query->has("sSearch_" . $i) && !$this->isEmpty($query->get("sSearch_" . $i))) { |
136
|
|
|
// search for this column is available |
137
|
|
|
$builder->columnSearch($c->getName(), $query->get("sSearch_" . $i)); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* @param ParameterBag $query |
144
|
|
|
* @param QueryConfigurationBuilder $builder |
145
|
|
|
* @param ColumnConfiguration[] $columnConfiguration |
146
|
|
|
* @throws DatatableException when a column for sorting is out of bounds |
147
|
|
|
* @return bool success? |
148
|
|
|
*/ |
149
|
|
|
private function determineSortableColumns($query, $builder, array $columnConfiguration) |
150
|
|
|
{ |
151
|
|
|
$columns = $this->getNumberOfSortingColumns($query); |
152
|
|
|
|
153
|
|
|
// this technically isn't needed, because the filtering will never hit the for loop anyways |
154
|
|
|
if ($columns == 0) { |
155
|
|
|
return false; |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
for ($i = 0; $i < $columns; $i++) { |
159
|
|
|
if ($query->has("iSortCol_" . $i) && $this->hasValue($query->get("iSortCol_" . $i))) { |
160
|
|
|
$c = $this->getColumnFromConfiguration($columnConfiguration, $query->get("iSortCol_" . $i)); |
161
|
|
|
|
162
|
|
|
if ($c->getOrder()->isOrderable()) { |
163
|
|
|
$builder->columnOrder($c->getName(), $query->get("sSortDir_" . $i)); |
164
|
|
|
} |
165
|
|
|
} |
166
|
|
|
} |
167
|
|
|
|
168
|
|
|
return true; |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
/** |
172
|
|
|
* Find out how many columns we are sorting by for the sorting loop |
173
|
|
|
* @see determineSortableColumns |
174
|
|
|
* @param ParameterBag $query |
175
|
|
|
* @return int |
176
|
|
|
*/ |
177
|
|
|
private function getNumberOfSortingColumns(ParameterBag $query) |
178
|
|
|
{ |
179
|
|
|
if (!$query->has('iSortingCols')) |
180
|
|
|
return 0; |
181
|
|
|
|
182
|
|
|
return intval($query->get('iSortingCols')) + 1; |
183
|
|
|
} |
184
|
|
|
|
185
|
|
|
/** |
186
|
|
|
* @param ColumnConfiguration[] $columnConfiguration |
187
|
|
|
* @param int $item |
188
|
|
|
* @return ColumnConfiguration a specific item from $ColumnConfiguration |
189
|
|
|
* @throws DatatableException |
190
|
|
|
*/ |
191
|
|
|
private function getColumnFromConfiguration(array $columnConfiguration, $item) |
192
|
|
|
{ |
193
|
|
|
$columnPosition = intval($item); |
194
|
|
|
|
195
|
|
|
if (!isset($columnConfiguration[$columnPosition])) { |
196
|
|
|
throw new DatatableException('The column requested for ordering does not exist'); |
197
|
|
|
} |
198
|
|
|
|
199
|
|
|
return $columnConfiguration[$columnPosition]; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* @param ParameterBag $query |
204
|
|
|
* @param QueryConfigurationBuilder $builder |
205
|
|
|
*/ |
206
|
|
|
public function getRegex($query, $builder) |
207
|
|
|
{ |
208
|
|
|
if ($query->has('bRegex')) { |
209
|
|
|
$builder->searchRegex($query->get('bRegex')); |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
} |
213
|
|
|
|
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.