Ticket #6063: 6063.01.patch
File 6063.01.patch, 18.0 KB (added by , 10 years ago) |
---|
-
src/bp-messages/bp-messages-classes.php
319 319 * 320 320 * @since BuddyPress (1.0.0) 321 321 * 322 * @param int $user_id The user ID. 323 * @param string $box The type of mailbox to get. Either 'inbox' or 'sentbox'. 324 * Defaults to 'inbox'. 325 * @param string $type The type of messages to get. Either 'all' or 'unread' 326 * or 'read'. Defaults to 'all'. 327 * @param int $limit The number of messages to get. Defaults to null. 328 * @param int $page The page number to get. Defaults to null. 329 * @param string $search_terms The search term to use. Defaults to ''. 322 * @param array $args { 323 * Array of arguments. 324 * @type int $user_id The user ID. 325 * @type string $box The type of mailbox to get. Either 'inbox' or 'sentbox'. 326 * Defaults to 'inbox'. 327 * @type string $type The type of messages to get. Either 'all' or 'unread' 328 * or 'read'. Defaults to 'all'. 329 * @type int $limit The number of messages to get. Defaults to null. 330 * @type int $page The page number to get. Defaults to null. 331 * @type string $search_terms The search term to use. Defaults to ''. 332 * @type array $meta_query Meta query arguments. See WP_Meta_Query for more details. 333 * } 330 334 * @return array|bool Array on success. Boolean false on failure. 331 335 */ 332 public static function get_current_threads_for_user( $ user_id, $box = 'inbox', $type = 'all', $limit = null, $page = null, $search_terms = '') {336 public static function get_current_threads_for_user( $args = array() ) { 333 337 global $wpdb, $bp; 334 338 339 // Backward compatibility with old method of passing arguments 340 if ( ! is_array( $args ) || func_num_args() > 1 ) { 341 _deprecated_argument( __METHOD__, '2.2.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) ); 342 343 $old_args_keys = array( 344 0 => 'user_id', 345 1 => 'box', 346 2 => 'type', 347 3 => 'limit', 348 4 => 'page', 349 5 => 'search_terms', 350 ); 351 352 $func_args = func_get_args(); 353 $args = bp_core_parse_args_array( $old_args_keys, $func_args ); 354 } 355 356 $r = wp_parse_args( $args, array( 357 'user_id' => false, 358 'box' => 'inbox', 359 'type' => 'all', 360 'limit' => null, 361 'page' => null, 362 'search_terms' => '', 363 'meta_query' => array() 364 ) ); 365 366 // some defaults 335 367 $user_id_sql = $pag_sql = $type_sql = $search_sql = ''; 368 $meta_query_sql = array( 369 'join' => '', 370 'where' => '' 371 ); 336 372 337 if ( $ limit && $page) {338 $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $ page - 1 ) * $limit), intval( $limit) );373 if ( $r['limit'] && $r['page'] ) { 374 $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['limit']), intval( $r['limit'] ) ); 339 375 } 340 376 341 if ( $ type== 'unread' ) {377 if ( $r['type'] == 'unread' ) { 342 378 $type_sql = " AND r.unread_count != 0 "; 343 } elseif ( $ type== 'read' ) {379 } elseif ( $r['type'] == 'read' ) { 344 380 $type_sql = " AND r.unread_count = 0 "; 345 381 } 346 382 347 if ( ! empty( $ search_terms) ) {348 $search_terms_like = '%' . bp_esc_like( $ search_terms) . '%';383 if ( ! empty( $r['search_terms'] ) ) { 384 $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%'; 349 385 $search_sql = $wpdb->prepare( "AND ( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like ); 350 386 } 351 387 352 if ( 'sentbox' == $box ) { 353 $user_id_sql = $wpdb->prepare( 'm.sender_id = %d', $user_id ); 354 $thread_ids = $wpdb->get_results( "SELECT m.thread_id, MAX(m.date_sent) AS date_sent FROM {$bp->messages->table_name_recipients} r, {$bp->messages->table_name_messages} m WHERE m.thread_id = r.thread_id AND m.sender_id = r.user_id AND {$user_id_sql} AND r.is_deleted = 0 {$search_sql} GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}" ); 355 $total_threads = $wpdb->get_var( "SELECT COUNT( DISTINCT m.thread_id ) FROM {$bp->messages->table_name_recipients} r, {$bp->messages->table_name_messages} m WHERE m.thread_id = r.thread_id AND m.sender_id = r.user_id AND {$user_id_sql} AND r.is_deleted = 0 {$search_sql} " ); 356 } else { 357 $user_id_sql = $wpdb->prepare( 'r.user_id = %d', $user_id ); 358 $thread_ids = $wpdb->get_results( "SELECT m.thread_id, MAX(m.date_sent) AS date_sent FROM {$bp->messages->table_name_recipients} r, {$bp->messages->table_name_messages} m WHERE m.thread_id = r.thread_id AND r.is_deleted = 0 AND {$user_id_sql} AND r.sender_only = 0 {$type_sql} {$search_sql} GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}" ); 359 $total_threads = $wpdb->get_var( "SELECT COUNT( DISTINCT m.thread_id ) FROM {$bp->messages->table_name_recipients} r, {$bp->messages->table_name_messages} m WHERE m.thread_id = r.thread_id AND r.is_deleted = 0 AND {$user_id_sql} AND r.sender_only = 0 {$type_sql} {$search_sql}" ); 388 if ( ! empty( $r['user_id'] ) ) { 389 if ( 'sentbox' == $r['box'] ) { 390 $user_id_sql = 'AND ' . $wpdb->prepare( 'm.sender_id = %d', $r['user_id'] ); 391 $user_id_sql .= ' AND m.sender_id = r.user_id'; 392 } else { 393 $user_id_sql = 'AND ' . $wpdb->prepare( 'r.user_id = %d', $r['user_id'] ); 394 $user_id_sql .= ' AND r.sender_only = 0'; 395 } 396 } 397 398 // Process meta query into SQL 399 $meta_query = self::get_meta_query_sql( $r['meta_query'] ); 400 if ( ! empty( $meta_query['join'] ) ) { 401 $meta_query_sql['join'] = $meta_query['join']; 360 402 } 403 if ( ! empty( $meta_query['where'] ) ) { 404 $meta_query_sql['where'] = $meta_query['where']; 405 } 406 407 // set up SQL array 408 $sql = array(); 409 $sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent'; 410 $sql['from'] = "FROM {$bp->messages->table_name_recipients} r, {$bp->messages->table_name_messages} m {$meta_query_sql['join']}"; 411 $sql['where'] = "WHERE m.thread_id = r.thread_id {$user_id_sql} AND r.is_deleted = 0 {$type_sql} {$search_sql} {$meta_query_sql['where']}"; 412 $sql['misc'] = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}"; 361 413 414 // get thread IDs 415 $thread_ids = $wpdb->get_results( implode( ' ', $sql ) ); 362 416 if ( empty( $thread_ids ) ) { 363 417 return false; 364 418 } 365 419 420 // adjust $sql to work for thread total 421 $sql['select'] = 'SELECT COUNT( DISTINCT m.thread_id )'; 422 unset( $sql['misc'] ); 423 $total_threads = $wpdb->get_var( implode( ' ', $sql ) ); 424 366 425 // Sort threads by date_sent 367 426 foreach( (array) $thread_ids as $thread ) { 368 427 $sorted_threads[$thread->thread_id] = strtotime( $thread->date_sent ); … … 391 450 } 392 451 393 452 /** 453 * Get the SQL for the 'meta_query' param in BP_Messages_Thread::get_current_threads_for_user(). 454 * 455 * We use WP_Meta_Query to do the heavy lifting of parsing the meta_query array 456 * and creating the necessary SQL clauses. 457 * 458 * @since BuddyPress (2.2.0) 459 * 460 * @param array $meta_query An array of meta_query filters. See the 461 * documentation for WP_Meta_Query for details. 462 * @return array $sql_array 'join' and 'where' clauses. 463 */ 464 public static function get_meta_query_sql( $meta_query = array() ) { 465 global $wpdb; 466 467 $sql_array = array( 468 'join' => '', 469 'where' => '', 470 ); 471 472 if ( ! empty( $meta_query ) ) { 473 $meta_query = new WP_Meta_Query( $meta_query ); 474 475 // WP_Meta_Query expects the table name at 476 // $wpdb->messagemeta 477 $wpdb->messagemeta = buddypress()->messages->table_name_meta; 478 479 return $meta_query->get_sql( 'message', 'm', 'id' ); 480 } 481 482 return $sql_array; 483 } 484 485 /** 394 486 * Mark a thread as read. 395 487 * 396 488 * @since BuddyPress (1.0.0) -
src/bp-messages/bp-messages-template.php
114 114 /** 115 115 * Constructor method. 116 116 * 117 * @param int $user_id ID of the user whose Messages box is being 118 * viewed. 119 * @param string $box Type of box being viewed ('notices', 'sentbox', 120 * 'inbox'). 121 * @param int $per_page Number of thread to return per page of results. 122 * @param int $max Max number of results to return. 123 * @param string $type Type of results to return. 'unread', 'read', 124 * or 'all'. 125 * @param string $search_terms Search terms for limiting results. 126 * @param string $page_arg Optional. URL argument for pagination 127 * parameter. Default: 'mpage'. 128 */ 129 public function __construct( $user_id, $box, $per_page, $max, $type, $search_terms, $page_arg = 'mpage' ) { 130 $this->pag_page = isset( $_GET[$page_arg] ) ? intval( $_GET[$page_arg] ) : 1; 131 $this->pag_num = isset( $_GET['num'] ) ? intval( $_GET['num'] ) : $per_page; 132 133 $this->user_id = $user_id; 134 $this->box = $box; 135 $this->type = $type; 136 $this->search_terms = $search_terms; 117 * @param array $args { 118 * Array of arguments. See bp_has_message_threads() for full description. 119 * } 120 */ 121 public function __construct( $args = array() ) { 122 global $wpdb, $bp; 123 124 // Backward compatibility with old method of passing arguments 125 if ( ! is_array( $args ) || func_num_args() > 1 ) { 126 _deprecated_argument( __METHOD__, '2.2.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) ); 127 128 $old_args_keys = array( 129 0 => 'user_id', 130 1 => 'box', 131 2 => 'per_page', 132 3 => 'max', 133 4 => 'type', 134 5 => 'search_terms', 135 6 => 'page_arg' 136 ); 137 138 $func_args = func_get_args(); 139 $args = bp_core_parse_args_array( $old_args_keys, $func_args ); 140 } 141 142 $r = wp_parse_args( $args, array( 143 'user_id' => bp_loggedin_user_id(), 144 'box' => 'inbox', 145 'per_page' => 10, 146 'max' => false, 147 'type' => 'all', 148 'search_terms' => '', 149 'page_arg' => 'mpage', 150 'meta_query' => array(), 151 ) ); 152 153 $this->pag_page = isset( $_GET[ $r['page_arg'] ] ) ? intval( $_GET[ $r['page_arg'] ] ) : 1; 154 $this->pag_num = isset( $_GET['num'] ) ? intval( $_GET['num'] ) : $r['per_page']; 155 156 $this->user_id = $r['user_id']; 157 $this->box = $r['box']; 158 $this->type = $r['type']; 159 $this->search_terms = $r['search_terms']; 137 160 138 161 if ( 'notices' == $this->box ) { 139 162 $this->threads = BP_Messages_Notice::get_notices( array( … … 141 164 'pag_page' => $this->pag_page 142 165 ) ); 143 166 } else { 144 $threads = BP_Messages_Thread::get_current_threads_for_user( $this->user_id, $this->box, $this->type, $this->pag_num, $this->pag_page, $this->search_terms ); 167 $threads = BP_Messages_Thread::get_current_threads_for_user( array( 168 'user_id' => $this->user_id, 169 'box' => $this->box, 170 'type' => $this->type, 171 'limit' => $this->pag_num, 172 'page' => $this->pag_page, 173 'search_terms' => $this->search_terms, 174 'meta_query' => $r['meta_query'], 175 ) ); 145 176 146 177 $this->threads = $threads['threads']; 147 178 $this->total_thread_count = $threads['total']; … … 153 184 } else { 154 185 $total_notice_count = BP_Messages_Notice::get_total_notice_count(); 155 186 156 if ( ! $max || $max>= (int) $total_notice_count ) {187 if ( ! $r['max'] || $r['max'] >= (int) $total_notice_count ) { 157 188 if ( 'notices' == $this->box ) { 158 189 $this->total_thread_count = (int) $total_notice_count; 159 190 } 160 191 } else { 161 $this->total_thread_count = (int) $ max;192 $this->total_thread_count = (int) $r['max']; 162 193 } 163 194 164 if ( $ max) {195 if ( $r['max'] ) { 165 196 if ( $max >= count( $this->threads ) ) { 166 197 $this->thread_count = count( $this->threads ); 167 198 } else { 168 $this->thread_count = (int) $ max;199 $this->thread_count = (int) $r['max']; 169 200 } 170 201 } else { 171 202 $this->thread_count = count( $this->threads ); … … 174 205 175 206 if ( (int) $this->total_thread_count && (int) $this->pag_num ) { 176 207 $pag_args = array( 177 $ page_arg=> '%#%',208 $r['page_arg'] => '%#%', 178 209 ); 179 210 180 211 if ( defined( 'DOING_AJAX' ) && true === (bool) DOING_AJAX ) { … … 343 374 * view will be inferred from the URL. 344 375 * @type int $per_page Number of results to return per page. Default: 10. 345 376 * @type int $max Max results to return. Default: false. 377 * @type string $type Type of results to return. 'unread', 'read' or 'all'. 378 * Default: 'all'. 346 379 * @type string $search_terms Terms to which to limit results. Default: 347 380 * the value of $_REQUEST['s']. 348 381 * @type string $page_arg URL argument used for the pagination param. 349 382 * Default: 'mpage'. 383 * @type array $meta_query Meta query arguments. Only applicable if $box is 384 * not 'notices'. See WP_Meta_Query more details. 350 385 * } 351 386 * @return bool True if there are threads to display, otherwise false. 352 387 */ … … 371 406 'type' => 'all', 372 407 'search_terms' => isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '', 373 408 'page_arg' => 'mpage', // See https://buddypress.trac.wordpress.org/ticket/3679 409 'meta_query' => array() 374 410 ), 'has_message_threads' ); 375 411 376 412 // If trying to access notices without capabilities, redirect to root domain … … 379 415 } 380 416 381 417 // Load the messages loop global up with messages 382 $messages_template = new BP_Messages_Box_Template( 383 $r['user_id'], 384 $r['box'], 385 $r['per_page'], 386 $r['max'], 387 $r['type'], 388 $r['search_terms'], 389 $r['page_arg'] 390 ); 418 $messages_template = new BP_Messages_Box_Template( $r ); 391 419 392 420 /** 393 421 * Filters if there are any message threads to display in inbox/sentbox/notices. -
tests/phpunit/testcases/messages/class.bp-messages-thread.php
23 23 'subject' => 'Bar', 24 24 ) ); 25 25 26 $threads = BP_Messages_Thread::get_current_threads_for_user( $u2, 'inbox', 'all', null, null, 'ar' ); 26 $threads = BP_Messages_Thread::get_current_threads_for_user( array( 27 'user_id' => $u2, 28 'box' => 'inbox', 29 'type' => 'all', 30 'search_terms' => 'ar' 31 ) ); 27 32 28 33 $expected = array( $t2 ); 29 34 $found = wp_parse_id_list( wp_list_pluck( $threads['threads'], 'thread_id' ) ); … … 50 55 'subject' => 'Bar', 51 56 ) ); 52 57 53 $threads = BP_Messages_Thread::get_current_threads_for_user( $u1, 'sentbox', 'all', null, null, 'ar' ); 58 $threads = BP_Messages_Thread::get_current_threads_for_user( array( 59 'user_id' => $u1, 60 'box' => 'sentbox', 61 'type' => 'all', 62 'search_terms' => 'ar' 63 ) ); 54 64 55 65 $expected = array( $t2 ); 56 66 $found = wp_parse_id_list( wp_list_pluck( $threads['threads'], 'thread_id' ) ); -
new file tests/phpunit/testcases/messages/template.php
new file mode 100644
- + 1 <?php 2 3 /** 4 * @group messages 5 * @group template 6 */ 7 class BP_Tests_Messages_Template extends BP_UnitTestCase { 8 /** 9 * @group bp_has_message_threads 10 * @group meta_query 11 */ 12 public function test_has_message_threads_meta_query() { 13 $u1 = $this->factory->user->create(); 14 $u2 = $this->factory->user->create(); 15 16 // dummy threads 17 $this->factory->message->create_many( 3, array( 18 'sender_id' => $u1, 19 'recipients' => array( $u2 ), 20 ) ); 21 22 // create initial thread 23 $t1 = $this->factory->message->create( array( 24 'sender_id' => $u1, 25 'recipients' => array( $u2 ), 26 'subject' => 'This is a knive', 27 ) ); 28 29 // create some replies for thread 1 30 $this->factory->message->create( array( 31 'thread_id' => $t1, 32 'sender_id' => $u2, 33 'recipients' => array( $u1 ), 34 'content' => "That's a spoon", 35 ) ); 36 $this->factory->message->create( array( 37 'thread_id' => $t1, 38 'sender_id' => $u1, 39 'recipients' => array( $u2 ), 40 'content' => "I see you've played knivey-spooney before.", 41 ) ); 42 $this->factory->message->create( array( 43 'thread_id' => $t1, 44 'sender_id' => $u2, 45 'recipients' => array( $u1 ), 46 'content' => '*crickets*', 47 ) ); 48 49 // create second thread 50 $t2 = $this->factory->message->create( array( 51 'sender_id' => $u1, 52 'recipients' => array( $u2 ), 53 'subject' => 'Oy', 54 ) ); 55 56 // create a reply for thread 2 57 $this->factory->message->create( array( 58 'thread_id' => $t2, 59 'sender_id' => $u2, 60 'recipients' => array( $u1 ), 61 'content' => "Oy yourself.", 62 ) ); 63 64 // grab the message ids as individual variables for thread 1 65 $thread = new BP_Messages_Thread( $t1 ); 66 $mids = wp_list_pluck( $thread->messages, 'id' ); 67 list( $m1, $m2, $m3, $m4 ) = $mids; 68 69 // grab the message ids as individual variables for thread 2 70 $thread = new BP_Messages_Thread( $t2 ); 71 $mids = wp_list_pluck( $thread->messages, 'id' ); 72 list( $m5, $m6 ) = $mids; 73 74 // add meta for some of the messages 75 bp_messages_update_meta( $m1, 'utensil', 'knive' ); 76 bp_messages_update_meta( $m1, 'is_knive', 'yes' ); 77 bp_messages_update_meta( $m1, "starred_by_user_{$u2}", true ); 78 79 bp_messages_update_meta( $m2, 'utensil', 'spoon' ); 80 bp_messages_update_meta( $m2, 'is_knive', 'no' ); 81 bp_messages_update_meta( $m2, 'is_spoon', 'yes' ); 82 83 // star a message that wasn't authored by the user 84 bp_messages_update_meta( $m3, "starred_by_user_{$u2}", true ); 85 86 bp_messages_update_meta( $m5, "starred_by_user_{$u2}", true ); 87 88 // now, do the message thread loop query 89 global $messages_template; 90 bp_has_message_threads( array( 91 // don't filter by user ID so we can grab messages that were not authored by 92 // the user. 93 // 94 // in our case, a user can star any message made by any user 95 'user_id' => 0, 96 'meta_query' => array( 97 array( 98 'key' => "starred_by_user_{$u2}" 99 ), 100 ) 101 ) ); 102 103 $this->assertEquals( 2, $messages_template->thread_count ); 104 $this->assertEqualSets( array( $t1, $t2 ), wp_list_pluck( $messages_template->threads, 'thread_id' ) ); 105 } 106 }