Skip to:
Content

BuddyPress.org

Ticket #8688: 8688.2.patch

File 8688.2.patch, 11.6 KB (added by imath, 3 years ago)
  • src/bp-groups/bp-groups-admin.php

    diff --git src/bp-groups/bp-groups-admin.php src/bp-groups/bp-groups-admin.php
    index a9701c106..e9674d433 100644
    function bp_groups_admin_load() { 
    354354                }
    355355
    356356                if ( ! empty( $user_names ) ) {
     357                        $new_members = count( $user_names );
     358
     359                        if ( 1 < $new_members ) {
     360                                bp_groups_defer_group_members_count( $group_id, true );
     361                        }
    357362
    358363                        foreach( array_values( $user_names ) as $user_name ) {
    359364                                $un = trim( $user_name );
    function bp_groups_admin_load() { 
    372377                                        }
    373378                                }
    374379                        }
     380
     381                        if ( 1 < $new_members ) {
     382                                bp_groups_defer_group_members_count( $group_id, false );
     383                        }
    375384                }
    376385
    377386                // Process member role changes.
  • src/bp-groups/bp-groups-functions.php

    diff --git src/bp-groups/bp-groups-functions.php src/bp-groups/bp-groups-functions.php
    index 4e3183e09..b1c23fb51 100644
    function bp_init_group_extensions() { 
    36783678        }
    36793679}
    36803680add_action( 'bp_init', 'bp_init_group_extensions', 11 );
     3681
     3682/**
     3683 * Updates a group members count when a user joined or left the group.
     3684 *
     3685 * @since 10.3.0
     3686 *
     3687 * @param BP_Groups_Member|int $groups_member The BP_Groups_Member object or the group member ID.
     3688 * @param int                  $group_id      The group's ID.
     3689 */
     3690function bp_groups_update_group_members_count( $groups_member, $group_id = 0 ) {
     3691        if ( true === $groups_member instanceof BP_Groups_Member ) {
     3692                $group_id = $groups_member->group_id;
     3693        }
     3694
     3695        BP_Groups_Member::refresh_total_member_count_for_group( (int) $group_id );
     3696}
     3697add_action( 'groups_member_after_save', 'bp_groups_update_group_members_count' );
     3698add_action( 'groups_member_after_remove', 'bp_groups_update_group_members_count' );
     3699add_action( 'bp_groups_member_after_delete', 'bp_groups_update_group_members_count', 10, 2 );
     3700
     3701/**
     3702 * Defers a group's counting to avoid updating it when batch adding/removing users to this group.
     3703 *
     3704 * @since 10.3.0
     3705 *
     3706 * @param int $group_id The group's ID.
     3707 * @param bool $defer True to defer, false otherwise.
     3708 */
     3709function bp_groups_defer_group_members_count( $group_id = 0, $defer = true ) {
     3710        if ( $defer ) {
     3711                remove_action( 'groups_member_after_save', 'bp_groups_update_group_members_count' );
     3712                remove_action( 'groups_member_after_remove', 'bp_groups_update_group_members_count' );
     3713                remove_action( 'bp_groups_member_after_delete', 'bp_groups_update_group_members_count', 10, 2 );
     3714        } else {
     3715                add_action( 'groups_member_after_save', 'bp_groups_update_group_members_count' );
     3716                add_action( 'groups_member_after_remove', 'bp_groups_update_group_members_count' );
     3717                add_action( 'bp_groups_member_after_delete', 'bp_groups_update_group_members_count', 10, 2 );
     3718
     3719                BP_Groups_Member::refresh_total_member_count_for_group( (int) $group_id );
     3720        }
     3721}
  • src/bp-groups/classes/class-bp-group-member-query.php

    diff --git src/bp-groups/classes/class-bp-group-member-query.php src/bp-groups/classes/class-bp-group-member-query.php
    index 267c81e09..d91224978 100644
    class BP_Group_Member_Query extends BP_User_Query { 
    4949         */
    5050        protected $group_member_ids;
    5151
     52        /**
     53         * Constructor.
     54         *
     55         * @since 10.3.0
     56         *
     57         * @param string|array|null $query See {@link BP_User_Query}.
     58         */
     59        public function __construct( $query = null ) {
     60                $qv = bp_parse_args(
     61                        $query,
     62                        array(
     63                                'count' => false, // True to perform a count query. False otherwise.
     64                        )
     65                );
     66
     67                parent::__construct( $qv );
     68        }
     69
    5270        /**
    5371         * Set up action hooks.
    5472         *
    class BP_Group_Member_Query extends BP_User_Query { 
    6280                        $this->query_vars_raw['type'] = 'last_joined';
    6381                }
    6482
    65                 // Set the sort order.
    66                 add_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) );
     83                if ( ! $this->query_vars_raw['count'] ) {
     84                        // Set the sort order.
     85                        add_action( 'bp_pre_user_query', array( $this, 'set_orderby' ) );
    6786
    68                 // Set up our populate_extras method.
    69                 add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     87                        // Set up our populate_extras method.
     88                        add_action( 'bp_user_query_populate_extras', array( $this, 'populate_group_member_extras' ), 10, 2 );
     89                } else {
     90                        $this->query_vars_raw['orderby'] = 'ID';
     91                }
     92        }
     93
     94        /**
     95         * Use WP_User_Query() to pull data for the user IDs retrieved in the main query.
     96         *
     97         * If a `count` query is performed, the function is used to validate existing users.
     98         *
     99         * @since 10.3.0
     100         */
     101        public function do_wp_user_query() {
     102                if ( ! $this->query_vars_raw['count'] ) {
     103                        return parent::do_wp_user_query();
     104                }
     105
     106                /**
     107                 * Filters the WP User Query arguments before passing into the class.
     108                 *
     109                 * @since 10.3.0
     110                 *
     111                 * @param array         $value Array of arguments for the user query.
     112                 * @param BP_User_Query $this  Current BP_User_Query instance.
     113                 */
     114                $wp_user_query = new WP_User_Query(
     115                        apply_filters(
     116                                'bp_group_members_count_query_args',
     117                                array(
     118                                        // Relevant.
     119                                        'fields'      => 'ID',
     120                                        'include'     => $this->user_ids,
     121
     122                                        // Overrides
     123                                        'blog_id'     => 0,    // BP does not require blog roles.
     124                                        'count_total' => false // We already have a count.
     125
     126                                ),
     127                                $this
     128                        )
     129                );
     130
     131                // Validate existing user IDs.
     132                $this->user_ids = array_map( 'intval', $wp_user_query->results );
     133                $this->results  = $this->user_ids;
     134
     135                // Set the total existing users.
     136                $this->total_users = count( $this->user_ids );
    70137        }
    71138
    72139        /**
    class BP_Group_Member_Query extends BP_User_Query { 
    473540
    474541                return wp_list_pluck( $group_user_ids, 'user_id' );
    475542        }
     543
     544        /**
     545         * Perform a database query to populate any extra metadata we might need.
     546         *
     547         * If a `count` query is performed, the function is used to validate active users.
     548         *
     549         * @since 10.3.0
     550         */
     551        public function populate_extras() {
     552                if ( ! $this->query_vars_raw['count'] ) {
     553                        return parent::populate_extras();
     554                }
     555
     556                // Validate active users.
     557                $active_users    = array_filter( BP_Core_User::get_last_activity( $this->user_ids ) );
     558                $active_user_ids = array_keys( $active_users );
     559                $this->results   = array_intersect( $this->user_ids, $active_user_ids );
     560
     561                // Set the total active users.
     562                $this->total_users = count( $this->results );
     563        }
    476564}
  • src/bp-groups/classes/class-bp-groups-group.php

    diff --git src/bp-groups/classes/class-bp-groups-group.php src/bp-groups/classes/class-bp-groups-group.php
    index c0b518237..e837d72ed 100644
    class BP_Groups_Group { 
    17891789         * @return int Count of confirmed members for the group.
    17901790         */
    17911791        public static function get_total_member_count( $group_id, $skip_cache = false ) {
    1792                 $cache_key = 'total_member_count';
    1793                 $count     = groups_get_groupmeta( $group_id, $cache_key );
     1792                $meta_key = 'total_member_count';
     1793                $count    = groups_get_groupmeta( $group_id, $meta_key );
    17941794
    17951795                if ( false === $count || true === $skip_cache ) {
    1796                         $members = groups_get_group_members(
     1796                        $group_members = new BP_Group_Member_Query(
    17971797                                array(
    17981798                                        'group_id'   => $group_id,
    17991799                                        'group_role' => array( 'member', 'admin', 'mod' ),
    1800                                         'type'       => 'active',
     1800                                        'count'      => true,
    18011801                                )
    18021802                        );
    18031803
    1804                         $count = $members['count'] ? $members['count'] : 0;
    1805 
    1806                         groups_update_groupmeta( $group_id, $cache_key, (int) $count );
     1804                        $count = $group_members->total_users;
     1805                        groups_update_groupmeta( $group_id, $meta_key, $count );
    18071806                }
    18081807
    18091808                /**
    class BP_Groups_Group { 
    18141813                 * @param int $count    Total member count for group.
    18151814                 * @param int $group_id The ID of the group.
    18161815                 */
    1817                 return (int) apply_filters( 'bp_groups_total_member_count', (int) $count, (int) $group_id );
     1816                return (int) apply_filters( 'bp_groups_total_member_count', $count, (int) $group_id );
    18181817        }
    18191818
    18201819        /**
  • src/bp-groups/classes/class-bp-groups-member.php

    diff --git src/bp-groups/classes/class-bp-groups-member.php src/bp-groups/classes/class-bp-groups-member.php
    index d938800fe..10d511d45 100644
    class BP_Groups_Member { 
    309309                // Update the user's group count.
    310310                self::refresh_total_group_count_for_user( $this->user_id );
    311311
    312                 // Update the group's member count.
    313                 self::refresh_total_member_count_for_group( $this->group_id );
    314 
    315312                /**
    316313                 * Fires after the current group membership item has been saved.
    317314                 *
    class BP_Groups_Member { 
    447444                // Update the user's group count.
    448445                self::refresh_total_group_count_for_user( $this->user_id );
    449446
    450                 // Update the group's member count.
    451                 self::refresh_total_member_count_for_group( $this->group_id );
    452 
    453447                /**
    454448                 * Fires after a member is removed from a group.
    455449                 *
    class BP_Groups_Member { 
    517511                // Update the user's group count.
    518512                self::refresh_total_group_count_for_user( $user_id );
    519513
    520                 // Update the group's member count.
    521                 self::refresh_total_member_count_for_group( $group_id );
    522 
    523514                /**
    524515                 * Fires after a member is removed from a group.
    525516                 *
  • tests/phpunit/testcases/groups/functions.php

    diff --git tests/phpunit/testcases/groups/functions.php tests/phpunit/testcases/groups/functions.php
    index 208378547..a6d9059cc 100644
     
    77class BP_Tests_Groups_Functions extends BP_UnitTestCase {
    88        static public $group_ids;
    99        static public $user_ids;
     10        protected $did_group_member_count = 0;
    1011
    1112        static public function wpSetUpBeforeClass( $factory ) {
    1213                self::$user_ids  = $factory->user->create_many( 3 );
    class BP_Tests_Groups_Functions extends BP_UnitTestCase { 
    344345                $this->assertEquals( 2, BP_Groups_Group::get_total_member_count( $g1 ) );
    345346        }
    346347
     348        /**
     349         * @group total_member_count
     350         * @ticket BP8688
     351         */
     352        public function test_total_member_count_groups_inactive_user() {
     353                $u1 = self::factory()->user->create();
     354                $u2 = wp_insert_user( array(
     355                        'user_pass'  => 'foobar',
     356                        'user_login' => 'foobar',
     357                        'user_email' => 'foobar@buddypress.org',
     358                ) );
     359
     360                $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     361
     362                groups_join_group( $g1, $u2 );
     363
     364                $this->assertEquals( 1, groups_get_total_member_count( $g1 ) );
     365        }
     366
     367        /**
     368         * @group total_member_count
     369         * @ticket BP8688
     370         */
     371        public function test_total_member_count_groups_spammed_user() {
     372                $u1 = self::factory()->user->create();
     373                $u2 = self::factory()->user->create();
     374
     375                $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     376
     377                groups_join_group( $g1, $u2 );
     378                bp_core_process_spammer_status( $u2, 'spam' );
     379
     380                $this->assertEquals( 1, groups_get_total_member_count( $g1 ) );
     381        }
     382
     383        /**
     384         * @group total_member_count
     385         * @ticket BP8688
     386         */
     387        public function test_total_member_count_groups_deferred() {
     388                $u1 = self::factory()->user->create();
     389                $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     390                $members = array();
     391                $this->did_group_member_count = 0;
     392
     393                add_filter( 'bp_groups_total_member_count', array( $this, 'filter_bp_groups_total_member_count' ) );
     394
     395                bp_groups_defer_group_members_count( $g1, true );
     396                for ( $i = 1; $i < 6; $i++ ) {
     397                        $members[ $i ] = self::factory()->user->create();
     398                        groups_join_group( $g1, $members[ $i ] );
     399                }
     400                bp_groups_defer_group_members_count( $g1, false );
     401
     402                remove_filter( 'bp_groups_total_member_count', array( $this, 'filter_bp_groups_total_member_count' ) );
     403
     404                $this->assertTrue( 1 === $this->did_group_member_count );
     405                $this->assertEquals( count( $members ) + 1, groups_get_total_member_count( $g1 ) );
     406        }
     407
     408        public function filter_bp_groups_total_member_count( $count ) {
     409                $this->did_group_member_count += 1;
     410                return $count;
     411        }
     412
    347413        /**
    348414         * @group total_member_count
    349415         * @group groups_create_group