Skip to:
Content

BuddyPress.org

Changeset 13196


Ignore:
Timestamp:
12/23/2021 08:07:07 PM (5 years ago)
Author:
imath
Message:

BP Messages: introduce a functionality to exit a messages thread

Exiting a messages thread is removing the user from the list of the recipients of the thread. The thread can carry on between the other recipients.

Props Oelita, vapvarun

Fixes #7540

Location:
trunk
Files:
1 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-messages/bp-messages-cache.php

    r13096 r13196  
    8888}
    8989add_action( 'messages_delete_thread', 'bp_messages_clear_cache_on_message_delete', 10, 2 );
     90add_action( 'bp_messages_exit_thread', 'bp_messages_clear_cache_on_message_delete', 10, 2 );
    9091
    9192/**
  • trunk/src/bp-messages/bp-messages-functions.php

    r13108 r13196  
    800800        return $retval;
    801801}
     802
     803/**
     804 * Exit one or more message thread(s) for a given user.
     805 *
     806 * @since 10.0.0
     807 *
     808 * @param int|array $thread_ids Thread ID or array of thread IDs.
     809 * @param int       $user_id    ID of the user to delete the threads for. Defaults
     810 *                              to the current logged-in user.
     811 * @return bool True on success, false on failure.
     812 */
     813function bp_messages_exit_thread( $thread_ids, $user_id = 0 ) {
     814
     815        if ( empty( $user_id ) ) {
     816                $user_id = bp_loggedin_user_id();
     817
     818                if ( bp_displayed_user_id() ) {
     819                        $user_id = bp_displayed_user_id();
     820                }
     821        }
     822
     823        /**
     824         * Fires before a user exits specified thread IDs.
     825         *
     826         * @since 10.0.0
     827         *
     828         * @param int|array $thread_ids Thread ID or array of thread IDs to be deleted.
     829         * @param int       $user_id    ID of the user the threads are being deleted for.
     830         */
     831        do_action( 'bp_messages_before_exit_thread', $thread_ids, $user_id );
     832
     833        if ( is_array( $thread_ids ) ) {
     834                $error = 0;
     835                for ( $i = 0, $count = count( $thread_ids ); $i < $count; ++$i ) {
     836                        if ( ! BP_Messages_Thread::exit_thread( $thread_ids[ $i ], $user_id ) ) {
     837                                $error = 1;
     838                        }
     839                }
     840
     841                if ( ! empty( $error ) ) {
     842                        return false;
     843                }
     844
     845                /**
     846                 * Fires after a user exited the specified thread IDs.
     847                 *
     848                 * @since 10.0.0
     849                 *
     850                 * @param int|array Thread ID or array of thread IDs that were deleted.
     851                 * @param int       ID of the user that the threads were deleted for.
     852                 */
     853                do_action( 'bp_messages_exit_thread', $thread_ids, $user_id );
     854
     855                return true;
     856        } else {
     857                if ( ! BP_Messages_Thread::exit_thread( $thread_ids, $user_id ) ) {
     858                        return false;
     859                }
     860
     861                /** This action is documented in bp-messages/bp-messages-functions.php */
     862                do_action( 'bp_messages_exit_thread', $thread_ids, $user_id );
     863
     864                return true;
     865        }
     866}
  • trunk/src/bp-messages/bp-messages-template.php

    r13185 r13196  
    21902190
    21912191/**
     2192 * Output the URL to exit the current thread.
     2193 *
     2194 * @since 10.0.0
     2195 */
     2196function bp_the_thread_exit_link() {
     2197        echo esc_url( bp_get_the_thread_exit_link() );
     2198}
     2199        /**
     2200         * Get the URL to exit the current thread.
     2201         *
     2202         * @since 10.0.0
     2203         *
     2204         * @return string URL
     2205         */
     2206        function bp_get_the_thread_exit_link() {
     2207
     2208                /**
     2209                 * Filters the URL to exit the current thread.
     2210                 *
     2211                 * @since 1.0.0
     2212                 *
     2213                 * @param string $value URL to exit the current thread.
     2214                 * @param string $value Text indicating action being executed.
     2215                 */
     2216                return apply_filters( 'bp_get_the_thread_exit_link', wp_nonce_url( bp_displayed_user_domain() . bp_get_messages_slug() . '/inbox/exit/' . bp_get_the_thread_id(), 'bp_messages_exit_thread' ) );
     2217        }
     2218
     2219/**
    21922220 * Output the 'Sent x hours ago' string for the current message.
    21932221 *
  • trunk/src/bp-messages/classes/class-bp-messages-component.php

    r13185 r13196  
    103103                        // Authenticated action variables.
    104104                        if ( is_user_logged_in() && bp_action_variable( 0 ) &&
    105                                 in_array( bp_action_variable( 0 ), array( 'delete', 'read', 'unread', 'bulk-manage', 'bulk-delete' ), true )
     105                                in_array( bp_action_variable( 0 ), array( 'delete', 'read', 'unread', 'bulk-manage', 'bulk-delete', 'exit' ), true )
    106106                        ) {
    107107                                require $this->path . 'bp-messages/actions/' . bp_action_variable( 0 ) . '.php';
  • trunk/src/bp-messages/classes/class-bp-messages-thread.php

    r13148 r13196  
    531531                 */
    532532                do_action( 'bp_messages_thread_after_delete', $thread_id, $message_ids, $user_id );
     533
     534                return true;
     535        }
     536
     537        /**
     538         * Exit a user from a thread.
     539         *
     540         * @since 10.0.0
     541         *
     542         * @global wpdb $wpdb WordPress database object.
     543         *
     544         * @param int $thread_id The message thread ID.
     545         * @param int $user_id The ID of the user in the thread.
     546         *                     Defaults to the current logged-in user.
     547         *
     548         * @return bool
     549         */
     550        public static function exit_thread( $thread_id = 0, $user_id = 0 ) {
     551                global $wpdb;
     552
     553                $thread_id = (int) $thread_id;
     554                $user_id   = (int) $user_id;
     555
     556                if ( empty( $user_id ) ) {
     557                        $user_id = bp_loggedin_user_id();
     558                }
     559
     560                // Check the user is a recipient of the thread and recipients count > 2.
     561                $recipients    = self::get_recipients_for_thread( $thread_id );
     562                $recipient_ids = wp_list_pluck( $recipients, 'user_id' );
     563
     564                if ( 2 >= count( $recipient_ids ) || ! in_array( $user_id, $recipient_ids, true ) ) {
     565                        return false;
     566                }
     567
     568                /**
     569                 * Fires before a user exits a thread.
     570                 *
     571                 * @since 10.0.0
     572                 *
     573                 * @param int $thread_id ID of the thread being deleted.
     574                 * @param int $user_id   ID of the user that the thread is being deleted for.
     575                 */
     576                do_action( 'bp_messages_thread_before_exit', $thread_id, $user_id );
     577
     578                $bp = buddypress();
     579
     580                // Delete the user from messages recipients
     581                $exited = $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->messages->table_name_recipients} WHERE thread_id = %d AND user_id = %d", $thread_id, $user_id ) );
     582
     583                // Bail if the user wasn't removed from the recipients list.
     584                if ( empty( $exited ) ) {
     585                        return false;
     586                }
     587
     588                /**
     589                 * Fires after a user exits a thread.
     590                 *
     591                 * @since 10.0.0
     592                 *
     593                 * @param int   $thread_id ID of the thread being deleted.
     594                 * @param int   $user_id   ID of the user the threads were deleted for.
     595                 */
     596                do_action( 'bp_messages_thread_after_exit', $thread_id, $user_id );
    533597
    534598                return true;
  • trunk/src/bp-templates/bp-legacy/buddypress/members/single/messages/single.php

    r12595 r13196  
    55 * @package BuddyPress
    66 * @subpackage bp-legacy
    7  * @version 3.0.0
     7 * @version 10.0.0
    88 */
    99
     
    4949                        </span>
    5050
    51                         <a class="button confirm" href="<?php bp_the_thread_delete_link(); ?>"><?php _e( 'Delete', 'buddypress' ); ?></a>
     51                        <a class="button confirm" href="<?php bp_the_thread_delete_link(); ?>"><?php esc_html_e( 'Delete', 'buddypress' ); ?></a>
     52
     53                        <?php if ( bp_get_thread_recipients_count() > 2 ) : ?>
     54
     55                                <a class="button confirm" href="<?php bp_the_thread_exit_link(); ?>"><?php esc_html_e( 'Exit Conversation', 'buddypress' ); ?></a>
     56
     57                        <?php endif; ?>
    5258
    5359                        <?php
  • trunk/src/bp-templates/bp-nouveau/buddypress/common/js-templates/messages/index.php

    r13151 r13196  
    189189                                                <span class="bp-screen-reader-text"><?php esc_html_e( 'Delete conversation.', 'buddypress' ); ?></span>
    190190                                        </button>
     191
     192                                        <# if ( undefined !== data.recipients && data.recipients.length > 2 ) { #>
     193                                                <button type="button" class="message-action-exit bp-tooltip bp-icons" data-bp-action="exit" data-bp-tooltip="<?php esc_attr_e( 'Exit conversation.', 'buddypress' ); ?>">
     194                                                        <span class="bp-screen-reader-text"><?php esc_html_e( 'Exit conversation.', 'buddypress' ); ?></span>
     195                                                </button>
     196                                        <# } #>
    191197
    192198                                        <# if ( undefined !== data.star_link ) { #>
     
    251257                                <span class="bp-screen-reader-text"><?php esc_html_e( 'Delete conversation.', 'buddypress' ); ?></span>
    252258                        </button>
     259
     260                        <# if ( undefined !== data.recipients && data.recipients.length > 2 ) { #>
     261                                <button type="button" class="message-action-exit bp-tooltip bp-icons" data-bp-action="exit" data-bp-tooltip="<?php esc_attr_e( 'Exit conversation.', 'buddypress' ); ?>">
     262                                        <span class="bp-screen-reader-text"><?php esc_html_e( 'Exit conversation.', 'buddypress' ); ?></span>
     263                                </button>
     264                        <# } #>
    253265                </div>
    254266        </header>
  • trunk/src/bp-templates/bp-nouveau/css/buddypress-rtl.css

    r13182 r13196  
    30723072.message-action-unstar:before,
    30733073.message-action-view:before,
    3074 .message-action-delete:before {
     3074.message-action-delete:before,
     3075.message-action-exit:before {
    30753076        font-family: dashicons;
    30763077        font-size: 18px;
     
    30933094.message-action-delete:before {
    30943095        content: "\f153";
     3096}
     3097
     3098.message-action-exit:before {
     3099        content: "\f14a";
    30953100}
    30963101
  • trunk/src/bp-templates/bp-nouveau/css/buddypress.css

    r13182 r13196  
    30723072.message-action-unstar:before,
    30733073.message-action-view:before,
    3074 .message-action-delete:before {
     3074.message-action-delete:before,
     3075.message-action-exit:before {
    30753076        font-family: dashicons;
    30763077        font-size: 18px;
     
    30933094.message-action-delete:before {
    30943095        content: "\f153";
     3096}
     3097
     3098.message-action-exit:before {
     3099        content: "\f14a";
    30953100}
    30963101
  • trunk/src/bp-templates/bp-nouveau/css/twentytwentyone-rtl.css

    r12921 r13196  
    907907}
    908908
    909 #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:before {
     909#buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:before, #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-exit:before {
    910910        width: 32px;
    911911        height: 32px;
     
    914914}
    915915
    916 #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:hover:before {
     916#buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:hover:before, #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-exit:hover:before {
    917917        border-radius: 50%;
    918918        color: var(--global--color-background);
  • trunk/src/bp-templates/bp-nouveau/css/twentytwentyone.css

    r12921 r13196  
    907907}
    908908
    909 #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:before {
     909#buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:before, #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-exit:before {
    910910        width: 32px;
    911911        height: 32px;
     
    914914}
    915915
    916 #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:hover:before {
     916#buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-delete:hover:before, #buddypress.twentytwentyone .bp-messages-content .actions button.bp-tooltip.message-action-exit:hover:before {
    917917        border-radius: 50%;
    918918        color: var(--global--color-background);
  • trunk/src/bp-templates/bp-nouveau/includes/messages/ajax.php

    r12989 r13196  
    44 *
    55 * @since 3.0.0
    6  * @version 8.0.0
     6 * @version 10.0.0
    77 */
    88
     
    1212add_action( 'admin_init', function() {
    1313        $ajax_actions = array(
    14                 array( 'messages_send_message'             => array( 'function' => 'bp_nouveau_ajax_messages_send_message', 'nopriv' => false ) ),
    15                 array( 'messages_send_reply'               => array( 'function' => 'bp_nouveau_ajax_messages_send_reply', 'nopriv' => false ) ),
    16                 array( 'messages_get_user_message_threads' => array( 'function' => 'bp_nouveau_ajax_get_user_message_threads', 'nopriv' => false ) ),
    17                 array( 'messages_thread_read'              => array( 'function' => 'bp_nouveau_ajax_messages_thread_read', 'nopriv' => false ) ),
    18                 array( 'messages_get_thread_messages'      => array( 'function' => 'bp_nouveau_ajax_get_thread_messages', 'nopriv' => false ) ),
    19                 array( 'messages_delete'                   => array( 'function' => 'bp_nouveau_ajax_delete_thread_messages', 'nopriv' => false ) ),
    20                 array( 'messages_unstar'                   => array( 'function' => 'bp_nouveau_ajax_star_thread_messages', 'nopriv' => false ) ),
    21                 array( 'messages_star'                     => array( 'function' => 'bp_nouveau_ajax_star_thread_messages', 'nopriv' => false ) ),
    22                 array( 'messages_unread'                   => array( 'function' => 'bp_nouveau_ajax_readunread_thread_messages', 'nopriv' => false ) ),
    23                 array( 'messages_read'                     => array( 'function' => 'bp_nouveau_ajax_readunread_thread_messages', 'nopriv' => false ) ),
    24                 array( 'messages_dismiss_sitewide_notice'  => array( 'function' => 'bp_nouveau_ajax_dismiss_sitewide_notice', 'nopriv' => false ) ),
     14                array(
     15                        'messages_send_message' => array(
     16                                'function' => 'bp_nouveau_ajax_messages_send_message',
     17                                'nopriv'   => false,
     18                        ),
     19                ),
     20                array(
     21                        'messages_send_reply' => array(
     22                                'function' => 'bp_nouveau_ajax_messages_send_reply',
     23                                'nopriv'  => false,
     24                        ),
     25                ),
     26                array(
     27                        'messages_get_user_message_threads' => array(
     28                                'function' => 'bp_nouveau_ajax_get_user_message_threads',
     29                                'nopriv'   => false,
     30                        ),
     31                ),
     32                array(
     33                        'messages_thread_read' => array(
     34                                'function' => 'bp_nouveau_ajax_messages_thread_read',
     35                                'nopriv'   => false,
     36                        ),
     37                ),
     38                array(
     39                        'messages_get_thread_messages' => array(
     40                                'function' => 'bp_nouveau_ajax_get_thread_messages',
     41                                'nopriv'   => false,
     42                        ),
     43                ),
     44                array(
     45                        'messages_delete' => array(
     46                                'function' => 'bp_nouveau_ajax_delete_thread_messages',
     47                                'nopriv'   => false,
     48                        ),
     49                ),
     50                array(
     51                        'messages_exit' => array(
     52                                'function' => 'bp_nouveau_ajax_exit_thread_messages',
     53                                'nopriv'   => false,
     54                        ),
     55                ),
     56                array(
     57                        'messages_unstar' => array(
     58                                'function' => 'bp_nouveau_ajax_star_thread_messages',
     59                                'nopriv'   => false,
     60                        ),
     61                ),
     62                array(
     63                        'messages_star' => array(
     64                                'function' => 'bp_nouveau_ajax_star_thread_messages',
     65                                'nopriv'   => false,
     66                        ),
     67                ),
     68                array(
     69                        'messages_unread' => array(
     70                                'function' => 'bp_nouveau_ajax_readunread_thread_messages',
     71                                'nopriv'   => false,
     72                        ),
     73                ),
     74                array(
     75                        'messages_read' => array(
     76                                'function' => 'bp_nouveau_ajax_readunread_thread_messages',
     77                                'nopriv'   => false,
     78                        ),
     79                ),
     80                array(
     81                        'messages_dismiss_sitewide_notice'  => array(
     82                                'function' => 'bp_nouveau_ajax_dismiss_sitewide_notice',
     83                                'nopriv' => false,
     84                        ),
     85                ),
    2586        );
    2687
     
    781842        }
    782843}
     844
     845/**
     846 * Ajax Handler of the exit action.
     847 *
     848 * @since 10.0.0
     849 */
     850function bp_nouveau_ajax_exit_thread_messages() {
     851        $response = array(
     852                'feedback' => __( 'There was a problem exiting the conversation. Please try again.', 'buddypress' ),
     853                'type'     => 'error',
     854        );
     855
     856        if ( empty( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'bp_nouveau_messages' ) ) {
     857                wp_send_json_error( $response );
     858        }
     859
     860        if ( empty( $_POST['id'] ) ) {
     861                wp_send_json_error( $response );
     862        }
     863
     864        $thread_ids = wp_parse_id_list( $_POST['id'] );
     865
     866        foreach ( $thread_ids as $thread_id ) {
     867                if ( ! messages_check_thread_access( $thread_id ) && ! bp_current_user_can( 'bp_moderate' ) ) {
     868                        wp_send_json_error( $response );
     869                }
     870
     871                bp_messages_exit_thread( $thread_id );
     872        }
     873
     874        wp_send_json_success( array(
     875                'feedback' => __( 'You have left the message thread.', 'buddypress' ),
     876                'type'     => 'success',
     877        ) );
     878}
  • trunk/src/bp-templates/bp-nouveau/js/buddypress-messages.js

    r12941 r13196  
    979979                                bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
    980980
    981                                 if ( 'delete' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
     981                                if ( 'delete' === action || 'exit' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
    982982                                        // Remove from the list of messages.
    983983                                        self.collection.remove( model.get( 'id' ) );
     
    10901090                                bp.Nouveau.Messages.displayFeedback( response.feedback, response.type );
    10911091
    1092                                 if ( 'delete' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
     1092                                if ( 'delete' === action || 'exit' === action || ( 'starred' === self.collection.options.box && 'unstar' === action ) ) {
    10931093                                        // Remove from the list of messages.
    10941094                                        self.collection.remove( thread_ids );
     
    12421242                        bp.Nouveau.Messages.threads.doAction( action, this.model.get( 'id' ), options ).done( function( response ) {
    12431243                                // Remove all views
    1244                                 if ( 'delete' === action ) {
     1244                                if ( 'delete' === action || 'exit' === action ) {
    12451245                                        bp.Nouveau.Messages.clearViews();
    12461246                                } else if ( response.messages ) {
  • trunk/src/bp-templates/bp-nouveau/sass/_nouveau_messages.scss

    r12398 r13196  
    88.message-action-unstar:before,
    99.message-action-view:before,
    10 .message-action-delete:before {
     10.message-action-delete:before,
     11.message-action-exit:before {
    1112        font-family: dashicons;
    1213        font-size: 18px;
     
    2930.message-action-delete:before {
    3031        content: "\f153";
     32}
     33
     34.message-action-exit:before {
     35        content: "\f14a";
    3136}
    3237
  • trunk/src/bp-templates/bp-nouveau/sass/twentytwentyone.scss

    r12921 r13196  
    12281228                                background: none;
    12291229
    1230                                 &.message-action-delete {
     1230                                &.message-action-delete,
     1231                                &.message-action-exit {
    12311232
    12321233                                        &:before {
  • trunk/tests/phpunit/testcases/messages/class.bp-messages-thread.php

    r13148 r13196  
    672672                $this->assertEquals( 'Bar and baz.', $thread->last_message_content );
    673673        }
     674
     675        /**
     676         * @group exit
     677         * @ticket BP7540
     678         */
     679        public function test_bp_messages_thread_exit() {
     680                $u1 = self::factory()->user->create();
     681                $u2 = self::factory()->user->create();
     682                $u3 = self::factory()->user->create();
     683
     684                $message = self::factory()->message->create_and_get( array(
     685                        'sender_id' => $u1,
     686                        'recipients' => array( $u2, $u3 ),
     687                        'subject' => 'Foo Bar',
     688                        'date_sent' => bp_core_current_time(),
     689                        'content' => 'Foo Bar is there.',
     690                ) );
     691
     692                $t1 = $message->thread_id;
     693
     694                $this->assertTrue( BP_Messages_Thread::exit_thread( $t1, $u3 ) );
     695        }
     696
     697        /**
     698         * @group exit
     699         * @ticket BP7540
     700         */
     701        public function test_bp_messages_thread_exit_not_enougth_recipients() {
     702                $u1 = self::factory()->user->create();
     703                $u2 = self::factory()->user->create();
     704
     705                $message = self::factory()->message->create_and_get( array(
     706                        'sender_id' => $u1,
     707                        'recipients' => array( $u2 ),
     708                        'subject' => 'Bar Foo',
     709                        'date_sent' => bp_core_current_time(),
     710                        'content' => 'Bar Foo is also there.',
     711                ) );
     712
     713                $t1 = $message->thread_id;
     714
     715                $this->assertFalse( BP_Messages_Thread::exit_thread( $t1, $u2 ) );
     716        }
     717
     718        /**
     719         * @group exit
     720         * @ticket BP7540
     721         */
     722        public function test_bp_messages_thread_exit_not_one_of_recipients() {
     723                $u1 = self::factory()->user->create();
     724                $u2 = self::factory()->user->create();
     725                $u3 = self::factory()->user->create();
     726                $u4 = self::factory()->user->create();
     727
     728                $message = self::factory()->message->create_and_get( array(
     729                        'sender_id' => $u1,
     730                        'recipients' => array( $u2, $u3 ),
     731                        'subject' => 'Taz',
     732                        'date_sent' => bp_core_current_time(),
     733                        'content' => 'Where is Taz?',
     734                ) );
     735
     736                $t1 = $message->thread_id;
     737
     738                $this->assertFalse( BP_Messages_Thread::exit_thread( $t1, $u4 ) );
     739        }
    674740}
Note: See TracChangeset for help on using the changeset viewer.