PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 3.4.8
Admin Columns v3.4.8
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
508 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 = array();
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 = array();
43
44 /**
45 * @var array
46 */
47 private $where = array();
48
49 /**
50 * @var array
51 */
52 private $group_by = array();
53
54 /**
55 * @var array
56 */
57 private $order_by = array();
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 * @see get_where_clause()
127 *
128 * @param $field
129 * @param null $operator
130 * @param null $value
131 * @param string $boolean
132 *
133 * @return $this
134 */
135 public function join_where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
136 // set default join
137 if ( ! $this->join ) {
138 $this->join();
139 }
140
141 $this->join_where[] = $this->get_where_clause( $field, $operator, $value, $boolean );
142
143 return $this;
144 }
145
146 public function order_by( $order_by, $order = 'asc' ) {
147 $parts = explode( ',', $order_by );
148
149 foreach ( $parts as $order_by ) {
150 $this->order_by[] = array(
151 'order_by' => trim( $order_by ),
152 'order' => strtoupper( $order ),
153 );
154 }
155
156 return $this;
157 }
158
159 public function limit( $limit ) {
160 $this->limit = absint( $limit );
161 }
162
163 public function distinct() {
164 $this->distinct = true;
165
166 return $this;
167 }
168
169 /**
170 * Set a where clause
171 *
172 * @param string|array $field
173 * @param string $operator
174 * @param string|int|array $value
175 * @param string $boolean
176 *
177 * @return array
178 */
179 private function get_where_clause( $field, $operator = null, $value = null, $boolean = 'AND' ) {
180 // allows to omit operator
181 if ( null === $value ) {
182 $value = $operator;
183 $operator = '=';
184 }
185
186 $where = array(
187 'nested' => false,
188 'boolean' => strtoupper( $boolean ),
189 'field' => $field,
190 'operator' => strtoupper( $operator ),
191 'value' => $value,
192 );
193
194 // set default join
195 if ( $field === 'post_type' && ! $this->join ) {
196 $this->join();
197 }
198
199 $nested = array();
200
201 if ( is_array( $field ) ) {
202 $count = count( $field );
203 for ( $i = 0; $i < $count; $i++ ) {
204 $nested[] = array_pop( $this->where );
205 }
206 }
207
208 if ( $nested ) {
209 $where['nested'] = true;
210 $where['field'] = array_reverse( $nested );
211 }
212
213 return $where;
214 }
215
216 /**
217 * @see get_where_clause()
218 *
219 * @param $field
220 * @param null $operator
221 * @param null $value
222 * @param string $boolean
223 *
224 * @return $this
225 */
226 public function remove_where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
227 $where = $this->get_where_clause( $field, $operator, $value, $boolean );
228
229 foreach ( $this->where as $k => $v ) {
230 if ( $v == $where ) {
231 unset( $this->where[ $k ] );
232 }
233 }
234
235 return $this;
236 }
237
238 /**
239 * @see get_where_clause()
240 *
241 * @param $field
242 * @param null $operator
243 * @param null $value
244 * @param string $boolean
245 *
246 * @return $this
247 */
248 public function where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
249 $this->where[] = $this->get_where_clause( $field, $operator, $value, $boolean );
250
251 return $this;
252 }
253
254 /**
255 * @see get_where_clause()
256 *
257 * @param $field
258 * @param null $operator
259 * @param null $value
260 *
261 * @return $this
262 */
263 public function or_where( $field, $operator = null, $value = null ) {
264 return $this->where( $field, $operator, $value, 'OR' );
265 }
266
267 /**
268 * @param array $in
269 *
270 * @return $this
271 */
272 public function where_in( array $in ) {
273 return $this->where( 'id', 'in', $in );
274 }
275
276 public function where_is_null( $field ) {
277 return $this->where( $field, '', 'IS NULL' );
278 }
279
280 public function where_post_type( $post_type ) {
281 return $this->where( 'post_type', '=', $post_type );
282 }
283
284 private function parse_field( $field ) {
285 switch ( $field ) {
286 case 'id':
287 $field = $this->join ? 'pt.' . $this->query->primary_id_column : 'mt' . $this->query->meta_id_column;
288
289 break;
290 case 'meta_key':
291 case 'meta_value':
292 $field = 'mt.' . $field;
293
294 break;
295 case 'taxonomy':
296 case 'post_type':
297 $field = 'pt.' . $field;
298
299 break;
300 }
301
302 return $field;
303 }
304
305 private function parse_where( $where, $clauses ) {
306 global $wpdb;
307
308 foreach ( $clauses as $clause ) {
309
310 if ( $clause['nested'] ) {
311 $clause['field'][0]['boolean'] = null;
312
313 $where .= sprintf( ' %s ( %s ) ', $clause['boolean'], $this->parse_where( '', $clause['field'] ) );
314 } else {
315 switch ( $clause['operator'] ) {
316 case 'IN':
317 $clause['value'] = sprintf( ' ( %s ) ', implode( ', ', array_map( 'intval', $clause['value'] ) ) );
318
319 break;
320 default:
321 $valid_raw = array( 'IS NULL', 'IS NOT NULL' );
322
323 if ( ! in_array( $clause['value'], $valid_raw ) ) {
324 $clause['value'] = $wpdb->prepare( '%s', $clause['value'] );
325 }
326 }
327
328 $clause['field'] = $this->parse_field( $clause['field'] );
329
330 $where .= implode( ' ', $clause );
331 }
332
333 }
334
335 return $where;
336 }
337
338 /**
339 * @return array
340 */
341 public function get() {
342 global $wpdb;
343
344 if ( ! $this->query ) {
345 return array();
346 }
347
348 // parse SELECT
349 $select = 'SELECT ';
350 $select .= $this->distinct ? 'DISTINCT ' : '';
351
352 if ( empty( $this->select ) ) {
353 $this->select( 'id' );
354 }
355
356 $fields = array();
357
358 foreach ( $this->select as $field ) {
359 $parsed = $this->parse_field( $field );
360
361 // output 'id' in the results
362 if ( 'id' === $field ) {
363 $parsed .= ' AS id';
364 }
365
366 $fields[] = $parsed;
367 }
368
369 if ( $this->count ) {
370 $fields[] = sprintf( 'COUNT(%s) AS count', $this->parse_field( $this->count ) );
371 }
372
373 $select .= implode( ', ', $fields );
374
375 // parse FROM
376 $from_tpl = ' FROM %s AS %s';
377
378 $from = sprintf( $from_tpl, $this->query->meta_table, 'mt' );
379 $join = '';
380
381 if ( $this->join ) {
382 $from = sprintf( $from_tpl, $this->query->primary_table, 'pt' );
383 $join = sprintf( ' %s JOIN %s AS mt ON mt.%s = pt.%s %s',
384 $this->join,
385 $this->query->meta_table,
386 $this->query->meta_id_column,
387 $this->query->primary_id_column,
388 $this->parse_where( '', $this->join_where )
389 );
390 }
391
392 // parse WHERE
393 $where = $this->parse_where( ' WHERE 1=1', $this->where );
394
395 // parse GROUP BY
396 $group_by = '';
397
398 if ( $this->group_by ) {
399 $group_by = ' GROUP BY ' . $this->parse_field( $this->group_by );
400 }
401
402 // parse ORDER BY
403 $order_by = '';
404
405 if ( ! empty( $this->order_by ) ) {
406 $order_by_clauses = array();
407
408 foreach ( $this->order_by as $order_by_clause ) {
409 $order_by_clauses[] = $this->parse_field( $order_by_clause['order_by'] ) . ' ' . $order_by_clause['order'];
410 }
411
412 $order_by = ' ORDER BY ' . implode( ', ', $order_by_clauses );
413 }
414
415 $limit = '';
416
417 if ( $this->limit ) {
418 $limit = ' LIMIT ' . $this->limit;
419 }
420
421 // build query and store it
422 $sql = $select . $from . $join . $where . $group_by . $order_by . $limit;
423
424 $this->set_sql( $sql );
425
426 $results = $wpdb->get_results( $sql );
427
428 if ( ! is_array( $results ) ) {
429 return array();
430 }
431
432 $return = $results;
433
434 if ( count( $fields ) === 1 ) {
435 $return = array();
436 $field = $this->select[0];
437
438 foreach ( $results as $result ) {
439 $return[] = $result->$field;
440 }
441 }
442
443 return $return;
444 }
445
446 /**
447 * Return last sql that was queried
448 * @return string
449 */
450 public function get_sql() {
451 $sql = preg_replace( '/ +/', ' ', $this->sql );
452 $sql = preg_replace( '/(SELECT|FROM|LEFT|INNER|WHERE|(AND|OR) \(|(AND|OR) (?!\()|ORDER BY|GROUP BY|LIMIT)/', "\n$1", $sql );
453
454 return $sql . "\n";
455 }
456
457 private function set_sql( $sql ) {
458 $this->sql = $sql;
459 }
460
461 /**
462 * @return WP_Meta_Query
463 */
464 public function get_query() {
465 return $this->query;
466 }
467
468 /**
469 * @param string $type
470 *
471 * @return bool
472 */
473 private function set_query( $type ) {
474 global $wpdb;
475
476 switch ( $type ) {
477 case 'user':
478 $table = $wpdb->users;
479 $id = 'ID';
480
481 break;
482 case 'comment':
483 $table = $wpdb->comments;
484 $id = 'comment_ID';
485
486 break;
487 case 'post':
488 $table = $wpdb->posts;
489 $id = 'ID';
490
491 break;
492 case 'term':
493 $table = $wpdb->terms;
494 $id = 'term_id';
495
496 break;
497
498 default:
499 return false;
500 }
501
502 $this->query = new WP_Meta_Query();
503 $this->query->get_sql( $type, $table, $id );
504
505 return true;
506 }
507
508 }