Make WordPress Core


Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/meta.php

    r18031 r18268  
    358358 * Given a meta query, generates SQL clauses to be appended to a main query
    359359 *
    360  * @since 3.1.0
    361  * @access private
    362  *
    363  * @param array $meta_query 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  *
     360 * @since 3.2.0
     361 *
     362 * @see WP_Meta_Query
     363 *
     364 * @param array (optional) $meta_query A meta query
    373365 * @param string $type Type of meta
    374366 * @param string $primary_table
     
    377369 * @return array( 'join' => $join_sql, 'where' => $where_sql )
    378370 */
    379 function _get_meta_sql( $meta_query, $type, $primary_table, $primary_id_column, $context = null ) {
    380     global $wpdb;
    381 
    382     if ( ! $meta_table = _get_meta_table( $type ) )
    383         return false;
    384 
    385     $meta_id_column = esc_sql( $type . '_id' );
    386 
    387     $join = '';
    388     $where = '';
    389     $i = 0;
    390     foreach ( $meta_query as $q ) {
    391         $meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : '';
    392         $meta_value = isset( $q['value'] ) ? $q['value'] : '';
    393         $meta_compare = isset( $q['compare'] ) ? strtoupper( $q['compare'] ) : '=';
    394         $meta_type = isset( $q['type'] ) ? strtoupper( $q['type'] ) : 'CHAR';
    395 
    396         if ( ! in_array( $meta_compare, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) )
    397             $meta_compare = '=';
    398 
    399         if ( 'NUMERIC' == $meta_type )
    400             $meta_type = 'SIGNED';
    401         elseif ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) )
    402             $meta_type = 'CHAR';
    403 
    404         if ( empty( $meta_key ) && empty( $meta_value ) )
    405             continue;
    406 
    407         $alias = $i ? 'mt' . $i : $meta_table;
    408 
    409         $join .= "\nINNER JOIN $meta_table";
    410         $join .= $i ? " AS $alias" : '';
    411         $join .= " ON ($primary_table.$primary_id_column = $alias.$meta_id_column)";
    412 
    413         $i++;
    414 
    415         if ( !empty( $meta_key ) )
    416             $where .= $wpdb->prepare( " AND $alias.meta_key = %s", $meta_key );
    417 
    418         if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
    419             if ( ! is_array( $meta_value ) )
    420                 $meta_value = preg_split( '/[,\s]+/', $meta_value );
     371function get_meta_sql( $meta_query = false, $type, $primary_table, $primary_id_column, $context = null ) {
     372    $meta_query_obj = new WP_Meta_Query( $meta_query );
     373    return $meta_query_obj->get_sql( $type, $primary_table, $primary_id_column, $context );
     374}
     375
     376/**
     377 * Container class for a multiple metadata query
     378 *
     379 * @since 3.2.0
     380 */
     381class WP_Meta_Query {
     382    /**
     383    * List of metadata queries. A single query is an associative array:
     384    * - 'key' string The meta key
     385    * - 'value' string|array The meta value
     386    * - 'compare' (optional) string How to compare the key to the value.
     387    *              Possible values: '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'.
     388    *              Default: '='
     389    * - 'type' string (optional) The type of the value.
     390    *              Possible values: 'NUMERIC', 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED'.
     391    *              Default: 'CHAR'
     392    *
     393    * @since 3.2.0
     394    * @access public
     395    * @var array
     396    */
     397    public $queries = array();
     398
     399    /**
     400     * The relation between the queries. Can be one of 'AND' or 'OR'.
     401     *
     402     * @since 3.2.0
     403     * @access public
     404     * @var string
     405     */
     406    public $relation;
     407
     408    /**
     409     * Constructor
     410     *
     411     * @param array (optional) $meta_query A meta query
     412     */
     413    function __construct( $meta_query = false ) {
     414        if ( !$meta_query )
     415            return;
     416
     417        if ( isset( $meta_query['relation'] ) && strtoupper( $meta_query['relation'] ) == 'OR' ) {
     418            $this->relation = 'OR';
    421419        } else {
    422             $meta_value = trim( $meta_value );
     420            $this->relation = 'AND';
    423421        }
    424422
    425         if ( empty( $meta_value ) )
    426             continue;
    427 
    428         if ( 'IN' == substr( $meta_compare, -2) ) {
    429             $meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')';
    430         } elseif ( 'BETWEEN' == substr( $meta_compare, -7) ) {
    431             $meta_value = array_slice( $meta_value, 0, 2 );
    432             $meta_compare_string = '%s AND %s';
    433         } elseif ( 'LIKE' == substr( $meta_compare, -4 ) ) {
    434             $meta_value = '%' . like_escape( $meta_value ) . '%';
    435             $meta_compare_string = '%s';
    436         } else {
    437             $meta_compare_string = '%s';
     423        $this->queries = array();
     424
     425        foreach ( $meta_query as $key => $query ) {
     426            if ( ! is_array( $query ) )
     427                continue;
     428
     429            $this->queries[] = $query;
    438430        }
    439 
    440         // @todo Temporary hack to support empty values. Do not use outside of core.
    441         if ( '_wp_zero_value' == $meta_value )
    442             $meta_value = 0;
    443 
    444         $where .= $wpdb->prepare( " AND CAST($alias.meta_value AS {$meta_type}) {$meta_compare} {$meta_compare_string}", $meta_value );
    445     }
    446 
    447     return apply_filters_ref_array( 'get_meta_sql', array( compact( 'join', 'where' ), $meta_query, $type, $primary_table, $primary_id_column, &$context ) );
    448 }
    449 
    450 /**
    451  * Populates the $meta_query property
    452  *
    453  * @access private
    454  * @since 3.1.0
    455  *
    456  * @param array $qv The query variables
    457  */
    458 function _parse_meta_query( &$qv ) {
    459     $meta_query = array();
    460 
    461     // Simple query needs to be first for orderby=meta_value to work correctly
    462     foreach ( array( 'key', 'value', 'compare', 'type' ) as $key ) {
    463         if ( !empty( $qv[ "meta_$key" ] ) )
    464             $meta_query[0][ $key ] = $qv[ "meta_$key" ];
    465     }
    466 
    467     if ( !empty( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ) {
    468         $meta_query = array_merge( $meta_query, $qv['meta_query'] );
    469     }
    470 
    471     $qv['meta_query'] = $meta_query;
     431    }
     432
     433    /**
     434     * Constructs a meta query based on 'meta_*' query vars
     435     *
     436     * @since 3.2.0
     437     * @access public
     438     *
     439     * @param array $qv The query variables
     440     */
     441    function parse_query_vars( $qv ) {
     442        $meta_query = array();
     443
     444        // Simple query needs to be first for orderby=meta_value to work correctly
     445        foreach ( array( 'key', 'compare', 'type' ) as $key ) {
     446            if ( !empty( $qv[ "meta_$key" ] ) )
     447                $meta_query[0][ $key ] = $qv[ "meta_$key" ];
     448        }
     449
     450        // WP_Query sets 'meta_value' = '' by default
     451        if ( isset( $qv[ 'meta_value' ] ) && '' !== $qv[ 'meta_value' ] )
     452            $meta_query[0]['value'] = $qv[ 'meta_value' ];
     453
     454        if ( !empty( $qv['meta_query'] ) && is_array( $qv['meta_query'] ) ) {
     455            $meta_query = array_merge( $meta_query, $qv['meta_query'] );
     456        }
     457
     458        $this->__construct( $meta_query );
     459    }
     460
     461    /**
     462     * Generates SQL clauses to be appended to a main query.
     463     *
     464     * @since 3.2.0
     465     * @access public
     466     *
     467     * @param string $type Type of meta
     468     * @param string $primary_table
     469     * @param string $primary_id_column
     470     * @param object $context (optional) The main query object
     471     * @return array( 'join' => $join_sql, 'where' => $where_sql )
     472     */
     473    function get_sql( $type, $primary_table, $primary_id_column, $context = null ) {
     474        global $wpdb;
     475
     476        if ( ! $meta_table = _get_meta_table( $type ) )
     477            return false;
     478
     479        $meta_id_column = esc_sql( $type . '_id' );
     480
     481        $join = array();
     482        $where = array();
     483
     484        foreach ( $this->queries as $k => $q ) {
     485            $meta_key = isset( $q['key'] ) ? trim( $q['key'] ) : '';
     486            $meta_compare = isset( $q['compare'] ) ? strtoupper( $q['compare'] ) : '=';
     487            $meta_type = isset( $q['type'] ) ? strtoupper( $q['type'] ) : 'CHAR';
     488
     489            if ( ! in_array( $meta_compare, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) )
     490                $meta_compare = '=';
     491
     492            if ( 'NUMERIC' == $meta_type )
     493                $meta_type = 'SIGNED';
     494            elseif ( ! in_array( $meta_type, array( 'BINARY', 'CHAR', 'DATE', 'DATETIME', 'DECIMAL', 'SIGNED', 'TIME', 'UNSIGNED' ) ) )
     495                $meta_type = 'CHAR';
     496
     497            $i = count( $join );
     498            $alias = $i ? 'mt' . $i : $meta_table;
     499
     500            // Set JOIN
     501            $join[$i]  = "INNER JOIN $meta_table";
     502            $join[$i] .= $i ? " AS $alias" : '';
     503            $join[$i] .= " ON ($primary_table.$primary_id_column = $alias.$meta_id_column)";
     504
     505            $where[$k] = '';
     506            if ( !empty( $meta_key ) )
     507                $where[$k] = $wpdb->prepare( "$alias.meta_key = %s", $meta_key );
     508
     509            if ( !isset( $q['value'] ) ) {
     510                if ( empty( $where[$k] ) )
     511                    unset( $join[$i] );
     512                continue;
     513            }
     514
     515            $meta_value = $q['value'];
     516
     517            if ( in_array( $meta_compare, array( 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN' ) ) ) {
     518                if ( ! is_array( $meta_value ) )
     519                    $meta_value = preg_split( '/[,\s]+/', $meta_value );
     520
     521                if ( empty( $meta_value ) ) {
     522                    unset( $join[$i] );
     523                    continue;
     524                }
     525            } else {
     526                $meta_value = trim( $meta_value );
     527            }
     528
     529            if ( 'IN' == substr( $meta_compare, -2) ) {
     530                $meta_compare_string = '(' . substr( str_repeat( ',%s', count( $meta_value ) ), 1 ) . ')';
     531            } elseif ( 'BETWEEN' == substr( $meta_compare, -7) ) {
     532                $meta_value = array_slice( $meta_value, 0, 2 );
     533                $meta_compare_string = '%s AND %s';
     534            } elseif ( 'LIKE' == substr( $meta_compare, -4 ) ) {
     535                $meta_value = '%' . like_escape( $meta_value ) . '%';
     536                $meta_compare_string = '%s';
     537            } else {
     538                $meta_compare_string = '%s';
     539            }
     540
     541            if ( ! empty( $where[$k] ) )
     542                $where[$k] .= ' AND ';
     543
     544            $where[$k] = ' (' . $where[$k] . $wpdb->prepare( "CAST($alias.meta_value AS {$meta_type}) {$meta_compare} {$meta_compare_string})", $meta_value );
     545        }
     546
     547        $where = array_filter( $where );
     548
     549        if ( empty( $where ) )
     550            $where = '';
     551        else
     552            $where = ' AND (' . implode( "\n{$this->relation} ", $where ) . ' )';
     553
     554        $join = implode( "\n", $join );
     555        if ( ! empty( $join ) )
     556            $join = ' ' . $join;
     557
     558        return apply_filters_ref_array( 'get_meta_sql', array( compact( 'join', 'where' ), $this->queries, $type, $primary_table, $primary_id_column, $context ) );
     559    }
    472560}
    473561
Note: See TracChangeset for help on using the changeset viewer.