PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 4.1.6
Admin Columns v4.1.6
7.0.19 2.3.5 2.4 2.4.1 2.4.10 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.4.8 2.4.9 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.6.1 2.5.6.2 2.5.6.3 2.5.6.4 3.0 3.0.1 3.0.2 3.0.3 3.0.5 3.0.7 3.1 3.1.1 3.1.10 3.1.2 3.1.3 3.1.5 3.2.3 3.2.7 3.3.1 3.4.1 3.4.6 3.4.8 4.0.1 4.0.3 4.1.6 4.2.2 4.2.5 4.3 4.3.2 4.4.1 4.4.4 4.4.5 4.5.5 4.6.1 4.7.18 4.7.19 4.7.20 4.7.7 7.0.13 7.0.14 7.0.16 trunk 1.0 1.1 1.1.3 1.2 1.2.1 1.3 1.3.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.5.1 1.4.6 1.4.6.1 1.4.6.2 1.4.6.3 1.4.6.4 1.4.7 1.4.8 1.4.9 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.2 2.2.1 2.2.1.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.5.1 2.2.6 2.2.6.1 2.2.6.2 2.2.6.3 2.2.6.4 2.2.7 2.2.8 2.2.8.1 2.2.9 2.3.1 2.3.2 2.3.3
codepress-admin-columns / classes / Meta / Query.php
codepress-admin-columns / classes / Meta Last commit date
Query.php 6 years ago QueryColumn.php 6 years ago
Query.php
504 lines
1 <?php
2
3 namespace AC\Meta;
4
5 use WP_Meta_Query;
6
7 class Query {
8
9 /**
10 * @var WP_Meta_Query
11 */
12 private $query;
13
14 /**
15 * @var string
16 */
17 private $sql;
18
19 /**
20 * @var array
21 */
22 private $select = [];
23
24 /**
25 * @var string|false
26 */
27 private $count = false;
28
29 /**
30 * @var bool
31 */
32 private $distinct = false;
33
34 /**
35 * @var bool
36 */
37 private $join = false;
38
39 /**
40 * @var array
41 */
42 private $join_where = [];
43
44 /**
45 * @var array
46 */
47 private $where = [];
48
49 /**
50 * @var array
51 */
52 private $group_by = [];
53
54 /**
55 * @var array
56 */
57 private $order_by = [];
58
59 /**
60 * @var int|false
61 */
62 private $limit = false;
63
64 /**
65 * @param string $meta_type
66 */
67 public function __construct( $meta_type ) {
68 $this->set_query( $meta_type );
69 }
70
71 /**
72 * Add a single field or multiple comma separated
73 *
74 * @param string $field e.g. id or id, meta_value
75 *
76 * @return $this
77 */
78 public function select( $field ) {
79 $fields = explode( ',', $field );
80
81 foreach ( $fields as $_field ) {
82 $this->select[] = trim( $_field );
83 }
84
85 return $this;
86 }
87
88 /**
89 * Add a COUNT clause AS count
90 *
91 * @param string $field
92 *
93 * @return $this
94 */
95 public function count( $field ) {
96 $this->count = $field;
97
98 return $this;
99 }
100
101 /**
102 * Group by an aggregated column.
103 * Supports: count
104 *
105 * @param string $field
106 *
107 * @return $this
108 */
109 public function group_by( $field ) {
110 $this->group_by = $field;
111
112 return $this;
113 }
114
115 public function join( $type = 'inner' ) {
116 $this->join = strtoupper( $type );
117
118 return $this;
119 }
120
121 public function left_join() {
122 return $this->join( 'left' );
123 }
124
125 /**
126 * @param $field
127 * @param null $operator
128 * @param null $value
129 * @param string $boolean
130 *
131 * @return $this
132 * @see get_where_clause()
133 */
134 public function join_where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
135 // set default join
136 if ( ! $this->join ) {
137 $this->join();
138 }
139
140 $this->join_where[] = $this->get_where_clause( $field, $operator, $value, $boolean );
141
142 return $this;
143 }
144
145 public function order_by( $order_by, $order = 'asc' ) {
146 $parts = explode( ',', $order_by );
147
148 foreach ( $parts as $_order_by ) {
149 $this->order_by[] = [
150 'order_by' => trim( $_order_by ),
151 'order' => strtoupper( $order ),
152 ];
153 }
154
155 return $this;
156 }
157
158 public function limit( $limit ) {
159 $this->limit = absint( $limit );
160 }
161
162 public function distinct() {
163 $this->distinct = true;
164
165 return $this;
166 }
167
168 /**
169 * Set a where clause
170 *
171 * @param string|array $field
172 * @param string $operator
173 * @param string|int|array $value
174 * @param string $boolean
175 *
176 * @return array
177 */
178 private function get_where_clause( $field, $operator = null, $value = null, $boolean = 'AND' ) {
179 // allows to omit operator
180 if ( null === $value ) {
181 $value = $operator;
182 $operator = '=';
183 }
184
185 $where = [
186 'nested' => false,
187 'boolean' => strtoupper( $boolean ),
188 'field' => $field,
189 'operator' => strtoupper( $operator ),
190 'value' => $value,
191 ];
192
193 // set default join
194 if ( $field === 'post_type' && ! $this->join ) {
195 $this->join();
196 }
197
198 $nested = [];
199
200 if ( is_array( $field ) ) {
201 $count = count( $field );
202 for ( $i = 0; $i < $count; $i++ ) {
203 $nested[] = array_pop( $this->where );
204 }
205 }
206
207 if ( $nested ) {
208 $where['nested'] = true;
209 $where['field'] = array_reverse( $nested );
210 }
211
212 return $where;
213 }
214
215 /**
216 * @param $field
217 * @param null $operator
218 * @param null $value
219 * @param string $boolean
220 *
221 * @return $this
222 * @see get_where_clause()
223 */
224 public function remove_where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
225 $where = $this->get_where_clause( $field, $operator, $value, $boolean );
226
227 foreach ( $this->where as $k => $v ) {
228 if ( $v == $where ) {
229 unset( $this->where[ $k ] );
230 }
231 }
232
233 return $this;
234 }
235
236 /**
237 * @param $field
238 * @param null $operator
239 * @param null $value
240 * @param string $boolean
241 *
242 * @return $this
243 * @see get_where_clause()
244 */
245 public function where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
246 $this->where[] = $this->get_where_clause( $field, $operator, $value, $boolean );
247
248 return $this;
249 }
250
251 /**
252 * @param $field
253 * @param null $operator
254 * @param null $value
255 *
256 * @return $this
257 * @see get_where_clause()
258 */
259 public function or_where( $field, $operator = null, $value = null ) {
260 return $this->where( $field, $operator, $value, 'OR' );
261 }
262
263 /**
264 * @param array $in
265 *
266 * @return $this
267 */
268 public function where_in( array $in ) {
269 return $this->where( 'id', 'in', $in );
270 }
271
272 public function where_is_null( $field ) {
273 return $this->where( $field, '', 'IS NULL' );
274 }
275
276 public function where_post_type( $post_type ) {
277 return $this->where( 'post_type', '=', $post_type );
278 }
279
280 private function parse_field( $field ) {
281 switch ( $field ) {
282 case 'id':
283 $field = $this->join ? 'pt.' . $this->query->primary_id_column : 'mt' . $this->query->meta_id_column;
284
285 break;
286 case 'meta_key':
287 case 'meta_value':
288 $field = 'mt.' . $field;
289
290 break;
291 case 'taxonomy':
292 case 'post_type':
293 $field = 'pt.' . $field;
294
295 break;
296 }
297
298 return $field;
299 }
300
301 private function parse_where( $where, $clauses ) {
302 global $wpdb;
303
304 foreach ( $clauses as $clause ) {
305
306 if ( $clause['nested'] ) {
307 $clause['field'][0]['boolean'] = null;
308
309 $where .= sprintf( ' %s ( %s ) ', $clause['boolean'], $this->parse_where( '', $clause['field'] ) );
310 } else {
311 switch ( $clause['operator'] ) {
312 case 'IN':
313 $clause['value'] = sprintf( ' ( %s ) ', implode( ', ', array_map( 'intval', $clause['value'] ) ) );
314
315 break;
316 default:
317 $valid_raw = [ 'IS NULL', 'IS NOT NULL' ];
318
319 if ( ! in_array( $clause['value'], $valid_raw ) ) {
320 $clause['value'] = $wpdb->prepare( '%s', $clause['value'] );
321 }
322 }
323
324 $clause['field'] = $this->parse_field( $clause['field'] );
325
326 $where .= implode( ' ', $clause );
327 }
328
329 }
330
331 return $where;
332 }
333
334 /**
335 * @return array
336 */
337 public function get() {
338 global $wpdb;
339
340 if ( ! $this->query ) {
341 return [];
342 }
343
344 // parse SELECT
345 $select = 'SELECT ';
346 $select .= $this->distinct ? 'DISTINCT ' : '';
347
348 if ( empty( $this->select ) ) {
349 $this->select( 'id' );
350 }
351
352 $fields = [];
353
354 foreach ( $this->select as $field ) {
355 $parsed = $this->parse_field( $field );
356
357 // output 'id' in the results
358 if ( 'id' === $field ) {
359 $parsed .= ' AS id';
360 }
361
362 $fields[] = $parsed;
363 }
364
365 if ( $this->count ) {
366 $fields[] = sprintf( 'COUNT(%s) AS count', $this->parse_field( $this->count ) );
367 }
368
369 $select .= implode( ', ', $fields );
370
371 // parse FROM
372 $from_tpl = ' FROM %s AS %s';
373
374 $from = sprintf( $from_tpl, $this->query->meta_table, 'mt' );
375 $join = '';
376
377 if ( $this->join ) {
378 $from = sprintf( $from_tpl, $this->query->primary_table, 'pt' );
379 $join = sprintf( ' %s JOIN %s AS mt ON mt.%s = pt.%s %s',
380 $this->join,
381 $this->query->meta_table,
382 $this->query->meta_id_column,
383 $this->query->primary_id_column,
384 $this->parse_where( '', $this->join_where )
385 );
386 }
387
388 // parse WHERE
389 $where = $this->parse_where( ' WHERE 1=1', $this->where );
390
391 // parse GROUP BY
392 $group_by = '';
393
394 if ( $this->group_by ) {
395 $group_by = ' GROUP BY ' . $this->parse_field( $this->group_by );
396 }
397
398 // parse ORDER BY
399 $order_by = '';
400
401 if ( ! empty( $this->order_by ) ) {
402 $order_by_clauses = [];
403
404 foreach ( $this->order_by as $order_by_clause ) {
405 $order_by_clauses[] = $this->parse_field( $order_by_clause['order_by'] ) . ' ' . $order_by_clause['order'];
406 }
407
408 $order_by = ' ORDER BY ' . implode( ', ', $order_by_clauses );
409 }
410
411 $limit = '';
412
413 if ( $this->limit ) {
414 $limit = ' LIMIT ' . $this->limit;
415 }
416
417 // build query and store it
418 $sql = $select . $from . $join . $where . $group_by . $order_by . $limit;
419
420 $this->set_sql( $sql );
421
422 $results = $wpdb->get_results( $sql );
423
424 if ( ! is_array( $results ) ) {
425 return [];
426 }
427
428 $return = $results;
429
430 if ( count( $fields ) === 1 ) {
431 $return = [];
432 $field = $this->select[0];
433
434 foreach ( $results as $result ) {
435 $return[] = $result->$field;
436 }
437 }
438
439 return $return;
440 }
441
442 /**
443 * Return last sql that was queried
444 * @return string
445 */
446 public function get_sql() {
447 $sql = preg_replace( '/ +/', ' ', $this->sql );
448 $sql = preg_replace( '/(SELECT|FROM|LEFT|INNER|WHERE|(AND|OR) \(|(AND|OR) (?!\()|ORDER BY|GROUP BY|LIMIT)/', "\n$1", $sql );
449
450 return $sql . "\n";
451 }
452
453 private function set_sql( $sql ) {
454 $this->sql = $sql;
455 }
456
457 /**
458 * @return WP_Meta_Query
459 */
460 public function get_query() {
461 return $this->query;
462 }
463
464 /**
465 * @param string $type
466 *
467 * @return bool
468 */
469 private function set_query( $type ) {
470 global $wpdb;
471
472 switch ( $type ) {
473 case 'user':
474 $table = $wpdb->users;
475 $id = 'ID';
476
477 break;
478 case 'comment':
479 $table = $wpdb->comments;
480 $id = 'comment_ID';
481
482 break;
483 case 'post':
484 $table = $wpdb->posts;
485 $id = 'ID';
486
487 break;
488 case 'term':
489 $table = $wpdb->terms;
490 $id = 'term_id';
491
492 break;
493
494 default:
495 return false;
496 }
497
498 $this->query = new WP_Meta_Query();
499 $this->query->get_sql( $type, $table, $id );
500
501 return true;
502 }
503
504 }