15
15
* Partials:
16
16
* offset=20
17
17
*/
18
- class QueryParser
18
+ class QueryParser extends \ Phalcon \ Di \Injectable
19
19
{
20
20
/**
21
21
* @var array
@@ -41,17 +41,28 @@ public function __construct(array $request)
41
41
*/
42
42
public function request (): array
43
43
{
44
- $ params = '' ;
44
+ $ params = [
45
+ 'params ' => '' ,
46
+ 'subquery ' => '' ,
47
+ ];
48
+
45
49
$ isSearch = false ;
50
+ $ hasSubquery = false ;
46
51
47
- //verify the user is search for something
52
+ //verify the user is searching for something
48
53
if (array_key_exists ('q ' , $ this ->request )) {
49
- $ params = $ this ->request ['q ' ];
54
+ $ params[ ' params ' ] = $ this ->request ['q ' ];
50
55
$ isSearch = true ;
51
56
}
52
57
58
+ //verify the request has a subquery
59
+ if (array_key_exists ('subq ' , $ this ->request )) {
60
+ $ params ['subquery ' ] = $ this ->request ['subq ' ];
61
+ $ hasSubquery = true ;
62
+ }
63
+
53
64
//initialize the model params
54
- $ modelSearchParams = $ this ->prepareSearch ($ params , $ isSearch );
65
+ $ modelSearchParams = $ this ->prepareSearch ($ params , $ isSearch, $ hasSubquery );
55
66
56
67
//filter the field
57
68
if (array_key_exists ('fields ' , $ this ->request )) {
@@ -114,33 +125,114 @@ protected function parseSearchParameters(string $unparsed): array
114
125
return $ mapped ;
115
126
}
116
127
128
+ /**
129
+ * Parses out the subquery parameters from a request.
130
+ *
131
+ * in = ::, not in = !::
132
+ *
133
+ * Unparsed, they will look like this:
134
+ * internet_special(id::vehicles_id)
135
+ * Parsed:
136
+ * Array('action' => in, 'firstField' => id, 'secondField' => vehicles_id,'model' => MyDealer\Models\InternetSpecial)
137
+ *
138
+ * *
139
+ * @param string $unparsed Unparsed search string
140
+ * @return array An array of fieldname=>value search parameters
141
+ */
142
+ protected function parseSubquery (string $ unparsed ): array
143
+ {
144
+ $ unparsed = urldecode ($ unparsed );
145
+ // Strip parens that come with the request string
146
+ $ tableName = explode ("( " , $ unparsed , 2 );
147
+ //print_r($tableName);die();
148
+ $ tableName = strtolower ($ tableName [0 ]);
149
+
150
+ $ modelName = str_replace ('_ ' , ' ' , $ tableName );
151
+ $ modelName = str_replace (' ' , '' , ucwords ($ modelName ));
152
+
153
+ //Add the namespace to the model name
154
+ $ model = $ this ->config ['namespace ' ]['models ' ] . '\\' . $ modelName ;
155
+
156
+ $ unparsed = str_replace ($ tableName , '' , $ unparsed );
157
+ $ unparsed = trim ($ unparsed , '() ' );
158
+
159
+ // Now we have an array of "key:value" strings.
160
+ $ splitFields = explode (', ' , $ unparsed );
161
+
162
+ if (strpos ($ splitFields [0 ], '!:: ' ) !== false ) {
163
+ $ action = 'not in ' ;
164
+ $ fieldsToRelate = explode ('!:: ' , $ splitFields [0 ]);
165
+ } elseif (strpos ($ splitFields [0 ], ':: ' ) !== false ) {
166
+ $ action = 'in ' ;
167
+ $ fieldsToRelate = explode (':: ' , $ splitFields [0 ]);
168
+ } else {
169
+ throw new \Exception ("Error Processing Subquery " , 1 );
170
+ }
171
+
172
+ $ subquery = [
173
+ 'action ' => $ action ,
174
+ 'firstField ' => $ fieldsToRelate [0 ],
175
+ 'secondField ' => $ fieldsToRelate [1 ],
176
+ 'model ' => $ model ,
177
+ ];
178
+
179
+ /*// Split the strings at their colon, set left to key, and right to value.
180
+ foreach ($splitFields as $field) {
181
+ $splitField = explode(':', $field);
182
+ $mapped[$splitField[0]] = $splitField[1];
183
+ }*/
184
+
185
+ return $ subquery ;
186
+ }
187
+
117
188
/**
118
189
* Prepare conditions to search in record
119
190
*
120
191
* @param string $unparsed
121
192
* @return array
122
193
*/
123
- protected function prepareSearch (string $ unparsed , bool $ isSearch = false ): array
194
+ protected function prepareSearch (array $ unparsed , bool $ isSearch = false , $ hasSubquery = false ): array
124
195
{
125
196
$ statement = [
126
197
'conditions ' => "1 = 1 " ,
127
198
'bind ' => [],
128
199
];
129
200
130
201
if ($ isSearch ) {
131
- $ mapped = $ this ->parseSearchParameters ($ unparsed );
202
+ $ mapped = $ this ->parseSearchParameters ($ unparsed[ ' params ' ] );
132
203
$ conditions = '1 = 1 ' ;
133
- $ keys = array_keys ($ mapped );
134
- array_unshift ($ keys , 1 );
135
- unset($ keys [0 ]);
136
204
137
- $ values = array_values ($ mapped );
138
- array_unshift ($ values , 1 );
139
- unset($ values [0 ]);
205
+ // $between = ' AND year between ?0 AND ?1';
206
+
207
+ $ tmpMapped = $ mapped ;
208
+
209
+ foreach ($ tmpMapped as $ key => $ value ) {
210
+ if (strpos ($ value , '~ ' ) !== false ) {
211
+ unset($ tmpMapped [$ key ]);
212
+ $ betweenMap [$ key ] = explode ('~ ' , $ value );
213
+ }
214
+ }
215
+
216
+ $ keys = array_keys ($ tmpMapped );
217
+ $ values = array_values ($ tmpMapped );
218
+
140
219
foreach ($ keys as $ key => $ field ) {
141
220
$ conditions .= " AND {$ field } = ? {$ key }" ;
142
221
}
143
222
223
+ if (isset ($ betweenMap )) {
224
+ foreach ($ betweenMap as $ key => $ fields ) {
225
+ $ binds = count ($ values );
226
+ $ conditions .= ' AND ' . $ key . ' BETWEEN ? ' . $ binds . ' AND ? ' . ($ binds + 1 );
227
+ $ values = array_merge ($ values , $ fields );
228
+ }
229
+ }
230
+
231
+ if ($ hasSubquery ) {
232
+ $ subquery = $ this ->parseSubquery ($ unparsed ['subquery ' ]);
233
+ $ conditions .= ' AND ' . $ subquery ['firstField ' ] . ' ' . $ subquery ['action ' ] . ' (select ' . $ subquery ['secondField ' ] . ' FROM ' . $ subquery ['model ' ] . ') ' ;
234
+ }
235
+
144
236
$ statement = [
145
237
'conditions ' => $ conditions ,
146
238
'bind ' => $ values ,
0 commit comments