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