| 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 | /** |
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 | | |
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']); |
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; |