Skip to:
Content

BuddyPress.org

Ticket #6063: 6063.01.patch

File 6063.01.patch, 18.0 KB (added by r-a-y, 10 years ago)
  • src/bp-messages/bp-messages-classes.php

     
    319319         *
    320320         * @since BuddyPress (1.0.0)
    321321         *
    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         * }
    330334         * @return array|bool Array on success. Boolean false on failure.
    331335         */
    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() ) {
    333337                global $wpdb, $bp;
    334338
     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
    335367                $user_id_sql = $pag_sql = $type_sql = $search_sql = '';
     368                $meta_query_sql = array(
     369                        'join'   => '',
     370                        'where'  => ''
     371                );
    336372
    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'] ) );
    339375                }
    340376
    341                 if ( $type == 'unread' ) {
     377                if ( $r['type'] == 'unread' ) {
    342378                        $type_sql = " AND r.unread_count != 0 ";
    343                 } elseif ( $type == 'read' ) {
     379                } elseif ( $r['type'] == 'read' ) {
    344380                        $type_sql = " AND r.unread_count = 0 ";
    345381                }
    346382
    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'] ) . '%';
    349385                        $search_sql        = $wpdb->prepare( "AND ( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like );
    350386                }
    351387
    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'];
    360402                }
     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}";
    361413
     414                // get thread IDs
     415                $thread_ids = $wpdb->get_results( implode( ' ', $sql ) );
    362416                if ( empty( $thread_ids ) ) {
    363417                        return false;
    364418                }
    365419
     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
    366425                // Sort threads by date_sent
    367426                foreach( (array) $thread_ids as $thread ) {
    368427                        $sorted_threads[$thread->thread_id] = strtotime( $thread->date_sent );
     
    391450        }
    392451
    393452        /**
     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        /**
    394486         * Mark a thread as read.
    395487         *
    396488         * @since BuddyPress (1.0.0)
  • src/bp-messages/bp-messages-template.php

     
    114114        /**
    115115         * Constructor method.
    116116         *
    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'];
    137160
    138161                if ( 'notices' == $this->box ) {
    139162                        $this->threads = BP_Messages_Notice::get_notices( array(
     
    141164                                'pag_page' => $this->pag_page
    142165                        ) );
    143166                } 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                        ) );
    145176
    146177                        $this->threads            = $threads['threads'];
    147178                        $this->total_thread_count = $threads['total'];
     
    153184                } else {
    154185                        $total_notice_count = BP_Messages_Notice::get_total_notice_count();
    155186
    156                         if ( !$max || $max >= (int) $total_notice_count ) {
     187                        if ( ! $r['max'] || $r['max'] >= (int) $total_notice_count ) {
    157188                                if ( 'notices' == $this->box ) {
    158189                                        $this->total_thread_count = (int) $total_notice_count;
    159190                                }
    160191                        } else {
    161                                 $this->total_thread_count = (int) $max;
     192                                $this->total_thread_count = (int) $r['max'];
    162193                        }
    163194
    164                         if ( $max ) {
     195                        if ( $r['max'] ) {
    165196                                if ( $max >= count( $this->threads ) ) {
    166197                                        $this->thread_count = count( $this->threads );
    167198                                } else {
    168                                         $this->thread_count = (int) $max;
     199                                        $this->thread_count = (int) $r['max'];
    169200                                }
    170201                        } else {
    171202                                $this->thread_count = count( $this->threads );
     
    174205
    175206                if ( (int) $this->total_thread_count && (int) $this->pag_num ) {
    176207                        $pag_args = array(
    177                                 $page_arg => '%#%',
     208                                $r['page_arg'] => '%#%',
    178209                        );
    179210
    180211                        if ( defined( 'DOING_AJAX' ) && true === (bool) DOING_AJAX ) {
     
    343374 *           view will be inferred from the URL.
    344375 *     @type int $per_page Number of results to return per page. Default: 10.
    345376 *     @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'.
    346379 *     @type string $search_terms Terms to which to limit results. Default:
    347380 *           the value of $_REQUEST['s'].
    348381 *     @type string $page_arg URL argument used for the pagination param.
    349382 *           Default: 'mpage'.
     383 *     @type array $meta_query Meta query arguments. Only applicable if $box is
     384 *           not 'notices'. See WP_Meta_Query more details.
    350385 * }
    351386 * @return bool True if there are threads to display, otherwise false.
    352387 */
     
    371406                'type'         => 'all',
    372407                'search_terms' => isset( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '',
    373408                'page_arg'     => 'mpage', // See https://buddypress.trac.wordpress.org/ticket/3679
     409                'meta_query'   => array()
    374410        ), 'has_message_threads' );
    375411
    376412        // If trying to access notices without capabilities, redirect to root domain
     
    379415        }
    380416
    381417        // 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 );
    391419
    392420        /**
    393421         * Filters if there are any message threads to display in inbox/sentbox/notices.
  • tests/phpunit/testcases/messages/class.bp-messages-thread.php

     
    2323                        'subject' => 'Bar',
    2424                ) );
    2525
    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                ) );
    2732
    2833                $expected = array( $t2 );
    2934                $found = wp_parse_id_list( wp_list_pluck( $threads['threads'], 'thread_id' ) );
     
    5055                        'subject' => 'Bar',
    5156                ) );
    5257
    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                ) );
    5464
    5565                $expected = array( $t2 );
    5666                $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 */
     7class 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}