Skip to:
Content

Ticket #7523: 7523.01.patch

File 7523.01.patch, 13.9 KB (added by r-a-y, 8 months ago)
  • src/bp-messages/bp-messages-functions.php

     
    550550        return $retval; 
    551551} 
    552552 
    553 /** Email *********************************************************************/ 
     553/** Hooks *********************************************************************/ 
     554 
     555/** 
     556 * Delete all message threads that the deleted user has sent. 
     557 * 
     558 * @since 2.9.0 
     559 * 
     560 * @param int $user_id The deleted user ID. 
     561 */ 
     562function bp_messages_delete_threads_on_user_delete( $user_id ) { 
     563        $threads = BP_Messages_Thread::get_current_threads_for_user( array( 
     564                'user_id'     => $user_id, 
     565                'box'         => 'sentbox', 
     566                'deleted'     => null, 
     567                'fields'      => 'ids', 
     568                'count_total' => false 
     569        ) ); 
     570 
     571        if ( empty( $threads ) ) { 
     572                return; 
     573        } 
     574 
     575        foreach ( $threads['threads'] as $thread_id ) { 
     576                BP_Messages_Thread::delete( $thread_id, $user_id, true ); 
     577        } 
     578} 
     579add_action( 'deleted_user', 'bp_messages_delete_threads_on_user_delete' ); 
    554580 
    555581/** 
    556582 * Email message recipients to alert them of a new unread private message. 
  • src/bp-messages/classes/class-bp-messages-thread.php

     
    328328         * @since 1.0.0 
    329329         * @since 2.7.0 The $user_id parameter was added. Previously the current user 
    330330         *              was always assumed. 
    331          * 
    332          * @param int $thread_id The message thread ID. 
    333          * @param int $user_id The ID of the user in the thread to mark messages as 
    334          *                     deleted for. Defaults to the current logged-in user. 
    335          * 
     331         * @since 2.9.0 Added $force as a parameter. 
     332         * 
     333         * @param int  $thread_id The message thread ID. 
     334         * @param int  $user_id   The ID of the user in the thread to mark messages as deleted for. Defaults 
     335         *                        to the current logged-in user. 
     336         * @param bool $force     Whether to delete the entire message thread for all recipients. If false, 
     337         *                        every recipient in a thread needs to mark the thread as deleted before the 
     338         *                        thread is deleted from the DB. Default: false. 
    336339         * @return bool 
    337340         */ 
    338         public static function delete( $thread_id = 0, $user_id = 0 ) { 
     341        public static function delete( $thread_id = 0, $user_id = 0, $force = false ) { 
    339342                global $wpdb; 
    340343 
    341                 $thread_id = (int) $thread_id; 
    342                 $user_id = (int) $user_id; 
     344                $thread_id  = (int) $thread_id; 
     345                $user_id    = (int) $user_id; 
    343346 
    344347                if ( empty( $user_id ) ) { 
    345348                        $user_id = bp_loggedin_user_id(); 
     
    358361 
    359362                $bp = buddypress(); 
    360363 
    361                 // Mark messages as deleted 
    362                 $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET is_deleted = 1 WHERE thread_id = %d AND user_id = %d", $thread_id, $user_id ) ); 
    363  
    364364                // Get the message ids in order to pass to the action. 
    365365                $message_ids = $wpdb->get_col( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_messages} WHERE thread_id = %d", $thread_id ) ); 
    366366 
    367                 // Check to see if any more recipients remain for this message. 
    368                 $recipients = $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND is_deleted = 0", $thread_id ) ); 
     367                // Do the following when a user manually deletes a thread. 
     368                if ( false === $force ) { 
     369                        // Mark messages as deleted 
     370                        $wpdb->query( $wpdb->prepare( "UPDATE {$bp->messages->table_name_recipients} SET is_deleted = 1 WHERE thread_id = %d AND user_id = %d", $thread_id, $user_id ) ); 
     371 
     372                        // Check to see if any more recipients remain for this message. 
     373                        $recipients = $wpdb->get_results( $wpdb->prepare( "SELECT id FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND is_deleted = 0", $thread_id ) ); 
     374                } 
    369375 
    370376                // No more recipients so delete all messages associated with the thread. 
    371                 if ( empty( $recipients ) ) { 
     377                if ( true === $force || ( false === $force && isset( $recipients ) && empty( $recipients ) ) ) { 
    372378 
    373379                        /** 
    374380                         * Fires before an entire message thread is deleted. 
     
    422428         * Get current message threads for a user. 
    423429         * 
    424430         * @since 1.0.0 
     431         * @since 2.9.0 Added $deleted, $fields and $count_total as parameters to $args. 
    425432         * 
    426433         * @param array $args { 
    427434         *     Array of arguments. 
    428          *     @type int    $user_id      The user ID. 
    429          *     @type string $box          The type of mailbox to get. Either 'inbox' or 'sentbox'. 
    430          *                                Defaults to 'inbox'. 
    431          *     @type string $type         The type of messages to get. Either 'all' or 'unread' 
    432          *                                or 'read'. Defaults to 'all'. 
    433          *     @type int    $limit        The number of messages to get. Defaults to null. 
    434          *     @type int    $page         The page number to get. Defaults to null. 
    435          *     @type string $search_terms The search term to use. Defaults to ''. 
    436          *     @type array  $meta_query   Meta query arguments. See WP_Meta_Query for more details. 
     435         *     @type int      $user_id      The user ID. 
     436         *     @type string   $box          The type of mailbox to get. Either 'inbox' or 'sentbox'. 
     437         *                                  Defaults to 'inbox'. 
     438         *     @type string   $type         The type of messages to get. Either 'all' or 'unread' 
     439         *                                  or 'read'. Defaults to 'all'. 
     440         *     @type int      $limit        The number of messages to get. Defaults to null. 
     441         *     @type int      $page         The page number to get. Defaults to null. 
     442         *     @type string   $search_terms The search term to use. Defaults to ''. 
     443         *     @type array    $meta_query   Meta query arguments. See WP_Meta_Query for more details. 
     444         *     @type int|null $deleted      Whether to fetch deleted messages. 0 means we will not fetch deleted 
     445         *                                  messages; 1 means we will. null means we will not query for deleted 
     446         *                                  messages. Default: 0. 
     447         *     @type string   $fields       Thread fields to retrieve. 'all' to fetch entire thread objects, 'ids' to 
     448         *                                  get only the message thread IDs. DefaultL 'all'. 
     449         *     @type bool     $count_total  If true, an additional DB query is run to count the total message threads 
     450         *                                  for the query. Default: true. 
    437451         * } 
    438452         * @return array|bool Array on success. Boolean false on failure. 
    439453         */ 
     
    463477                        'limit'        => null, 
    464478                        'page'         => null, 
    465479                        'search_terms' => '', 
    466                         'meta_query'   => array() 
     480                        'meta_query'   => array(), 
     481                        'deleted'      => 0, 
     482                        'fields'       => 'all', 
     483                        'count_total'  => true 
    467484                ) ); 
    468485 
    469                 $pag_sql = $type_sql = $search_sql = $user_id_sql = $sender_sql = ''; 
    470                 $meta_query_sql = array( 
    471                         'join'  => '', 
    472                         'where' => '' 
    473                 ); 
     486                $pag_sql = $meta_query_join_sql = ''; 
     487                $where   = array(); 
    474488 
    475489                if ( $r['limit'] && $r['page'] ) { 
    476490                        $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['limit'] ), intval( $r['limit'] ) ); 
    477491                } 
    478492 
    479493                if ( $r['type'] == 'unread' ) { 
    480                         $type_sql = " AND r.unread_count != 0 "; 
     494                        $where['type'] = "r.unread_count != 0 "; 
    481495                } elseif ( $r['type'] == 'read' ) { 
    482                         $type_sql = " AND r.unread_count = 0 "; 
     496                        $where['type'] = "r.unread_count = 0 "; 
    483497                } 
    484498 
    485499                if ( ! empty( $r['search_terms'] ) ) { 
    486500                        $search_terms_like = '%' . bp_esc_like( $r['search_terms'] ) . '%'; 
    487                         $search_sql        = $wpdb->prepare( "AND ( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like ); 
     501                        $where['search']   = $wpdb->prepare( "( subject LIKE %s OR message LIKE %s )", $search_terms_like, $search_terms_like ); 
    488502                } 
    489503 
    490504                $r['user_id'] = (int) $r['user_id']; 
    491505 
    492                 // Default deleted SQL. 
    493                 $deleted_sql = 'r.is_deleted = 0'; 
     506                // Deleted SQL. 
     507                if ( is_int( $r['deleted'] ) ) { 
     508                        $where['delete'] = $wpdb->prepare( "r.is_deleted = %d", $r['deleted'] ); 
     509                } 
    494510 
    495511                switch ( $r['box'] ) { 
    496512                        case 'sentbox' : 
    497                                 $user_id_sql = 'AND ' . $wpdb->prepare( 'm.sender_id = %d', $r['user_id'] ); 
    498                                 $sender_sql  = 'AND m.sender_id = r.user_id'; 
     513                                $where['user_id'] = $wpdb->prepare( 'm.sender_id = %d', $r['user_id'] ); 
     514                                $where['sender']  = 'm.sender_id = r.user_id'; 
    499515                                break; 
    500516 
    501517                        case 'inbox' : 
    502                                 $user_id_sql = 'AND ' . $wpdb->prepare( 'r.user_id = %d', $r['user_id'] ); 
    503                                 $sender_sql  = 'AND r.sender_only = 0'; 
     518                                $where['user_id'] = $wpdb->prepare( 'r.user_id = %d', $r['user_id'] ); 
     519                                $where['sender']  = 'r.sender_only = 0'; 
    504520                                break; 
    505521 
    506522                        default : 
    507523                                // Omit user-deleted threads from all other custom message boxes. 
    508                                 $deleted_sql = $wpdb->prepare( '( r.user_id = %d AND r.is_deleted = 0 )', $r['user_id'] ); 
     524                                $where['custom_box'] = $wpdb->prepare( '( r.user_id = %d AND r.is_deleted = 0 )', $r['user_id'] ); 
    509525                                break; 
    510526                } 
    511527 
    512528                // Process meta query into SQL. 
    513529                $meta_query = self::get_meta_query_sql( $r['meta_query'] ); 
    514530                if ( ! empty( $meta_query['join'] ) ) { 
    515                         $meta_query_sql['join'] = $meta_query['join']; 
     531                        $meta_query_join_sql = $meta_query['join']; 
    516532                } 
    517533                if ( ! empty( $meta_query['where'] ) ) { 
    518                         $meta_query_sql['where'] = $meta_query['where']; 
     534                        // Strips leading AND; also see BP_Groups_Group::strip_leading_and(). 
     535                        $where['meta_query'] = preg_replace( '/^\s*AND\s*/', '', $meta_query['where'] ); 
    519536                } 
    520537 
    521538                $bp = buddypress(); 
    522539 
    523540                // Set up SQL array. 
    524541                $sql = array(); 
    525                 $sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent'; 
    526                 $sql['from']   = "FROM {$bp->messages->table_name_recipients} r INNER JOIN {$bp->messages->table_name_messages} m ON m.thread_id = r.thread_id {$meta_query_sql['join']}"; 
    527                 $sql['where']  = "WHERE {$deleted_sql} {$user_id_sql} {$sender_sql} {$type_sql} {$search_sql} {$meta_query_sql['where']}"; 
    528                 $sql['misc']   = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}"; 
     542                if ( 'ids' === $r['fields'] ) { 
     543                        $sql['select'] = 'SELECT m.thread_id'; 
     544                } else { 
     545                        $sql['select'] = 'SELECT m.thread_id, MAX(m.date_sent) AS date_sent'; 
     546                } 
     547                $sql['from']  = "FROM {$bp->messages->table_name_recipients} r INNER JOIN {$bp->messages->table_name_messages} m ON m.thread_id = r.thread_id {$meta_query_join_sql}"; 
     548                $sql['where'] = 'WHERE ' . join( ' AND ', $where ); 
     549                $sql['misc']  = "GROUP BY m.thread_id ORDER BY date_sent DESC {$pag_sql}"; 
    529550 
    530551                // Get thread IDs. 
    531                 $thread_ids = $wpdb->get_results( implode( ' ', $sql ) ); 
     552                if ( 'ids' === $r['fields'] ) { 
     553                        $thread_ids = $wpdb->get_col( implode( ' ', $sql ) ); 
     554                } else { 
     555                        $thread_ids = $wpdb->get_results( implode( ' ', $sql ) ); 
     556                } 
    532557                if ( empty( $thread_ids ) ) { 
    533558                        return false; 
    534559                } 
    535560 
    536561                // Adjust $sql to work for thread total. 
    537                 $sql['select'] = 'SELECT COUNT( DISTINCT m.thread_id )'; 
    538                 unset( $sql['misc'] ); 
    539                 $total_threads = $wpdb->get_var( implode( ' ', $sql ) ); 
     562                $total_threads = null; 
     563                if ( true === $r['count_total'] ) { 
     564                        $sql['select'] = 'SELECT COUNT( DISTINCT m.thread_id )'; 
     565                        unset( $sql['misc'] ); 
     566                        $total_threads = $wpdb->get_var( implode( ' ', $sql ) ); 
     567                } 
     568 
     569                if ( 'all' === $r['fields'] ) { 
     570                        // Sort threads by date_sent. 
     571                        foreach( (array) $thread_ids as $thread ) { 
     572                                $sorted_threads[ $thread->thread_id ] = strtotime( $thread->date_sent ); 
     573                        } 
    540574 
    541                 // Sort threads by date_sent. 
    542                 foreach( (array) $thread_ids as $thread ) { 
    543                         $sorted_threads[ $thread->thread_id ] = strtotime( $thread->date_sent ); 
     575                        arsort( $sorted_threads ); 
     576 
     577                        $threads = array(); 
     578                        foreach ( (array) $sorted_threads as $thread_id => $date_sent ) { 
     579                                $threads[] = new BP_Messages_Thread( $thread_id, 'ASC', array( 
     580                                        'update_meta_cache' => false 
     581                                ) ); 
     582                        } 
    544583                } 
    545584 
    546                 arsort( $sorted_threads ); 
     585                // Set up return value. 
     586                if ( 'all' === $r['fields'] ) { 
     587                        $threads = &$threads; 
     588                } else { 
     589                        $threads = $thread_ids; 
     590                } 
     591                $retval = array( 'threads' => $threads ); 
    547592 
    548                 $threads = array(); 
    549                 foreach ( (array) $sorted_threads as $thread_id => $date_sent ) { 
    550                         $threads[] = new BP_Messages_Thread( $thread_id, 'ASC', array( 
    551                                 'update_meta_cache' => false 
    552                         ) ); 
     593                if ( null !== $total_threads ) { 
     594                        $retval['total'] = (int) $total_threads; 
    553595                } 
    554596 
    555597                /** 
     
    558600                 * @since 2.2.0 
    559601                 * 
    560602                 * @param array $value { 
    561                  *     @type array $threads       Array of threads. Passed by reference. 
    562                  *     @type int   $total_threads Number of threads found by the query. 
     603                 *     @type array $threads       Array of threads. Passed by reference if 'fields' is 'all' in the query. 
     604                 *     @type int   $total_threads Number of threads found by the query. This is added as an array key if 
     605                 *                                'count_total' is true in the query. 
    563606                 * } 
    564607                 */ 
    565                 return apply_filters( 'bp_messages_thread_current_threads', array( 
    566                         'threads' => &$threads, 
    567                         'total'   => (int) $total_threads 
    568                 ) ); 
     608                return apply_filters( 'bp_messages_thread_current_threads', $retval ); 
    569609        } 
    570610 
    571611        /** 
  • tests/phpunit/testcases/messages/template.php

     
    359359 
    360360                $_REQUEST = $request; 
    361361        } 
     362 
     363        /** 
     364         * @group delete 
     365         * @group BP_Messages_Box_Template 
     366         */ 
     367        public function test_bp_messages_template_should_not_have_threads_by_deleted_user() { 
     368                $u1 = $this->factory->user->create(); 
     369                $u2 = $this->factory->user->create(); 
     370                $u3 = $this->factory->user->create(); 
     371 
     372                // create initial thread 
     373                $this->factory->message->create( array( 
     374                        'sender_id'  => $u2, 
     375                        'recipients' => array( $u1 ), 
     376                ) ); 
     377 
     378                // create some threads by our deleted user 
     379                $this->factory->message->create_many( 3, array( 
     380                        'sender_id'  => $u3, 
     381                        'recipients' => array( $u1 ), 
     382                ) ); 
     383 
     384                // Delete user 3. 
     385                if ( is_multisite() ) { 
     386                        wpmu_delete_user( $u3 ); 
     387                } else { 
     388                        wp_delete_user( $u3 ); 
     389                } 
     390 
     391                // Only the initial thread should remain. 
     392                $threads = new BP_Messages_Box_Template( array( 
     393                        'user_id' => $u1 
     394                ) ); 
     395                $this->assertEquals( 1, $threads->thread_count ); 
     396        } 
    362397}