WordPress.org

Make WordPress Core

Ticket #17194: 17194.diff

File 17194.diff, 5.7 KB (added by scribu, 7 years ago)
  • wp-includes/taxonomy.php

     
    539539         *              Possible values: 'term_id', 'slug' or 'name'
    540540         *              Default: 'term_id'
    541541         * - 'operator' string (optional)
    542          *              Possible values: 'IN' and 'NOT IN'.
     542         *              Possible values: 'AND', 'IN' or 'NOT IN'.
    543543         *              Default: 'IN'
    544544         * - 'include_children' bool (optional) Whether to include child terms.
    545545         *              Default: true
     
    548548         * @access public
    549549         * @var array
    550550         */
    551         var $queries = array();
     551        public $queries = array();
    552552
    553553        /**
    554554         * The relation between the queries. Can be one of 'AND' or 'OR'.
     
    557557         * @access public
    558558         * @var string
    559559         */
    560         var $relation;
     560        public $relation;
    561561
    562562        /**
    563          * PHP4 type constructor.
     563         * Standard response when the query should not return any rows.
    564564         *
     565         * @since 3.2.0
     566         * @access private
     567         * @var string
     568         */
     569        private static $no_results = array( 'join' => '', 'where' => ' AND 0 = 1' );
     570
     571        /**
     572         * Constructor.
     573         *
    565574         * Parses a compact tax query and sets defaults.
    566575         *
    567576         * @since 3.1.0
     
    581590         *      'field' => 'slug',
    582591         *    ),
    583592         *  )
    584          *
    585          * @return WP_Tax_Query
    586593         */
    587         function WP_Tax_Query( $tax_query ) {
     594        public function __construct( $tax_query ) {
    588595                if ( isset( $tax_query['relation'] ) && strtoupper( $tax_query['relation'] ) == 'OR' ) {
    589596                        $this->relation = 'OR';
    590597                } else {
     
    621628         * @param string $primary_id_column
    622629         * @return array
    623630         */
    624         function get_sql( $primary_table, $primary_id_column ) {
     631        public function get_sql( $primary_table, $primary_id_column ) {
    625632                global $wpdb;
    626633
    627634                $join = '';
     
    629636                $i = 0;
    630637
    631638                foreach ( $this->queries as $query ) {
     639                        try {
     640                                $this->clean_query( $query );
     641                        } catch ( Exception $e ) {
     642                                return self::$no_results;
     643                        }
     644
    632645                        extract( $query );
    633646
    634                         if ( ! taxonomy_exists( $taxonomy ) )
    635                                 return array( 'join' => '', 'where' => ' AND 0 = 1');
    636 
    637                         $terms = array_unique( (array) $terms );
    638 
    639                         if ( empty( $terms ) )
    640                                 continue;
    641 
    642                         if ( is_taxonomy_hierarchical( $taxonomy ) && $include_children ) {
    643                                 $this->_transform_terms( $terms, $taxonomy, $field, 'term_id' );
    644 
    645                                 $children = array();
    646                                 foreach ( $terms as $term ) {
    647                                         $children = array_merge( $children, get_term_children( $term, $taxonomy ) );
    648                                         $children[] = $term;
    649                                 }
    650                                 $terms = $children;
    651 
    652                                 $this->_transform_terms( $terms, $taxonomy, 'term_id', 'term_taxonomy_id' );
    653                         }
    654                         else {
    655                                 $this->_transform_terms( $terms, $taxonomy, $field, 'term_taxonomy_id' );
    656                         }
    657 
    658647                        if ( 'IN' == $operator ) {
    659648
    660649                                if ( empty( $terms ) ) {
    661650                                        if ( 'OR' == $this->relation )
    662651                                                continue;
    663652                                        else
    664                                                 return array( 'join' => '', 'where' => ' AND 0 = 1' );
     653                                                return self::$no_results;
    665654                                }
    666655
    667656                                $terms = implode( ',', $terms );
     
    714703        }
    715704
    716705        /**
    717          * Transforms a list of terms, from one field to another.
     706         * Validates a single query.
    718707         *
    719          * @since 3.1.0
     708         * @since 3.2.0
    720709         * @access private
    721710         *
    722          * @param array &$terms The list of terms
    723          * @param string $taxonomy The taxonomy of the terms
    724          * @param string $field The initial field
     711         * @param array &$query The single query
     712         */
     713        private function clean_query( &$query ) {
     714                if ( ! taxonomy_exists( $query['taxonomy'] ) )
     715                        throw new Exception( 'Invalid taxonomy' );
     716
     717                $query['terms'] = array_unique( (array) $query['terms'] );
     718
     719                if ( is_taxonomy_hierarchical( $query['taxonomy'] ) && $query['include_children'] ) {
     720                        $this->transform_query( $query, 'term_id' );
     721
     722                        $children = array();
     723                        foreach ( $query['terms'] as $term ) {
     724                                $children = array_merge( $children, get_term_children( $term, $query['taxonomy'] ) );
     725                                $children[] = $term;
     726                        }
     727                        $query['terms'] = $children;
     728                }
     729
     730                $this->transform_query( $query, 'term_taxonomy_id' );
     731        }
     732
     733        /**
     734         * Transforms a single query, from one field to another.
     735         *
     736         * @since 3.2.0
     737         * @access private
     738         *
     739         * @param array &$query The single query
    725740         * @param string $resulting_field The resulting field
    726741         */
    727         function _transform_terms( &$terms, $taxonomy, $field, $resulting_field ) {
     742        private function transform_query( &$query, $resulting_field ) {
    728743                global $wpdb;
    729744
    730                 if ( empty( $terms ) )
     745                if ( empty( $query['terms'] ) )
    731746                        return;
    732747
    733                 if ( $field == $resulting_field )
     748                if ( $query['field'] == $resulting_field )
    734749                        return;
    735750
    736751                $resulting_field = esc_sql( $resulting_field );
    737752
    738                 switch ( $field ) {
     753                switch ( $query['field'] ) {
    739754                        case 'slug':
    740755                        case 'name':
    741                                 $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $terms ) ) . "'";
     756                                $terms = "'" . implode( "','", array_map( 'sanitize_title_for_query', $query['terms'] ) ) . "'";
    742757                                $terms = $wpdb->get_col( "
    743758                                        SELECT $wpdb->term_taxonomy.$resulting_field
    744759                                        FROM $wpdb->term_taxonomy
    745760                                        INNER JOIN $wpdb->terms USING (term_id)
    746                                         WHERE taxonomy = '$taxonomy'
    747                                         AND $wpdb->terms.$field IN ($terms)
     761                                        WHERE taxonomy = '{$query['taxonomy']}'
     762                                        AND $wpdb->terms.{$query['field']} IN ($terms)
    748763                                " );
    749764                                break;
    750765
    751766                        default:
    752                                 $terms = implode( ',', array_map( 'intval', $terms ) );
     767                                $terms = implode( ',', array_map( 'intval', $query['terms'] ) );
    753768                                $terms = $wpdb->get_col( "
    754769                                        SELECT $resulting_field
    755770                                        FROM $wpdb->term_taxonomy
    756                                         WHERE taxonomy = '$taxonomy'
     771                                        WHERE taxonomy = '{$query['taxonomy']}'
    757772                                        AND term_id IN ($terms)
    758773                                " );
    759774                }
     775
     776                if ( 'AND' == $query['operator'] && count( $terms ) < count( $query['terms'] ) ) {
     777                        throw new Exception( 'Inexistent terms' );
     778                }
     779
     780                $query['terms'] = $terms;
     781                $query['field'] = $resulting_field;
    760782        }
    761783}
    762784