1+ <?php
2+
3+ namespace Vladvildanov \PredisVl \Query \Filter ;
4+
5+ use Vladvildanov \PredisVl \Enum \Logical ;
6+
7+ class AggregateFilter extends AbstractFilter implements AggregateFilterInterface
8+ {
9+ /**
10+ * @var array
11+ */
12+ private array $ filters = [];
13+
14+ /**
15+ * Mapping for logical operators according to query syntax.
16+ *
17+ * @var array
18+ * @link https://redis.io/docs/interact/search-and-query/query/combined/
19+ */
20+ private array $ conjunctionMapping = [
21+ '&& ' => ' ' ,
22+ '|| ' => ' | ' ,
23+ ];
24+
25+ /**
26+ * Creates an aggregated filter based on the set of given filters.
27+ *
28+ * If the same logical operator should be applied to all filters, you could pass them here in constructor.
29+ * If you need a combination of logical operators use and() or() methods to build suitable aggregate filter.
30+ *
31+ * @param FilterInterface $filters
32+ * @param Logical $conjunction
33+ */
34+ public function __construct ($ filters = [], Logical $ conjunction = Logical::and)
35+ {
36+ if (!empty ($ filters )) {
37+ $ this ->addFilters ($ filters , $ conjunction );
38+ }
39+ }
40+
41+ /**
42+ * @inheritDoc
43+ */
44+ public function and (FilterInterface ...$ filter ): AggregateFilterInterface
45+ {
46+ $ this ->addFilters (func_get_args (), Logical::and);
47+
48+ return $ this ;
49+ }
50+
51+ /**
52+ * @inheritDoc
53+ */
54+ public function or (FilterInterface ...$ filter ): AggregateFilterInterface
55+ {
56+ $ this ->addFilters (func_get_args (), Logical::or);
57+
58+ return $ this ;
59+ }
60+
61+ /**
62+ * @inheritDoc
63+ */
64+ public function toExpression (): string
65+ {
66+ return trim (implode ('' , $ this ->filters ), ' | ' );
67+ }
68+
69+ /**
70+ * Add filters with given conjunction into array.
71+ *
72+ * @param FilterInterface[] $filters
73+ * @param Logical $conjunction
74+ * @return void
75+ */
76+ private function addFilters (array $ filters , Logical $ conjunction ): void
77+ {
78+ if (count ($ filters ) === 1 ) {
79+ $ this ->filters [] = $ this ->conjunctionMapping [$ conjunction ->value ];
80+ $ this ->filters [] = $ filters [0 ]->toExpression ();
81+ } else {
82+ if (!empty ($ this ->filters )) {
83+ $ this ->filters [] = ' ' ;
84+ }
85+
86+ foreach ($ filters as $ i => $ filter ) {
87+ $ this ->filters [] = $ filter ->toExpression ();
88+
89+ if ($ i !== count ($ filters ) - 1 ) {
90+ $ this ->filters [] = $ this ->conjunctionMapping [$ conjunction ->value ];
91+ }
92+ }
93+ }
94+ }
95+ }
0 commit comments