1+ <?php namespace utils ;
2+ /**
3+ * Copyright 2021 OpenStack Foundation
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ * Unless required by applicable law or agreed to in writing, software
9+ * distributed under the License is distributed on an "AS IS" BASIS,
10+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+ * See the License for the specific language governing permissions and
12+ * limitations under the License.
13+ **/
14+
15+ use Doctrine \ORM \Query \Expr \Join ;
16+ use Doctrine \ORM \QueryBuilder ;
17+
18+ /**
19+ * Class DoctrineCollectionFieldsFilterMapping
20+ * @package App\Http\Utils\Filters
21+ */
22+ class DoctrineCollectionFieldsFilterMapping extends DoctrineJoinFilterMapping
23+ {
24+ private $ allowed_collection_fields = [];
25+
26+ private $ joins = [];
27+
28+ /**
29+ * DoctrineCollectionFieldsFilterMapping constructor.
30+ * @param string $table
31+ * @param string $alias
32+ * @param array $joins
33+ * @param array $allowed_collection_fields
34+ */
35+ public function __construct
36+ (
37+ string $ table ,
38+ string $ alias ,
39+ array $ joins = [],
40+ array $ allowed_collection_fields = []
41+ )
42+ {
43+ $ this ->allowed_collection_fields = $ allowed_collection_fields ;
44+ $ this ->joins = $ joins ;
45+ parent ::__construct ($ table , $ alias , "" );
46+ }
47+
48+ /**
49+ * @param FilterElement $filter
50+ * @param array $bindings
51+ * @return string
52+ */
53+ public function toRawSQL (FilterElement $ filter , array $ bindings = []):string
54+ {
55+ throw new \Exception ;
56+ }
57+
58+ /**
59+ * @param string $exp
60+ * @return FilterElement|null
61+ * @throws FilterParserException
62+ */
63+ private function parseFilter (string $ exp ):?FilterElement
64+ {
65+ list ($ field , $ op , $ value ) = FilterParser::filterExpresion ($ exp );
66+ if (!key_exists ($ field , $ this ->allowed_collection_fields ))
67+ throw new FilterParserException (sprintf ("Field %s is not allowed as filter " , $ field ));
68+
69+ return FilterParser::buildFilter ($ this ->allowed_collection_fields [$ field ], $ op , $ value );
70+ }
71+
72+ /**
73+ * @param QueryBuilder $query
74+ * @param FilterElement $filter
75+ * @return QueryBuilder
76+ * @throws \models\exceptions\ValidationException
77+ */
78+ public function apply (QueryBuilder $ query , FilterElement $ filter ):QueryBuilder
79+ {
80+ $ value = $ filter ->getValue ();
81+
82+ if (is_array ($ value )) {
83+
84+ $ inner_where = '' ;
85+
86+ foreach ($ value as $ val ) {
87+
88+ $ filterElement = $ this ->parseFilter ($ val );
89+ $ param_count = $ query ->getParameters ()->count () + 1 ;
90+ if (!empty ($ inner_where ))
91+ $ inner_where .= sprintf (" %s " , $ filter ->getSameFieldOp ());
92+ $ inner_where .= sprintf ("%s %s %s " , $ filterElement ->getField (), $ filterElement ->getOperator (), ":value_ " . $ param_count );
93+ $ query ->setParameter (":value_ " . $ param_count , $ filterElement ->getValue ());
94+ }
95+
96+ if (!in_array ($ this ->alias , $ query ->getAllAliases ()))
97+ $ query ->innerJoin ($ this ->table , $ this ->alias , Join::WITH );
98+
99+ foreach ($ this ->joins as $ join => $ join_alias ){
100+ if (!in_array ($ join_alias , $ query ->getAllAliases ()))
101+ $ query ->innerJoin (sprintf ("%s.%s " , $ this ->alias , $ join ), $ join_alias , Join::WITH );
102+ }
103+
104+ $ inner_where = sprintf ("( %s ) " , $ inner_where );
105+
106+ if ($ this ->main_operator === Filter::MainOperatorAnd)
107+ return $ query ->andWhere ($ inner_where );
108+ else
109+ return $ query ->orWhere ($ inner_where );
110+ }
111+
112+ $ param_count = $ query ->getParameters ()->count () + 1 ;
113+ $ filterElement = $ this ->parseFilter ($ value );
114+ $ where = sprintf ("%s %s %s " , $ filterElement ->getField (), $ filterElement ->getOperator (), ":value_ " . $ param_count );
115+ $ query ->setParameter (":value_ " . $ param_count , $ filterElement ->getValue ());
116+ if (!in_array ($ this ->alias , $ query ->getAllAliases ()))
117+ $ query ->innerJoin ($ this ->table , $ this ->alias , Join::WITH );
118+
119+ foreach ($ this ->joins as $ join => $ join_alias ){
120+ if (!in_array ($ join_alias , $ query ->getAllAliases ()))
121+ $ query ->innerJoin (sprintf ("%s.%s " , $ this ->alias , $ join ), $ join_alias , Join::WITH );
122+ }
123+
124+ if ($ this ->main_operator === Filter::MainOperatorAnd)
125+ return $ query ->andWhere ($ where );
126+ else
127+ return $ query ->orWhere ($ where );
128+ }
129+
130+ /**
131+ * @param QueryBuilder $query
132+ * @param FilterElement $filter
133+ * @return string
134+ */
135+ public function applyOr (QueryBuilder $ query , FilterElement $ filter ):string
136+ {
137+ $ value = $ filter ->getValue ();
138+
139+ if (is_array ($ value )) {
140+ $ inner_where = '' ;
141+
142+ foreach ($ value as $ val ) {
143+ $ filterElement = $ this ->parseFilter ($ val );
144+ $ param_count = $ query ->getParameters ()->count () + 1 ;
145+ if (!empty ($ inner_where ))
146+ $ inner_where .= sprintf (" %s " , $ filter ->getSameFieldOp ());
147+ $ inner_where .= sprintf ("%s %s %s " , $ filterElement ->getField (), $ filterElement ->getOperator (), ":value_ " . $ param_count );
148+ $ query ->setParameter (":value_ " . $ param_count , $ filterElement ->getValue ());
149+ }
150+
151+ $ inner_where = sprintf ("( %s ) " , $ inner_where );
152+
153+ if (!in_array ($ this ->alias , $ query ->getAllAliases ()))
154+ $ query ->innerJoin ($ this ->table , $ this ->alias , Join::WITH );
155+
156+ foreach ($ this ->joins as $ join => $ join_alias ){
157+ if (!in_array ($ join_alias , $ query ->getAllAliases ()))
158+ $ query ->innerJoin (sprintf ("%s.%s " , $ this ->alias , $ join ), $ join_alias , Join::WITH );
159+ }
160+
161+ return $ inner_where ;
162+ }
163+
164+ $ param_count = $ query ->getParameters ()->count () + 1 ;
165+ $ filterElement = $ this ->parseFilter ($ value );
166+ $ where = sprintf ("%s %s %s " , $ filterElement ->getField (), $ filterElement ->getOperator (), ":value_ " . $ param_count );
167+ $ query ->setParameter (":value_ " . $ param_count , $ filterElement ->getValue ());
168+ if (!in_array ($ this ->alias , $ query ->getAllAliases ()))
169+ $ query ->innerJoin ($ this ->table , $ this ->alias , Join::WITH );
170+
171+ foreach ($ this ->joins as $ join => $ join_alias ){
172+ if (!in_array ($ join_alias , $ query ->getAllAliases ()))
173+ $ query ->innerJoin (sprintf ("%s.%s " , $ this ->alias , $ join ), $ join_alias , Join::WITH );
174+ }
175+
176+ return $ where ;
177+ }
178+
179+ }
0 commit comments