@@ -40,6 +40,7 @@ class QueryProcessor extends Component
40
40
'NOT LIKE ' => 'filterLikeCondition ' ,
41
41
'OR LIKE ' => 'filterLikeCondition ' ,
42
42
'OR NOT LIKE ' => 'filterLikeCondition ' ,
43
+ 'CALLBACK ' => 'filterCallbackCondition ' ,
43
44
];
44
45
45
46
/**
@@ -50,9 +51,9 @@ class QueryProcessor extends Component
50
51
/**
51
52
* @param ArrayQuery $query
52
53
*
53
- * @return array
54
+ * @return array[]
54
55
*/
55
- public function process ($ query ): array
56
+ public function process ($ query )
56
57
{
57
58
$ this ->_query = $ query ;
58
59
@@ -72,7 +73,7 @@ public function process($query): array
72
73
*
73
74
* @return array sorted data
74
75
*/
75
- protected function applyOrderBy (array $ data , $ orderBy ): array
76
+ protected function applyOrderBy (array $ data , $ orderBy )
76
77
{
77
78
if (!empty ($ orderBy )) {
78
79
ArrayHelper::multisort ($ data , array_keys ($ orderBy ), array_values ($ orderBy ));
@@ -90,7 +91,7 @@ protected function applyOrderBy(array $data, $orderBy): array
90
91
*
91
92
* @return array data
92
93
*/
93
- protected function applyLimit (array $ data , $ limit , $ offset ): array
94
+ protected function applyLimit (array $ data , $ limit , $ offset )
94
95
{
95
96
if (empty ($ limit ) && empty ($ offset )) {
96
97
return $ data ;
@@ -115,7 +116,7 @@ protected function applyLimit(array $data, $limit, $offset): array
115
116
*
116
117
* @return array data
117
118
*/
118
- protected function applyWhere (array $ data , $ where ): array
119
+ protected function applyWhere (array $ data , $ where )
119
120
{
120
121
return $ this ->filterCondition ($ data , $ where );
121
122
}
@@ -130,7 +131,7 @@ protected function applyWhere(array $data, $where): array
130
131
*
131
132
* @throws InvalidParamException
132
133
*/
133
- protected function filterCondition (array $ data , $ condition ): array
134
+ public function filterCondition (array $ data , $ condition )
134
135
{
135
136
if (empty ($ condition )) {
136
137
return $ data ;
@@ -145,12 +146,13 @@ protected function filterCondition(array $data, $condition): array
145
146
if (isset ($ this ->conditionFilters [$ operator ])) {
146
147
$ method = $ this ->conditionFilters [$ operator ];
147
148
} else {
148
- throw new InvalidParamException ( " Invalid condition filter ' { $ operator } ' " ) ;
149
+ $ method = ' filterSimpleCondition ' ;
149
150
}
151
+
150
152
array_shift ($ condition );
151
153
152
154
return $ this ->$ method ($ data , $ operator , $ condition );
153
- } else {
155
+ } else { // hash format: 'column1' => 'value1', 'column2' => 'value2', ...
154
156
return $ this ->filterHashCondition ($ data , $ condition );
155
157
}
156
158
}
@@ -163,13 +165,18 @@ protected function filterCondition(array $data, $condition): array
163
165
*
164
166
* @return array filtered data
165
167
*/
166
- protected function filterHashCondition (array $ data , $ condition ): array
168
+ public function filterHashCondition (array $ data , $ condition )
167
169
{
168
170
foreach ($ condition as $ column => $ value ) {
169
171
if (is_array ($ value )) {
172
+ // IN condition
170
173
$ data = $ this ->filterInCondition ($ data , 'IN ' , [$ column , $ value ]);
171
174
} else {
172
175
$ data = array_filter ($ data , function ($ row ) use ($ column , $ value ) {
176
+ if ($ value instanceof \Closure) {
177
+ return call_user_func ($ value , $ row [$ column ]);
178
+ }
179
+
173
180
return $ row [$ column ] == $ value ;
174
181
});
175
182
}
@@ -187,7 +194,7 @@ protected function filterHashCondition(array $data, $condition): array
187
194
*
188
195
* @return array filtered data
189
196
*/
190
- protected function filterAndCondition (array $ data , $ operator , $ operands ): array
197
+ protected function filterAndCondition (array $ data , $ operator , $ operands )
191
198
{
192
199
foreach ($ operands as $ operand ) {
193
200
if (is_array ($ operand )) {
@@ -207,7 +214,7 @@ protected function filterAndCondition(array $data, $operator, $operands): array
207
214
*
208
215
* @return array filtered data
209
216
*/
210
- protected function filterOrCondition (array $ data , $ operator , $ operands ): array
217
+ protected function filterOrCondition (array $ data , $ operator , $ operands )
211
218
{
212
219
$ parts = [];
213
220
foreach ($ operands as $ operand ) {
@@ -242,7 +249,7 @@ protected function filterOrCondition(array $data, $operator, $operands): array
242
249
*
243
250
* @throws InvalidParamException if wrong number of operands have been given
244
251
*/
245
- protected function filterNotCondition (array $ data , $ operator , $ operands ): array
252
+ protected function filterNotCondition (array $ data , $ operator , $ operands )
246
253
{
247
254
if (count ($ operands ) != 1 ) {
248
255
throw new InvalidParamException ("Operator ' $ operator' requires exactly one operand. " );
@@ -280,7 +287,7 @@ protected function filterNotCondition(array $data, $operator, $operands): array
280
287
*
281
288
* @throws InvalidParamException if wrong number of operands have been given
282
289
*/
283
- protected function filterBetweenCondition (array $ data , $ operator , $ operands ): array
290
+ protected function filterBetweenCondition (array $ data , $ operator , $ operands )
284
291
{
285
292
if (!isset ($ operands [0 ], $ operands [1 ], $ operands [2 ])) {
286
293
throw new InvalidParamException ("Operator ' $ operator' requires three operands. " );
@@ -311,7 +318,7 @@ protected function filterBetweenCondition(array $data, $operator, $operands): ar
311
318
*
312
319
* @throws InvalidParamException if wrong number of operands have been given
313
320
*/
314
- protected function filterInCondition (array $ data , $ operator , $ operands ): array
321
+ protected function filterInCondition (array $ data , $ operator , $ operands )
315
322
{
316
323
if (!isset ($ operands [0 ], $ operands [1 ])) {
317
324
throw new InvalidParamException ("Operator ' $ operator' requires two operands. " );
@@ -362,7 +369,7 @@ protected function filterInCondition(array $data, $operator, $operands): array
362
369
*
363
370
* @throws InvalidParamException if wrong number of operands have been given
364
371
*/
365
- protected function filterLikeCondition (array $ data , $ operator , $ operands ): array
372
+ protected function filterLikeCondition (array $ data , $ operator , $ operands )
366
373
{
367
374
if (!isset ($ operands [0 ], $ operands [1 ])) {
368
375
throw new InvalidParamException ("Operator ' $ operator' requires two operands. " );
@@ -431,4 +438,81 @@ protected function filterLikeCondition(array $data, $operator, $operands): array
431
438
return true ;
432
439
});
433
440
}
441
+
442
+ /**
443
+ * Applies 'CALLBACK' condition.
444
+ *
445
+ * @param array $data data to be filtered
446
+ * @param string $operator operator
447
+ * @param array $operands the only one operand is the PHP callback, which should be compatible with
448
+ * `array_filter()` PHP function, e.g.:
449
+ *
450
+ * ```php
451
+ * function ($row) {
452
+ * //return bool whether row matches condition or not
453
+ * }
454
+ * ```
455
+ *
456
+ * @return array filtered data
457
+ *
458
+ * @throws InvalidParamException if wrong number of operands have been given
459
+ *
460
+ * @since 1.0.3
461
+ */
462
+ public function filterCallbackCondition (array $ data , $ operator , $ operands )
463
+ {
464
+ if (count ($ operands ) != 1 ) {
465
+ throw new InvalidParamException ("Operator ' $ operator' requires exactly one operand. " );
466
+ }
467
+
468
+ $ callback = reset ($ operands );
469
+
470
+ return array_filter ($ data , $ callback );
471
+ }
472
+
473
+ /**
474
+ * Applies comparison condition, e.g. `column operator value`.
475
+ *
476
+ * @param array $data data to be filtered
477
+ * @param string $operator operator
478
+ * @param array $operands
479
+ *
480
+ * @return array filtered data
481
+ *
482
+ * @throws InvalidParamException if wrong number of operands have been given or operator is not supported
483
+ *
484
+ * @since 1.0.4
485
+ */
486
+ public function filterSimpleCondition (array $ data , $ operator , $ operands )
487
+ {
488
+ if (count ($ operands ) !== 2 ) {
489
+ throw new InvalidParamException ("Operator ' $ operator' requires two operands. " );
490
+ }
491
+ list ($ column , $ value ) = $ operands ;
492
+
493
+ return array_filter ($ data , function ($ row ) use ($ operator , $ column , $ value ) {
494
+ switch ($ operator ) {
495
+ case '= ' :
496
+ case '== ' :
497
+ return $ row [$ column ] == $ value ;
498
+ case '=== ' :
499
+ return $ row [$ column ] === $ value ;
500
+ case '!= ' :
501
+ case '<> ' :
502
+ return $ row [$ column ] != $ value ;
503
+ case '!== ' :
504
+ return $ row [$ column ] !== $ value ;
505
+ case '> ' :
506
+ return $ row [$ column ] > $ value ;
507
+ case '< ' :
508
+ return $ row [$ column ] < $ value ;
509
+ case '>= ' :
510
+ return $ row [$ column ] >= $ value ;
511
+ case '<= ' :
512
+ return $ row [$ column ] <= $ value ;
513
+ default :
514
+ throw new InvalidParamException ("Operator ' $ operator' is not supported. " );
515
+ }
516
+ });
517
+ }
434
518
}
0 commit comments