@@ -40,6 +40,7 @@ class QueryProcessor extends Component
4040 'NOT LIKE ' => 'filterLikeCondition ' ,
4141 'OR LIKE ' => 'filterLikeCondition ' ,
4242 'OR NOT LIKE ' => 'filterLikeCondition ' ,
43+ 'CALLBACK ' => 'filterCallbackCondition ' ,
4344 ];
4445
4546 /**
@@ -50,9 +51,9 @@ class QueryProcessor extends Component
5051 /**
5152 * @param ArrayQuery $query
5253 *
53- * @return array
54+ * @return array[]
5455 */
55- public function process ($ query ): array
56+ public function process ($ query )
5657 {
5758 $ this ->_query = $ query ;
5859
@@ -72,7 +73,7 @@ public function process($query): array
7273 *
7374 * @return array sorted data
7475 */
75- protected function applyOrderBy (array $ data , $ orderBy ): array
76+ protected function applyOrderBy (array $ data , $ orderBy )
7677 {
7778 if (!empty ($ orderBy )) {
7879 ArrayHelper::multisort ($ data , array_keys ($ orderBy ), array_values ($ orderBy ));
@@ -90,7 +91,7 @@ protected function applyOrderBy(array $data, $orderBy): array
9091 *
9192 * @return array data
9293 */
93- protected function applyLimit (array $ data , $ limit , $ offset ): array
94+ protected function applyLimit (array $ data , $ limit , $ offset )
9495 {
9596 if (empty ($ limit ) && empty ($ offset )) {
9697 return $ data ;
@@ -115,7 +116,7 @@ protected function applyLimit(array $data, $limit, $offset): array
115116 *
116117 * @return array data
117118 */
118- protected function applyWhere (array $ data , $ where ): array
119+ protected function applyWhere (array $ data , $ where )
119120 {
120121 return $ this ->filterCondition ($ data , $ where );
121122 }
@@ -130,7 +131,7 @@ protected function applyWhere(array $data, $where): array
130131 *
131132 * @throws InvalidParamException
132133 */
133- protected function filterCondition (array $ data , $ condition ): array
134+ public function filterCondition (array $ data , $ condition )
134135 {
135136 if (empty ($ condition )) {
136137 return $ data ;
@@ -145,12 +146,13 @@ protected function filterCondition(array $data, $condition): array
145146 if (isset ($ this ->conditionFilters [$ operator ])) {
146147 $ method = $ this ->conditionFilters [$ operator ];
147148 } else {
148- throw new InvalidParamException ( " Invalid condition filter ' { $ operator } ' " ) ;
149+ $ method = ' filterSimpleCondition ' ;
149150 }
151+
150152 array_shift ($ condition );
151153
152154 return $ this ->$ method ($ data , $ operator , $ condition );
153- } else {
155+ } else { // hash format: 'column1' => 'value1', 'column2' => 'value2', ...
154156 return $ this ->filterHashCondition ($ data , $ condition );
155157 }
156158 }
@@ -163,13 +165,18 @@ protected function filterCondition(array $data, $condition): array
163165 *
164166 * @return array filtered data
165167 */
166- protected function filterHashCondition (array $ data , $ condition ): array
168+ public function filterHashCondition (array $ data , $ condition )
167169 {
168170 foreach ($ condition as $ column => $ value ) {
169171 if (is_array ($ value )) {
172+ // IN condition
170173 $ data = $ this ->filterInCondition ($ data , 'IN ' , [$ column , $ value ]);
171174 } else {
172175 $ data = array_filter ($ data , function ($ row ) use ($ column , $ value ) {
176+ if ($ value instanceof \Closure) {
177+ return call_user_func ($ value , $ row [$ column ]);
178+ }
179+
173180 return $ row [$ column ] == $ value ;
174181 });
175182 }
@@ -187,7 +194,7 @@ protected function filterHashCondition(array $data, $condition): array
187194 *
188195 * @return array filtered data
189196 */
190- protected function filterAndCondition (array $ data , $ operator , $ operands ): array
197+ protected function filterAndCondition (array $ data , $ operator , $ operands )
191198 {
192199 foreach ($ operands as $ operand ) {
193200 if (is_array ($ operand )) {
@@ -207,7 +214,7 @@ protected function filterAndCondition(array $data, $operator, $operands): array
207214 *
208215 * @return array filtered data
209216 */
210- protected function filterOrCondition (array $ data , $ operator , $ operands ): array
217+ protected function filterOrCondition (array $ data , $ operator , $ operands )
211218 {
212219 $ parts = [];
213220 foreach ($ operands as $ operand ) {
@@ -242,7 +249,7 @@ protected function filterOrCondition(array $data, $operator, $operands): array
242249 *
243250 * @throws InvalidParamException if wrong number of operands have been given
244251 */
245- protected function filterNotCondition (array $ data , $ operator , $ operands ): array
252+ protected function filterNotCondition (array $ data , $ operator , $ operands )
246253 {
247254 if (count ($ operands ) != 1 ) {
248255 throw new InvalidParamException ("Operator ' $ operator' requires exactly one operand. " );
@@ -280,7 +287,7 @@ protected function filterNotCondition(array $data, $operator, $operands): array
280287 *
281288 * @throws InvalidParamException if wrong number of operands have been given
282289 */
283- protected function filterBetweenCondition (array $ data , $ operator , $ operands ): array
290+ protected function filterBetweenCondition (array $ data , $ operator , $ operands )
284291 {
285292 if (!isset ($ operands [0 ], $ operands [1 ], $ operands [2 ])) {
286293 throw new InvalidParamException ("Operator ' $ operator' requires three operands. " );
@@ -311,7 +318,7 @@ protected function filterBetweenCondition(array $data, $operator, $operands): ar
311318 *
312319 * @throws InvalidParamException if wrong number of operands have been given
313320 */
314- protected function filterInCondition (array $ data , $ operator , $ operands ): array
321+ protected function filterInCondition (array $ data , $ operator , $ operands )
315322 {
316323 if (!isset ($ operands [0 ], $ operands [1 ])) {
317324 throw new InvalidParamException ("Operator ' $ operator' requires two operands. " );
@@ -362,7 +369,7 @@ protected function filterInCondition(array $data, $operator, $operands): array
362369 *
363370 * @throws InvalidParamException if wrong number of operands have been given
364371 */
365- protected function filterLikeCondition (array $ data , $ operator , $ operands ): array
372+ protected function filterLikeCondition (array $ data , $ operator , $ operands )
366373 {
367374 if (!isset ($ operands [0 ], $ operands [1 ])) {
368375 throw new InvalidParamException ("Operator ' $ operator' requires two operands. " );
@@ -431,4 +438,81 @@ protected function filterLikeCondition(array $data, $operator, $operands): array
431438 return true ;
432439 });
433440 }
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+ }
434518}
0 commit comments