Ticket #30478: 30478.diff
| File 30478.diff, 14.8 KB (added by , 11 years ago) |
|---|
-
src/wp-includes/comment.php
diff --git src/wp-includes/comment.php src/wp-includes/comment.php index c8984f0..5d82b1f 100644
class WP_Comment_Query { 511 511 $this->query_vars['orderby'] : 512 512 preg_split( '/[,\s]/', $this->query_vars['orderby'] ); 513 513 514 $allowed_keys = array( 515 'comment_agent', 516 'comment_approved', 517 'comment_author', 518 'comment_author_email', 519 'comment_author_IP', 520 'comment_author_url', 521 'comment_content', 522 'comment_date', 523 'comment_date_gmt', 524 'comment_ID', 525 'comment_karma', 526 'comment_parent', 527 'comment_post_ID', 528 'comment_type', 529 'user_id', 530 ); 531 if ( ! empty( $this->query_vars['meta_key'] ) ) { 532 $allowed_keys[] = $this->query_vars['meta_key']; 533 $allowed_keys[] = 'meta_value'; 534 $allowed_keys[] = 'meta_value_num'; 514 $orderby_array = array(); 515 $found_orderby_comment_ID = false; 516 foreach ( $ordersby as $_key => $_value ) { 517 if ( ! $_value ) { 518 continue; 519 } 520 521 if ( is_int( $_key ) ) { 522 $_orderby = $_value; 523 $_order = $order; 524 } else { 525 $_orderby = $_key; 526 $_order = $_value; 527 } 528 529 if ( ! $found_orderby_comment_ID && 'comment_ID' === $_orderby ) { 530 $found_orderby_comment_ID = true; 531 } 532 533 $parsed = $this->parse_orderby( $_orderby ); 534 535 if ( ! $parsed ) { 536 continue; 537 } 538 539 $orderby_array[] = $parsed . ' ' . $this->parse_order( $_order ); 540 } 541 542 // If no valid clauses were found, order by comment_date_gmt. 543 if ( empty( $orderby_array ) ) { 544 $orderby_array[] = "$wpdb->comments.comment_date_gmt $order"; 535 545 } 536 $ordersby = array_intersect( $ordersby, $allowed_keys ); 537 foreach ( $ordersby as $key => $value ) { 538 if ( $value == $this->query_vars['meta_key'] || $value == 'meta_value' ) { 539 $ordersby[ $key ] = "$wpdb->commentmeta.meta_value"; 540 } elseif ( $value == 'meta_value_num' ) { 541 $ordersby[ $key ] = "$wpdb->commentmeta.meta_value+0"; 546 547 // To ensure determinate sorting, always include a comment_ID clause. 548 if ( ! $found_orderby_comment_ID ) { 549 $comment_ID_order = ''; 550 551 // Inherit order from comment_date or comment_date_gmt, if available. 552 foreach ( $orderby_array as $orderby_clause ) { 553 if ( preg_match( '/comment_date(?:_gmt)*\ (ASC|DESC)/', $orderby_clause, $match ) ) { 554 $comment_ID_order = $match[1]; 555 break; 556 } 557 } 558 559 // If no date-related order is available, use the date from the first available clause. 560 if ( ! $comment_ID_order ) { 561 foreach ( $orderby_array as $orderby_clause ) { 562 if ( false !== strpos( 'ASC', $orderby_clause ) ) { 563 $comment_ID_order = 'ASC'; 564 } else { 565 $comment_ID_order = 'DESC'; 566 } 567 568 break; 569 } 542 570 } 571 572 // Default to DESC. 573 if ( ! $comment_ID_order ) { 574 $comment_ID_order = 'DESC'; 575 } 576 577 $orderby_array[] = "$wpdb->comments.comment_ID $comment_ID_order"; 543 578 } 544 $orderby = empty( $ordersby ) ? 'comment_date_gmt' : implode(', ', $ordersby); 579 580 $orderby = implode( ', ', $orderby_array ); 545 581 } else { 546 $orderby = 'comment_date_gmt';582 $orderby = "$wpdb->comments.comment_date_gmt $order"; 547 583 } 548 584 549 585 $number = absint( $this->query_vars['number'] ); … … class WP_Comment_Query { 724 760 725 761 $where = implode( ' AND ', $where ); 726 762 727 $pieces = array( 'fields', 'join', 'where', 'orderby', ' order', 'limits', 'groupby' );763 $pieces = array( 'fields', 'join', 'where', 'orderby', 'limits', 'groupby' ); 728 764 /** 729 765 * Filter the comment query clauses. 730 766 * … … class WP_Comment_Query { 739 775 $join = isset( $clauses[ 'join' ] ) ? $clauses[ 'join' ] : ''; 740 776 $where = isset( $clauses[ 'where' ] ) ? $clauses[ 'where' ] : ''; 741 777 $orderby = isset( $clauses[ 'orderby' ] ) ? $clauses[ 'orderby' ] : ''; 742 $order = isset( $clauses[ 'order' ] ) ? $clauses[ 'order' ] : '';743 778 $limits = isset( $clauses[ 'limits' ] ) ? $clauses[ 'limits' ] : ''; 744 779 $groupby = isset( $clauses[ 'groupby' ] ) ? $clauses[ 'groupby' ] : ''; 745 780 … … class WP_Comment_Query { 752 787 } 753 788 754 789 if ( $orderby ) { 755 $orderby = "ORDER BY $orderby $order";790 $orderby = "ORDER BY $orderby"; 756 791 } 757 792 758 793 $this->request = "SELECT $fields FROM $wpdb->comments $join $where $groupby $orderby $limits"; … … class WP_Comment_Query { 804 839 805 840 return ' AND (' . implode(' OR ', $searches) . ')'; 806 841 } 842 843 /** 844 * Parse and sanitize 'orderby' keys passed to the comment query. 845 * 846 * @since 4.2.0 847 * @access protected 848 * 849 * @global wpdb $wpdb WordPress database abstraction object. 850 * 851 * @param string $orderby Alias for the field to order by. 852 * @return string|bool Value to used in the ORDER clause. False otherwise. 853 */ 854 protected function parse_orderby( $orderby ) { 855 global $wpdb; 856 857 $allowed_keys = array( 858 'comment_agent', 859 'comment_approved', 860 'comment_author', 861 'comment_author_email', 862 'comment_author_IP', 863 'comment_author_url', 864 'comment_content', 865 'comment_date', 866 'comment_date_gmt', 867 'comment_ID', 868 'comment_karma', 869 'comment_parent', 870 'comment_post_ID', 871 'comment_type', 872 'user_id', 873 ); 874 875 if ( ! empty( $this->query_vars['meta_key'] ) ) { 876 $allowed_keys[] = $this->query_vars['meta_key']; 877 $allowed_keys[] = 'meta_value'; 878 $allowed_keys[] = 'meta_value_num'; 879 } 880 881 $parsed = false; 882 if ( $orderby == $this->query_vars['meta_key'] || $orderby == 'meta_value' ) { 883 $parsed = "$wpdb->commentmeta.meta_value"; 884 } else if ( $orderby == 'meta_value_num' ) { 885 $parsed = "$wpdb->commentmeta.meta_value+0"; 886 } else if ( in_array( $orderby, $allowed_keys ) ) { 887 $parsed = "$wpdb->comments.$orderby"; 888 } 889 890 return $parsed; 891 } 892 893 /** 894 * Parse an 'order' query variable and cast it to ASC or DESC as necessary. 895 * 896 * @since 4.2.0 897 * @access protected 898 * 899 * @param string $order The 'order' query variable. 900 * @return string The sanitized 'order' query variable. 901 */ 902 protected function parse_order( $order ) { 903 if ( ! is_string( $order ) || empty( $order ) ) { 904 return 'DESC'; 905 } 906 907 if ( 'ASC' === strtoupper( $order ) ) { 908 return 'ASC'; 909 } else { 910 return 'DESC'; 911 } 912 } 807 913 } 808 914 809 915 /** -
tests/phpunit/tests/comment/query.php
diff --git tests/phpunit/tests/comment/query.php tests/phpunit/tests/comment/query.php index 3f56ee2..69c36e2 100644
class Tests_Comment_Query extends WP_UnitTestCase { 581 581 */ 582 582 function test_orderby_meta() { 583 583 $comment_id = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) ); 584 sleep( 1 ); 584 585 $comment_id2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) ); 586 sleep( 1 ); 585 587 $comment_id3 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id ) ); 586 588 587 589 add_comment_meta( $comment_id, 'key', 'value1', true ); … … class Tests_Comment_Query extends WP_UnitTestCase { 612 614 $this->assertEquals( $comment_id2, $comments[1]->comment_ID ); 613 615 614 616 $comments = get_comments( array( 'meta_value' => 'value3', 'orderby' => array( 'key' ) ) ); 615 $this->assertEquals( 2, count( $comments ) ); 616 $this->assertEquals( $comment_id, $comments[0]->comment_ID ); 617 $this->assertEquals( $comment_id3, $comments[1]->comment_ID ); 617 $this->assertEquals( array( $comment_id3, $comment_id ), wp_list_pluck( $comments, 'comment_ID' ) ); 618 618 619 619 $comments = get_comments( array( 'meta_value' => 'value3', 'orderby' => array( 'meta_value' ) ) ); 620 $this->assertEquals( 2, count( $comments ) ); 621 $this->assertEquals( $comment_id, $comments[0]->comment_ID ); 622 $this->assertEquals( $comment_id3, $comments[1]->comment_ID ); 620 $this->assertEquals( array( $comment_id3, $comment_id ), wp_list_pluck( $comments, 'comment_ID' ) ); 623 621 624 622 // value1 is present on two different keys for $comment_id yet we should get only one instance 625 623 // of that comment in the results … … class Tests_Comment_Query extends WP_UnitTestCase { 985 983 } 986 984 987 985 public function test_orderby_default() { 986 global $wpdb; 987 988 988 $q = new WP_Comment_Query(); 989 989 $q->query( array() ); 990 990 991 $this->assertContains( 'ORDER BY comment_date_gmt', $q->request );991 $this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request ); 992 992 } 993 993 994 994 public function test_orderby_single() { 995 global $wpdb; 996 995 997 $q = new WP_Comment_Query(); 996 998 $q->query( array( 997 999 'orderby' => 'comment_agent', 998 1000 ) ); 999 1001 1000 $this->assertContains( 'ORDER BY comment_agent', $q->request );1002 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent", $q->request ); 1001 1003 } 1002 1004 1003 1005 public function test_orderby_single_invalid() { 1006 global $wpdb; 1007 1004 1008 $q = new WP_Comment_Query(); 1005 1009 $q->query( array( 1006 1010 'orderby' => 'foo', 1007 1011 ) ); 1008 1012 1009 $this->assertContains( 'ORDER BY comment_date_gmt', $q->request );1013 $this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request ); 1010 1014 } 1011 1015 1012 1016 public function test_orderby_comma_separated() { 1017 global $wpdb; 1018 1013 1019 $q = new WP_Comment_Query(); 1014 1020 $q->query( array( 1015 1021 'orderby' => 'comment_agent, comment_approved', 1016 1022 ) ); 1017 1023 1018 $this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );1024 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request ); 1019 1025 } 1020 1026 1021 public function test_orderby_array() { 1027 public function test_orderby_flat_array() { 1028 global $wpdb; 1029 1022 1030 $q = new WP_Comment_Query(); 1023 1031 $q->query( array( 1024 1032 'orderby' => array( 'comment_agent', 'comment_approved' ), 1025 1033 ) ); 1026 1034 1027 $this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );1035 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request ); 1028 1036 } 1029 1037 1030 1038 public function test_orderby_array_contains_invalid_item() { 1039 global $wpdb; 1040 1031 1041 $q = new WP_Comment_Query(); 1032 1042 $q->query( array( 1033 1043 'orderby' => array( 'comment_agent', 'foo', 'comment_approved' ), 1034 1044 ) ); 1035 1045 1036 $this->assertContains( 'ORDER BY comment_agent, comment_approved', $q->request );1046 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_approved DESC", $q->request ); 1037 1047 } 1038 1048 1039 1049 public function test_orderby_array_contains_all_invalid_items() { 1050 global $wpdb; 1051 1040 1052 $q = new WP_Comment_Query(); 1041 1053 $q->query( array( 1042 1054 'orderby' => array( 'foo', 'bar', 'baz' ), 1043 1055 ) ); 1044 1056 1045 $this->assertContains( 'ORDER BY comment_date_gmt', $q->request );1057 $this->assertContains( "ORDER BY $wpdb->comments.comment_date_gmt", $q->request ); 1046 1058 } 1047 1059 1048 1060 /** … … class Tests_Comment_Query extends WP_UnitTestCase { 1081 1093 $this->assertNotContains( 'ORDER BY', $q->request ); 1082 1094 } 1083 1095 1096 /** 1097 * @ticket 30478 1098 */ 1099 public function test_orderby_array() { 1100 global $wpdb; 1101 1102 $q = new WP_Comment_Query(); 1103 $found = $q->query( array( 1104 'fields' => 'ids', 1105 'orderby' => array( 1106 'comment_agent' => 'DESC', 1107 'comment_date_gmt' => 'ASC', 1108 'comment_ID' => 'DESC', 1109 ), 1110 ) ); 1111 1112 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt ASC, $wpdb->comments.comment_ID DESC", $q->request ); 1113 } 1114 1115 /** 1116 * @ticket 30478 1117 */ 1118 public function test_orderby_array_should_discard_invalid_columns() { 1119 global $wpdb; 1120 1121 $q = new WP_Comment_Query(); 1122 $found = $q->query( array( 1123 'fields' => 'ids', 1124 'orderby' => array( 1125 'comment_agent' => 'DESC', 1126 'foo' => 'ASC', 1127 'comment_ID' => 'DESC', 1128 ), 1129 ) ); 1130 1131 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_ID DESC", $q->request ); 1132 } 1133 1134 /** 1135 * @ticket 30478 1136 */ 1137 public function test_orderby_array_should_convert_invalid_order_to_DESC() { 1138 global $wpdb; 1139 1140 $q = new WP_Comment_Query(); 1141 $found = $q->query( array( 1142 'fields' => 'ids', 1143 'orderby' => array( 1144 'comment_agent' => 'DESC', 1145 'comment_date_gmt' => 'foo', 1146 'comment_ID' => 'DESC', 1147 ), 1148 ) ); 1149 1150 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt DESC, $wpdb->comments.comment_ID DESC", $q->request ); 1151 } 1152 1153 /** 1154 * @ticket 30478 1155 */ 1156 public function test_orderby_array_should_sort_by_comment_ID_as_fallback_and_should_inherit_order_from_comment_date_gmt() { 1157 global $wpdb; 1158 1159 $q = new WP_Comment_Query(); 1160 $found = $q->query( array( 1161 'fields' => 'ids', 1162 'orderby' => array( 1163 'comment_agent' => 'DESC', 1164 'comment_date_gmt' => 'ASC', 1165 ), 1166 ) ); 1167 1168 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date_gmt ASC, $wpdb->comments.comment_ID ASC", $q->request ); 1169 } 1170 1171 /** 1172 * @ticket 30478 1173 */ 1174 public function test_orderby_array_should_sort_by_comment_ID_as_fallback_and_should_inherit_order_from_comment_date() { 1175 global $wpdb; 1176 1177 $q = new WP_Comment_Query(); 1178 $found = $q->query( array( 1179 'fields' => 'ids', 1180 'orderby' => array( 1181 'comment_agent' => 'DESC', 1182 'comment_date' => 'ASC', 1183 ), 1184 ) ); 1185 1186 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent DESC, $wpdb->comments.comment_date ASC, $wpdb->comments.comment_ID ASC", $q->request ); 1187 } 1188 1189 /** 1190 * @ticket 30478 1191 */ 1192 public function test_orderby_array_should_sort_by_comment_ID_DESC_as_fallback_when_not_sorted_by_date() { 1193 global $wpdb; 1194 1195 $q = new WP_Comment_Query(); 1196 $found = $q->query( array( 1197 'fields' => 'ids', 1198 'orderby' => array( 1199 'comment_agent' => 'ASC', 1200 ), 1201 ) ); 1202 1203 $this->assertContains( "ORDER BY $wpdb->comments.comment_agent ASC, $wpdb->comments.comment_ID DESC", $q->request ); 1204 } 1205 1206 /** 1207 * @ticket 30478 1208 */ 1209 public function test_orderby_date_modified_gmt_should_order_by_comment_ID_in_case_of_tie_ASC() { 1210 $now = current_time( 'mysql', 1 ); 1211 $comments = $this->factory->comment->create_many( 5, array( 1212 'comment_post_ID' => $this->post_id, 1213 'comment_date_gmt' => $now, 1214 ) ); 1215 1216 $q = new WP_Comment_Query(); 1217 $found = $q->query( array( 1218 'orderby' => 'comment_date_gmt', 1219 'order' => 'ASC', 1220 ) ); 1221 1222 // $comments is ASC by default. 1223 $this->assertEquals( $comments, wp_list_pluck( $found, 'comment_ID' ) ); 1224 } 1225 1226 /** 1227 * @ticket 30478 1228 */ 1229 public function test_orderby_date_modified_gmt_should_order_by_comment_ID_in_case_of_tie_DESC() { 1230 $now = current_time( 'mysql', 1 ); 1231 $comments = $this->factory->comment->create_many( 5, array( 1232 'comment_post_ID' => $this->post_id, 1233 'comment_date_gmt' => $now, 1234 ) ); 1235 1236 $q = new WP_Comment_Query(); 1237 $found = $q->query( array( 1238 'orderby' => 'comment_date_gmt', 1239 'order' => 'DESC', 1240 ) ); 1241 1242 // $comments is ASC by default. 1243 rsort( $comments ); 1244 1245 $this->assertEquals( $comments, wp_list_pluck( $found, 'comment_ID' ) ); 1246 } 1247 1084 1248 public function test_count() { 1085 1249 $c1 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7 ) ); 1086 1250 $c2 = $this->factory->comment->create( array( 'comment_post_ID' => $this->post_id, 'user_id' => 7 ) );