WordPress.org

Make WordPress Core

Ticket #17065: 17065.5.diff

File 17065.5.diff, 8.1 KB (added by johnbillion, 5 years ago)
  • src/wp-includes/query.php

     
    22002200        }
    22012201
    22022202        /**
     2203         * If the passed orderby value is allowed, convert the alias to a properly-prefixed orderby value
     2204         *
     2205         * @since 4.0.0
     2206         *
     2207         * @global wpdb $wpdb
     2208         * @param string $orderby Alias for the field to order by.
     2209         * @return string Table-prefixed value to used in the ORDER clause.
     2210         */
     2211        protected function parse_orderby( $orderby ) {
     2212                global $wpdb;
     2213
     2214                // Used to filter values
     2215                $allowed_keys = array(
     2216                        'post_name', 'post_author', 'post_date', 'post_title', 'post_modified', 'post_parent', 'post_type',
     2217                        'name', 'author', 'date', 'title', 'modified', 'parent', 'type',
     2218                        'ID', 'menu_order', 'comment_count',
     2219                        'rand',
     2220                );
     2221                $meta_key = $this->get( 'meta_key' );
     2222                if ( ! empty( $meta_key ) ) {
     2223                        $allowed_keys[] = $meta_key;
     2224                        $allowed_keys[] = 'meta_value';
     2225                        $allowed_keys[] = 'meta_value_num';
     2226                }
     2227
     2228                if ( ! in_array( $orderby, $allowed_keys ) ) {
     2229                        return false;
     2230                }
     2231
     2232                switch ( $orderby ) {
     2233
     2234                        case 'post_name':
     2235                        case 'post_author':
     2236                        case 'post_date':
     2237                        case 'post_title':
     2238                        case 'post_modified':
     2239                        case 'post_parent':
     2240                        case 'post_type':
     2241                        case 'ID':
     2242                        case 'menu_order':
     2243                        case 'comment_count':
     2244                                $orderby = "$wpdb->posts.{$orderby}";
     2245                                break;
     2246                        case 'rand':
     2247                                $orderby = 'RAND()';
     2248                                break;
     2249                        case $meta_key:
     2250                        case 'meta_value':
     2251                                $type = $this->get( 'meta_type' );
     2252                                if ( ! empty( $type ) ) {
     2253                                        $meta_type = $this->meta_query->get_cast_for_type( $type );
     2254                                        $orderby = "CAST($wpdb->postmeta.meta_value AS {$meta_type})";
     2255                                } else {
     2256                                        $orderby = "$wpdb->postmeta.meta_value";
     2257                                }
     2258                                break;
     2259                        case 'meta_value_num':
     2260                                $orderby = "$wpdb->postmeta.meta_value+0";
     2261                                break;
     2262                        default:
     2263                                $orderby = "$wpdb->posts.post_" . $orderby;
     2264                                break;
     2265                }
     2266
     2267                return $orderby;
     2268        }
     2269
     2270        /**
     2271         * Parse an 'order' query variable and cast it to ASC or DESC as necessary.
     2272         *
     2273         * @since 4.0.0
     2274         *
     2275         * @param string $order The 'order' query variable.
     2276         * @return string The sanitized 'order' query variable.
     2277         */
     2278        protected function parse_order( $order ) {
     2279                if ( !is_string( $order ) or empty( $order ) ) {
     2280                        return 'DESC';
     2281                }
     2282
     2283                if ( strtoupper( $order ) == 'ASC' ) {
     2284                        return 'ASC';
     2285                } else {
     2286                        return 'DESC';
     2287                }
     2288        }
     2289
     2290        /**
    22032291         * Sets the 404 property and saves whether query is feed.
    22042292         *
    22052293         * @since 2.0.0
     
    27022790
    27032791                $where .= $search . $whichauthor . $whichmimetype;
    27042792
    2705                 if ( empty($q['order']) || ((strtoupper($q['order']) != 'ASC') && (strtoupper($q['order']) != 'DESC')) )
     2793                if ( !isset( $q['order'] ) ) {
    27062794                        $q['order'] = 'DESC';
     2795                } else {
     2796                        $q['order'] = $this->parse_order( $q['order'] );
     2797                }
    27072798
    27082799                // Order by
    2709                 if ( empty($q['orderby']) ) {
    2710                         $orderby = "$wpdb->posts.post_date " . $q['order'];
     2800                if ( empty( $q['orderby'] ) ) {
     2801                        // Boolean false or empty array blanks out ORDER BY,
     2802                        // while leaving the value unset or otherwise empty sets the default.
     2803                        if ( isset( $q['orderby'] ) && ( is_array( $q['orderby'] ) || false === $q['orderby'] ) ) {
     2804                                $orderby = '';
     2805                        } else {
     2806                                $orderby = "$wpdb->posts.post_date " . $q['order'];
     2807                        }
    27112808                } elseif ( 'none' == $q['orderby'] ) {
    27122809                        $orderby = '';
    27132810                } elseif ( $q['orderby'] == 'post__in' && ! empty( $post__in ) ) {
     
    27152812                } elseif ( $q['orderby'] == 'post_parent__in' && ! empty( $post_parent__in ) ) {
    27162813                        $orderby = "FIELD( {$wpdb->posts}.post_parent, $post_parent__in )";
    27172814                } else {
    2718                         // Used to filter values
    2719                         $allowed_keys = array( 'name', 'author', 'date', 'title', 'modified', 'menu_order', 'parent', 'ID', 'rand', 'comment_count', 'type' );
    2720                         if ( !empty($q['meta_key']) ) {
    2721                                 $allowed_keys[] = $q['meta_key'];
    2722                                 $allowed_keys[] = 'meta_value';
    2723                                 $allowed_keys[] = 'meta_value_num';
    2724                         }
    2725                         $q['orderby'] = urldecode($q['orderby']);
    2726                         $q['orderby'] = addslashes_gpc($q['orderby']);
    2727 
    27282815                        $orderby_array = array();
    2729                         foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
    2730                                 // Only allow certain values for safety
    2731                                 if ( ! in_array($orderby, $allowed_keys) )
    2732                                         continue;
     2816                        if ( is_array( $q['orderby'] ) ) {
     2817                                foreach ( $q['orderby'] as $_orderby => $order ) {
     2818                                        $orderby = addslashes_gpc( urldecode( $_orderby ) );
     2819                                        $parsed = $this->parse_orderby( $orderby );
     2820                                        if ( ! $parsed ) {
     2821                                                continue;
     2822                                        }
     2823                                        $orderby_array[] = $parsed . ' ' . $this->parse_order( $order );
     2824                                }
     2825                                $orderby = implode( ', ', $orderby_array );
     2826                        } else {
     2827                                $q['orderby'] = urldecode($q['orderby']);
     2828                                $q['orderby'] = addslashes_gpc($q['orderby']);
    27332829
    2734                                 switch ( $orderby ) {
    2735                                         case 'menu_order':
    2736                                                 $orderby = "$wpdb->posts.menu_order";
    2737                                                 break;
    2738                                         case 'ID':
    2739                                                 $orderby = "$wpdb->posts.ID";
    2740                                                 break;
    2741                                         case 'rand':
    2742                                                 $orderby = 'RAND()';
    2743                                                 break;
    2744                                         case $q['meta_key']:
    2745                                         case 'meta_value':
    2746                                                 if ( isset( $q['meta_type'] ) ) {
    2747                                                         $meta_type = $this->meta_query->get_cast_for_type( $q['meta_type'] );
    2748                                                         $orderby = "CAST($wpdb->postmeta.meta_value AS {$meta_type})";
    2749                                                 } else {
    2750                                                         $orderby = "$wpdb->postmeta.meta_value";
    2751                                                 }
    2752                                                 break;
    2753                                         case 'meta_value_num':
    2754                                                 $orderby = "$wpdb->postmeta.meta_value+0";
    2755                                                 break;
    2756                                         case 'comment_count':
    2757                                                 $orderby = "$wpdb->posts.comment_count";
    2758                                                 break;
    2759                                         default:
    2760                                                 $orderby = "$wpdb->posts.post_" . $orderby;
     2830                                foreach ( explode( ' ', $q['orderby'] ) as $i => $orderby ) {
     2831                                        $parsed = $this->parse_orderby( $orderby );
     2832                                        // Only allow certain values for safety
     2833                                        if ( ! $parsed ) {
     2834                                                continue;
     2835                                        }
     2836
     2837                                        $orderby_array[] = $parsed;
    27612838                                }
     2839                                $orderby = implode( ' ' . $q['order'] . ', ', $orderby_array );
    27622840
    2763                                 $orderby_array[] = $orderby;
     2841                                if ( empty( $orderby ) )
     2842                                        $orderby = "$wpdb->posts.post_date ".$q['order'];
     2843                                else
     2844                                        $orderby .= " {$q['order']}";
    27642845                        }
    2765                         $orderby = implode( ' ' . $q['order'] . ', ', $orderby_array );
    2766 
    2767                         if ( empty( $orderby ) )
    2768                                 $orderby = "$wpdb->posts.post_date ".$q['order'];
    2769                         else
    2770                                 $orderby .= " {$q['order']}";
    27712846                }
    27722847
    27732848                // Order search results by relevance only when another "orderby" is not specified in the query.
  • tests/phpunit/tests/post/query.php

     
    761761                $q3 = new WP_Query( array( 'post_status' => array( 'any', 'auto-draft' ) ) );
    762762                $this->assertNotContains( "post_status <> 'auto-draft'", $q3->request );
    763763        }
     764
     765        /**
     766         *
     767         * @ticket 17065
     768         */
     769        function test_orderby_array() {
     770                global $wpdb;
     771
     772                $q1 = new WP_Query( array(
     773                        'orderby' => array(
     774                                'type' => 'DESC',
     775                                'name' => 'ASC'
     776                        )
     777                ) );
     778                $this->assertContains(
     779                        "ORDER BY $wpdb->posts.post_type DESC, $wpdb->posts.post_name ASC",
     780                        $q1->request
     781                );
     782
     783                $q2 = new WP_Query( array( 'orderby' => array() ) );
     784                $this->assertNotContains( 'ORDER BY', $q2->request );
     785                $this->assertNotContains( 'ORDER', $q2->request );
     786
     787                $q3 = new WP_Query( array( 'post_type' => 'post' ) );
     788                $this->assertContains(
     789                        "ORDER BY $wpdb->posts.post_date DESC",
     790                        $q3->request
     791                );
     792
     793                $q4 = new WP_Query( array( 'post_type' => 'post' ) );
     794                $this->assertContains(
     795                        "ORDER BY $wpdb->posts.post_date DESC",
     796                        $q4->request
     797                );
     798        }
     799
     800        /**
     801         *
     802         * @ticket 17065
     803         */
     804        function test_order() {
     805                global $wpdb;
     806
     807                $q1 = new WP_Query( array(
     808                        'orderby' => array(
     809                                'post_type' => 'foo'
     810                        )
     811                ) );
     812                $this->assertContains(
     813                        "ORDER BY $wpdb->posts.post_type DESC",
     814                        $q1->request
     815                );
     816
     817                $q2 = new WP_Query( array(
     818                        'orderby' => 'title',
     819                        'order'   => 'foo'
     820                ) );
     821                $this->assertContains(
     822                        "ORDER BY $wpdb->posts.post_title DESC",
     823                        $q2->request
     824                );
     825
     826                $q3 = new WP_Query( array(
     827                        'order' => 'asc'
     828                ) );
     829                $this->assertContains(
     830                        "ORDER BY $wpdb->posts.post_date ASC",
     831                        $q3->request
     832                );
     833        }
    764834}
     835 No newline at end of file