| 358 | | * @since 3.1.0 |
| 359 | | * @access private |
| 360 | | * |
| 361 | | * @param array $meta_query List of metadata queries. A single query is an associative array: |
| 362 | | * - 'key' string The meta key |
| 363 | | * - 'value' string|array The meta value |
| 364 | | * - 'compare' (optional) string How to compare the key to the value. |
| 365 | | * Possible values: '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. |
| 366 | | * Default: '=' |
| 367 | | * - 'type' string (optional) The type of the value. |
| 368 | | * Possible values: 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. |
| 369 | | * Default: 'CHAR' |
| 370 | | * |
| 371 | | * @param string $type Type of meta |
| 372 | | * @param string $primary_table |
| 373 | | * @param string $primary_id_column |
| 374 | | * @param object $context (optional) The main query object |
| 375 | | * @return array( 'join' => $join_sql, 'where' => $where_sql ) |
| | 358 | * @since 3.2 |
| 380 | | if ( ! $meta_table = _get_meta_table( $type ) ) |
| 381 | | return false; |
| | 362 | /** |
| | 363 | * List of metadata queries. A single query is an associative array: |
| | 364 | * - 'key' string The meta key |
| | 365 | * - 'value' string|array The meta value |
| | 366 | * - 'compare' (optional) string How to compare the key to the value. |
| | 367 | * Possible values: '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'. |
| | 368 | * Default: '=' |
| | 369 | * - 'type' string (optional) The type of the value. |
| | 370 | * Possible values: 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'. |
| | 371 | * Default: 'CHAR' |
| | 372 | * |
| | 373 | * @since 3.2 |
| | 374 | * @access public |
| | 375 | * @var array |
| | 376 | */ |
| | 377 | public $queries = array(); |
| 385 | | $join = ''; |
| 386 | | $where = ''; |
| 387 | | $i = 0; |
| 388 | | foreach ( $meta_query as $q ) { |
| 389 | | $meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : ''; |
| 390 | | $meta_value = isset( $q['value'] ) ? $q['value'] : ''; |
| 391 | | $meta_compare = isset( $q['compare'] ) ? strtoupper( $q['compare'] ) : '='; |
| 392 | | $meta_type = isset( $q['type'] ) ? strtoupper( $q['type'] ) : 'CHAR'; |
| | 389 | /** |
| | 390 | * Populates the $queries property by looking for 'meta_*' query variables |
| | 391 | * |
| | 392 | * @since 3.2 |
| | 393 | * @access public |
| | 394 | * |
| | 395 | * @param array $qv The query variables |
| | 396 | */ |
| | 397 | function parse_query_vars( $qv ) { |
| | 398 | $this->queries = array(); |
| 394 | | if ( ! in_array( $meta_compare, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) |
| 395 | | $meta_compare = '='; |
| | 400 | // Simple query needs to be first for orderby=meta_value to work correctly |
| | 401 | foreach ( array( 'key', 'value', 'compare', 'type' ) as $key ) { |
| | 402 | if ( !empty( $qv[ "meta_$key" ] ) ) |
| | 403 | $this->queries[0][ $key ] = $qv[ "meta_$key" ]; |
| | 404 | } |
| 402 | | if ( empty( $meta_key ) && empty( $meta_value ) ) |
| 403 | | continue; |
| | 411 | /** |
| | 412 | * Generates SQL clauses to be appended to a main query. |
| | 413 | * |
| | 414 | * @since 3.2 |
| | 415 | * @access public |
| | 416 | * |
| | 417 | * @param string $type Type of meta |
| | 418 | * @param string $primary_table |
| | 419 | * @param string $primary_id_column |
| | 420 | * @param object $context (optional) The main query object |
| | 421 | * @return array( 'join' => $join_sql, 'where' => $where_sql ) |
| | 422 | */ |
| | 423 | function get_sql( $type, $primary_table, $primary_id_column, $context = null ) { |
| | 424 | global $wpdb; |
| 413 | | if ( !empty( $meta_key ) ) |
| 414 | | $where .= $wpdb->prepare( " AND $alias.meta_key = %s", $meta_key ); |
| | 440 | if ( ! in_array( $meta_compare, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) |
| | 441 | $meta_compare = '='; |
| 416 | | if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { |
| 417 | | if ( ! is_array( $meta_value ) ) |
| 418 | | $meta_value = preg_split( '/[,\s]+/', $meta_value ); |
| 419 | | } else { |
| 420 | | $meta_value = trim( $meta_value ); |
| 421 | | } |
| | 443 | if ( 'NUMERIC' == $meta_type ) |
| | 444 | $meta_type = 'SIGNED'; |
| | 445 | elseif ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) ) |
| | 446 | $meta_type = 'CHAR'; |
| 426 | | if ( 'IN' == substr( $meta_compare, -2) ) { |
| 427 | | $meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')'; |
| 428 | | } elseif ( 'BETWEEN' == substr( $meta_compare, -7) ) { |
| 429 | | $meta_value = array_slice( $meta_value, 0, 2 ); |
| 430 | | $meta_compare_string = '%s AND %s'; |
| 431 | | } elseif ( 'LIKE' == substr( $meta_compare, -4 ) ) { |
| 432 | | $meta_value = '%' . like_escape( $meta_value ) . '%'; |
| 433 | | $meta_compare_string = '%s'; |
| 434 | | } else { |
| 435 | | $meta_compare_string = '%s'; |
| 436 | | } |
| | 451 | $alias = $i ? 'mt' . $i : $meta_table; |
| 448 | | /** |
| 449 | | * Populates the $meta_query property |
| 450 | | * |
| 451 | | * @access private |
| 452 | | * @since 3.1.0 |
| 453 | | * |
| 454 | | * @param array $qv The query variables |
| 455 | | */ |
| 456 | | function _parse_meta_query( &$qv ) { |
| 457 | | $meta_query = array(); |
| | 462 | if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) { |
| | 463 | if ( ! is_array( $meta_value ) ) |
| | 464 | $meta_value = preg_split( '/[,\s]+/', $meta_value ); |
| | 465 | } else { |
| | 466 | $meta_value = trim( $meta_value ); |
| | 467 | } |
| 465 | | if ( !empty( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ) { |
| 466 | | $meta_query = array_merge( $meta_query, $qv['meta_query'] ); |
| | 472 | if ( 'IN' == substr( $meta_compare, -2) ) { |
| | 473 | $meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')'; |
| | 474 | } elseif ( 'BETWEEN' == substr( $meta_compare, -7) ) { |
| | 475 | $meta_value = array_slice( $meta_value, 0, 2 ); |
| | 476 | $meta_compare_string = '%s AND %s'; |
| | 477 | } elseif ( 'LIKE' == substr( $meta_compare, -4 ) ) { |
| | 478 | $meta_value = '%' . like_escape( $meta_value ) . '%'; |
| | 479 | $meta_compare_string = '%s'; |
| | 480 | } else { |
| | 481 | $meta_compare_string = '%s'; |
| | 482 | } |
| | 483 | |
| | 484 | // @todo Temporary hack to support empty values. Do not use outside of core. |
| | 485 | if ( '_wp_zero_value' == $meta_value ) |
| | 486 | $meta_value = 0; |
| | 487 | |
| | 488 | $where .= $wpdb->prepare( " AND CAST($alias.meta_value AS {$meta_type}) {$meta_compare} {$meta_compare_string}", $meta_value ); |
| | 489 | } |
| | 490 | |
| | 491 | return apply_filters_ref_array( 'get_meta_sql', array( compact( 'join', 'where' ), $this->queries, $type, $primary_table, $primary_id_column, $context ) ); |