PluginProbe ʕ •ᴥ•ʔ
Admin Columns / 3.4.1
Admin Columns v3.4.1
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 7 years ago QueryColumn.php 7 years ago
Query.php
507 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 for ( $i = 0; $i < count( $field ); $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 * @see get_where_clause()
217 *
218 * @param $field
219 * @param null $operator
220 * @param null $value
221 * @param string $boolean
222 *
223 * @return $this
224 */
225 public function remove_where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
226 $where = $this->get_where_clause( $field, $operator, $value, $boolean );
227
228 foreach ( $this->where as $k => $v ) {
229 if ( $v == $where ) {
230 unset( $this->where[ $k ] );
231 }
232 }
233
234 return $this;
235 }
236
237 /**
238 * @see get_where_clause()
239 *
240 * @param $field
241 * @param null $operator
242 * @param null $value
243 * @param string $boolean
244 *
245 * @return $this
246 */
247 public function where( $field, $operator = null, $value = null, $boolean = 'AND' ) {
248 $this->where[] = $this->get_where_clause( $field, $operator, $value, $boolean );
249
250 return $this;
251 }
252
253 /**
254 * @see get_where_clause()
255 *
256 * @param $field
257 * @param null $operator
258 * @param null $value
259 *
260 * @return $this
261 */
262 public function or_where( $field, $operator = null, $value = null ) {
263 return $this->where( $field, $operator, $value, 'OR' );
264 }
265
266 /**
267 * @param array $in
268 *
269 * @return $this
270 */
271 public function where_in( array $in ) {
272 return $this->where( 'id', 'in', $in );
273 }
274
275 public function where_is_null( $field ) {
276 return $this->where( $field, '', 'IS NULL' );
277 }
278
279 public function where_post_type( $post_type ) {
280 return $this->where( 'post_type', '=', $post_type );
281 }
282
283 private function parse_field( $field ) {
284 switch ( $field ) {
285 case 'id':
286 $field = $this->join ? 'pt.' . $this->query->primary_id_column : 'mt' . $this->query->meta_id_column;
287
288 break;
289 case 'meta_key':
290 case 'meta_value':
291 $field = 'mt.' . $field;
292
293 break;
294 case 'taxonomy':
295 case 'post_type':
296 $field = 'pt.' . $field;
297
298 break;
299 }
300
301 return $field;
302 }
303
304 private function parse_where( $where, $clauses ) {
305 global $wpdb;
306
307 foreach ( $clauses as $clause ) {
308
309 if ( $clause['nested'] ) {
310 $clause['field'][0]['boolean'] = null;
311
312 $where .= sprintf( ' %s ( %s ) ', $clause['boolean'], $this->parse_where( '', $clause['field'] ) );
313 } else {
314 switch ( $clause['operator'] ) {
315 case 'IN':
316 $clause['value'] = sprintf( ' ( %s ) ', implode( ', ', array_map( 'intval', $clause['value'] ) ) );
317
318 break;
319 default:
320 $valid_raw = array( 'IS NULL', 'IS NOT NULL' );
321
322 if ( ! in_array( $clause['value'], $valid_raw ) ) {
323 $clause['value'] = $wpdb->prepare( '%s', $clause['value'] );
324 }
325 }
326
327 $clause['field'] = $this->parse_field( $clause['field'] );
328
329 $where .= implode( ' ', $clause );
330 }
331
332 }
333
334 return $where;
335 }
336
337 /**
338 * @return array
339 */
340 public function get() {
341 global $wpdb;
342
343 if ( ! $this->query ) {
344 return array();
345 }
346
347 // parse SELECT
348 $select = 'SELECT ';
349 $select .= $this->distinct ? 'DISTINCT ' : '';
350
351 if ( empty( $this->select ) ) {
352 $this->select( 'id' );
353 }
354
355 $fields = array();
356
357 foreach ( $this->select as $field ) {
358 $parsed = $this->parse_field( $field );
359
360 // output 'id' in the results
361 if ( 'id' === $field ) {
362 $parsed .= ' AS id';
363 }
364
365 $fields[] = $parsed;
366 }
367
368 if ( $this->count ) {
369 $fields[] = sprintf( 'COUNT(%s) AS count', $this->parse_field( $this->count ) );
370 }
371
372 $select .= implode( ', ', $fields );
373
374 // parse FROM
375 $from_tpl = ' FROM %s AS %s';
376
377 $from = sprintf( $from_tpl, $this->query->meta_table, 'mt' );
378 $join = '';
379
380 if ( $this->join ) {
381 $from = sprintf( $from_tpl, $this->query->primary_table, 'pt' );
382 $join = sprintf( ' %s JOIN %s AS mt ON mt.%s = pt.%s %s',
383 $this->join,
384 $this->query->meta_table,
385 $this->query->meta_id_column,
386 $this->query->primary_id_column,
387 $this->parse_where( '', $this->join_where )
388 );
389 }
390
391 // parse WHERE
392 $where = $this->parse_where( ' WHERE 1=1', $this->where );
393
394 // parse GROUP BY
395 $group_by = '';
396
397 if ( $this->group_by ) {
398 $group_by = ' GROUP BY ' . $this->parse_field( $this->group_by );
399 }
400
401 // parse ORDER BY
402 $order_by = '';
403
404 if ( ! empty( $this->order_by ) ) {
405 $order_by_clauses = array();
406
407 foreach ( $this->order_by as $order_by_clause ) {
408 $order_by_clauses[] = $this->parse_field( $order_by_clause['order_by'] ) . ' ' . $order_by_clause['order'];
409 }
410
411 $order_by = ' ORDER BY ' . implode( ', ', $order_by_clauses );
412 }
413
414 $limit = '';
415
416 if ( $this->limit ) {
417 $limit = ' LIMIT ' . $this->limit;
418 }
419
420 // build query and store it
421 $sql = $select . $from . $join . $where . $group_by . $order_by . $limit;
422
423 $this->set_sql( $sql );
424
425 $results = $wpdb->get_results( $sql );
426
427 if ( ! is_array( $results ) ) {
428 return array();
429 }
430
431 $return = $results;
432
433 if ( count( $fields ) === 1 ) {
434 $return = array();
435 $field = $this->select[0];
436
437 foreach ( $results as $result ) {
438 $return[] = $result->$field;
439 }
440 }
441
442 return $return;
443 }
444
445 /**
446 * Return last sql that was queried
447 * @return string
448 */
449 public function get_sql() {
450 $sql = preg_replace( '/ +/', ' ', $this->sql );
451 $sql = preg_replace( '/(SELECT|FROM|LEFT|INNER|WHERE|(AND|OR) \(|(AND|OR) (?!\()|ORDER BY|GROUP BY|LIMIT)/', "\n$1", $sql );
452
453 return $sql . "\n";
454 }
455
456 private function set_sql( $sql ) {
457 $this->sql = $sql;
458 }
459
460 /**
461 * @return WP_Meta_Query
462 */
463 public function get_query() {
464 return $this->query;
465 }
466
467 /**
468 * @param string $type
469 *
470 * @return bool
471 */
472 private function set_query( $type ) {
473 global $wpdb;
474
475 switch ( $type ) {
476 case 'user':
477 $table = $wpdb->users;
478 $id = 'ID';
479
480 break;
481 case 'comment':
482 $table = $wpdb->comments;
483 $id = 'comment_ID';
484
485 break;
486 case 'post':
487 $table = $wpdb->posts;
488 $id = 'ID';
489
490 break;
491 case 'term':
492 $table = $wpdb->terms;
493 $id = 'term_id';
494
495 break;
496
497 default:
498 return false;
499 }
500
501 $this->query = new WP_Meta_Query();
502 $this->query->get_sql( $type, $table, $id );
503
504 return true;
505 }
506
507 }