Skip to:
Content

BuddyPress.org

Changeset 13103


Ignore:
Timestamp:
09/09/2021 02:01:40 PM (6 weeks ago)
Author:
espellcaste
Message:

Improving the group member count routine and the function helper.

The group member count routine was updated to avoid direct, uncached, SQL query and unnecessary cache refresh when a group's Members page was viewed.

is now being used to get the group member count which takes into account users' existence in the site,

the query is now cached and filterable.

was also updated to get the current group from if available.

Props imath
Fixes #7614 and see #6749

Location:
trunk
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/bp-groups/bp-groups-functions.php

    r13101 r13103  
    7878 *                          Possible values are `'id'` or `'slug'`.
    7979 * @param string|int $value (Required) A value for the $field. A Group ID or slug.
    80  * @return BP_Groups_Group|false The Group object if found, false otherwise.
     80 * @return BP_Groups_Group|bool The Group object if found, false otherwise.
    8181 */
    8282function bp_get_group_by( $field, $value ) {
     
    104104 * @since 10.0.0
    105105 *
     106 * @global BP_Groups_Template $groups_template Groups template object.
     107 *
    106108 * @param false|int|string|BP_Groups_Group $group (Optional) The Group ID, the Group Slug or the Group object.
    107109 *                                                Default: false.
    108  * @return BP_Groups_Group|false                  The Group object if found, false otherwise.
     110 * @return BP_Groups_Group|bool The Group object if found, false otherwise.
    109111 */
    110112function bp_get_group( $group = false ) {
     
    115117    if ( $group instanceof BP_Groups_Group ) {
    116118        $group_obj = $group;
    117     } elseif ( is_string( $group ) ) {
    118         $group_obj = bp_get_group_by( 'slug', $group );
    119     } elseif ( is_numeric( $group ) ) {
    120         $group_obj = bp_get_group_by( 'id', $group );
    121     } elseif ( isset( $groups_template->group ) && is_object( $groups_template->group ) ) {
     119
     120        // Nothing requested? Let's use the current Group of the Groups Loop, if available.
     121    } elseif ( ! $group && isset( $groups_template->group ) && is_object( $groups_template->group ) ) {
    122122        $group_obj = $groups_template->group;
     123    } else {
     124        $current_group = null;
     125
     126        // Let's get the current group if we can.
     127        if ( did_action( 'bp_groups_set_current_group' ) ) {
     128            $current_group = groups_get_current_group();
     129        }
     130
     131        $field = '';
     132        if ( is_string( $group ) ) {
     133            $field = 'slug';
     134        } elseif ( is_numeric( $group ) ) {
     135            $field = 'id';
     136            $group = (int) $group;
     137        }
     138
     139        // Let's use the current Group if it matches with the requested field value.
     140        if ( isset( $current_group->{$field} ) && $current_group->{$field} === $group ) {
     141            $group_obj = $current_group;
     142        } else {
     143            $group_obj = bp_get_group_by( $field, $group );
     144        }
    123145    }
    124146
     
    482504    $bp = buddypress();
    483505
    484     return in_array( $status, (array) $bp->groups->valid_status );
     506    return in_array( $status, (array) $bp->groups->valid_status, true );
    485507}
    486508
     
    534556 *
    535557 * @param string $group_slug The group's slug.
    536  * @return int|null The group ID on success; null on failure.
     558 * @return int|null The group ID on success, null on failure.
    537559 */
    538560function groups_get_id( $group_slug ) {
     
    546568 *
    547569 * @param string $group_slug The group's slug.
    548  * @return int|null The group ID on success; null on failure.
     570 * @return int|null The group ID on success, null on failure.
    549571 */
    550572function groups_get_id_by_previous_slug( $group_slug ) {
     
    685707    groups_update_groupmeta( $group_id, 'last_activity', bp_core_current_time() );
    686708}
    687 add_action( 'groups_join_group',           'groups_update_last_activity' );
    688 add_action( 'groups_leave_group',          'groups_update_last_activity' );
    689 add_action( 'groups_created_group',        'groups_update_last_activity' );
     709add_action( 'groups_join_group', 'groups_update_last_activity' );
     710add_action( 'groups_leave_group', 'groups_update_last_activity' );
     711add_action( 'groups_created_group', 'groups_update_last_activity' );
    690712
    691713/** General Group Functions ***************************************************/
     
    824846 *
    825847 * @since 1.2.3
    826  *
    827  * @param int $group_id Group ID.
    828  * @return int Count of confirmed members for the group.
    829  */
    830 function groups_get_total_member_count( $group_id ) {
    831     return BP_Groups_Group::get_total_member_count( $group_id );
     848 * @since 10.0.0 Updated to use `bp_get_group`.
     849 *
     850 * @param int|string|BP_Groups_Group $group      The Group ID, the Group Slug or the Group object.
     851 * @param bool                       $skip_cache Optional. Skip grabbing from cache. Defaults to false.
     852 * @return int|bool Count of confirmed members for the group. False if group doesn't exist.
     853 */
     854function groups_get_total_member_count( $group, $skip_cache = false ) {
     855
     856    $group = bp_get_group( $group );
     857
     858    if ( empty( $group->id ) ) {
     859        return false;
     860    }
     861
     862    return (int) BP_Groups_Group::get_total_member_count( $group->id, (bool) $skip_cache );
    832863}
    833864
     
    919950 *
    920951 * @since 1.2.0
    921  *
     952 * @since 10.0.0 Added the `$skip_cache` parameter.
     953 *
     954 * @param bool $skip_cache Optional. Skip getting count from cache.
     955 *                         Defaults to false.
    922956 * @return int
    923957 */
    924 function groups_get_total_group_count() {
    925     $count = wp_cache_get( 'bp_total_group_count', 'bp' );
    926 
    927     if ( false === $count ) {
    928         $count = BP_Groups_Group::get_total_group_count();
    929         wp_cache_set( 'bp_total_group_count', $count, 'bp' );
    930     }
    931 
    932     return $count;
     958function groups_get_total_group_count( $skip_cache = false ) {
     959    return (int) BP_Groups_Group::get_total_group_count( $skip_cache );
    933960}
    934961
     
    950977function groups_get_user_groups( $user_id = 0, $pag_num = 0, $pag_page = 0 ) {
    951978
    952     if ( empty( $user_id ) )
     979    if ( empty( $user_id ) ) {
    953980        $user_id = bp_displayed_user_id();
     981    }
    954982
    955983    return BP_Groups_Member::get_group_ids( $user_id, $pag_num, $pag_page );
     
    11791207 * @since 1.5.0
    11801208 *
    1181  * @return BP_Groups_Group The current group object.
     1209 * @global BuddyPress $bp The one true BuddyPress instance.
     1210 *
     1211 * @return BP_Groups_Group|bool The current group object or false.
    11821212 */
    11831213function groups_get_current_group() {
     
    11931223     * @since 1.5.0
    11941224     *
    1195      * @param BP_Groups_Group $current_group Current BP_Groups_Group object.
     1225     * @param BP_Groups_Group|bool $current_group Current BP_Groups_Group object or false.
    11961226     */
    11971227    return apply_filters( 'groups_get_current_group', $current_group );
  • trunk/src/bp-groups/classes/class-bp-groups-component.php

    r13101 r13103  
    266266            }
    267267
     268            // Make sure the Group ID is an integer.
     269            $this->current_group->id = (int) $this->current_group->id;
     270
    268271            // When in a single group, the first action is bumped down one because of the
    269272            // group name, so we need to adjust this and set the group name to current_item.
     
    281284            // If the user is not an admin, check if they are a moderator.
    282285            if ( ! bp_is_item_admin() ) {
    283                 bp_update_is_item_mod  ( groups_is_user_mod  ( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
     286                bp_update_is_item_mod( groups_is_user_mod( bp_loggedin_user_id(), $this->current_group->id ), 'groups' );
    284287            }
    285288
    286289            // Check once if the current group has a custom front template.
    287290            $this->current_group->front_template = bp_groups_get_front_template( $this->current_group );
     291
     292            /**
     293             * Fires once the `current_group` global is fully set.
     294             *
     295             * @since 10.0.0
     296             *
     297             * @param BP_Groups_Group|object $current_group The current group object.
     298             */
     299            do_action_ref_array( 'bp_groups_set_current_group', array( $this->current_group ) );
    288300
    289301            // Initialize the nav for the groups component.
  • trunk/src/bp-groups/classes/class-bp-groups-group.php

    r13086 r13103  
    17241724     *
    17251725     * @since 1.6.0
    1726      *
    1727      * @return int Group count.
    1728      */
    1729     public static function get_total_group_count() {
     1726     * @since 10.0.0 Added the `$skip_cache` parameter.
     1727     *
     1728     * @global BuddyPress $bp   The one true BuddyPress instance.
     1729     * @global wpdb       $wpdb WordPress database object.
     1730     *
     1731     * @param bool $skip_cache Optional. Skip getting count from cache.
     1732     *                         Defaults to false.
     1733     * @return int
     1734     */
     1735    public static function get_total_group_count( $skip_cache = false ) {
    17301736        global $wpdb;
    17311737
    1732         $hidden_sql = '';
    1733         if ( !bp_current_user_can( 'bp_moderate' ) )
    1734             $hidden_sql = "WHERE status != 'hidden'";
    1735 
    1736         $bp = buddypress();
    1737 
    1738         return $wpdb->get_var( "SELECT COUNT(id) FROM {$bp->groups->table_name} {$hidden_sql}" );
     1738        $cache_key = 'bp_total_group_count';
     1739        $count     = wp_cache_get( $cache_key, 'bp' );
     1740
     1741        if ( false === $count || true === $skip_cache ) {
     1742            $hidden_sql = '';
     1743            if ( ! bp_current_user_can( 'bp_moderate' ) ) {
     1744                $hidden_sql = "WHERE status != 'hidden'";
     1745            }
     1746
     1747            $bp    = buddypress();
     1748            $count = $wpdb->get_var( "SELECT COUNT(id) FROM {$bp->groups->table_name} {$hidden_sql}" );
     1749
     1750            wp_cache_set( $cache_key, (int) $count, 'bp' );
     1751        }
     1752
     1753        /**
     1754         * Filters the total group count.
     1755         *
     1756         * @since 10.0.0
     1757         *
     1758         * @param int $count Total group count.
     1759         */
     1760        return (int) apply_filters( 'bp_groups_total_group_count', (int) $count );
    17391761    }
    17401762
     
    17431765     *
    17441766     * @since 1.6.0
    1745      *
    1746      * @param int $group_id Group ID.
     1767     * @since 10.0.0 Updated to use the `groups_get_group_members`.
     1768     *
     1769     * @param int  $group_id   Group ID.
     1770     * @param bool $skip_cache Optional. Skip getting count from cache. Defaults to false.
    17471771     * @return int Count of confirmed members for the group.
    17481772     */
    1749     public static function get_total_member_count( $group_id ) {
    1750         global $wpdb;
    1751 
    1752         $bp = buddypress();
    1753 
    1754         return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 1 AND is_banned = 0", $group_id ) );
     1773    public static function get_total_member_count( $group_id, $skip_cache = false ) {
     1774        $cache_key = 'total_member_count';
     1775        $count     = groups_get_groupmeta( $group_id, $cache_key );
     1776
     1777        if ( false === $count || true === $skip_cache ) {
     1778            $members = groups_get_group_members(
     1779                array(
     1780                    'group_id'            => $group_id,
     1781                    'exclude_banned'      => true,
     1782                    'exclude_admins_mods' => false,
     1783                    'type'                => 'active',
     1784                )
     1785            );
     1786
     1787            $count = $members['count'] ? $members['count'] : 0;
     1788
     1789            groups_update_groupmeta( $group_id, $cache_key, (int) $count );
     1790        }
     1791
     1792        /**
     1793         * Filters the total member count for a group.
     1794         *
     1795         * @since 10.0.0
     1796         *
     1797         * @param int $count    Total member count for group.
     1798         * @param int $group_id The ID of the group.
     1799         */
     1800        return (int) apply_filters( 'bp_groups_total_member_count', (int) $count, (int) $group_id );
    17551801    }
    17561802
  • trunk/src/bp-groups/classes/class-bp-groups-list-table.php

    r12788 r13103  
    702702     *
    703703     * @since 1.7.0
     704     * @since 10.0.0 Updated to use `groups_get_total_member_count`.
    704705     *
    705706     * @param array $item Information about the current row.
    706707     */
    707708    public function column_members( $item = array() ) {
    708         $count = groups_get_groupmeta( $item['id'], 'total_member_count' );
     709        $count = groups_get_total_member_count( absint( $item['id'] ) );
    709710
    710711        /**
  • trunk/src/bp-groups/classes/class-bp-groups-member.php

    r13097 r13103  
    466466
    467467    /**
    468      * Refresh the total_group_count for a user.
     468     * Refresh the `total_group_count` for a user.
    469469     *
    470470     * @since 1.8.0
    471471     *
    472472     * @param int $user_id ID of the user.
    473      * @return bool True on success, false on failure.
    474473     */
    475474    public static function refresh_total_group_count_for_user( $user_id ) {
    476         return bp_update_user_meta( $user_id, 'total_group_count', (int) self::total_group_count( $user_id ) );
    477     }
    478 
    479     /**
    480      * Refresh the total_member_count for a group.
     475        bp_update_user_meta( $user_id, 'total_group_count', (int) self::total_group_count( $user_id ) );
     476    }
     477
     478    /**
     479     * Refresh the `total_member_count` for a group.
     480     *
     481     * The request skip the current cache so that we always grab the lastest total count.
    481482     *
    482483     * @since 1.8.0
     484     * @since 10.0.0 Updated to use `BP_Groups_Group::get_total_member_count`
    483485     *
    484486     * @param int $group_id ID of the group.
    485      * @return bool|int True on success, false on failure.
    486487     */
    487488    public static function refresh_total_member_count_for_group( $group_id ) {
    488         return groups_update_groupmeta( $group_id, 'total_member_count', (int) BP_Groups_Group::get_total_member_count( $group_id ) );
     489        BP_Groups_Group::get_total_member_count( $group_id, true );
    489490    }
    490491
     
    496497     * @param int $user_id  ID of the user.
    497498     * @param int $group_id ID of the group.
    498      * @return True on success, false on failure.
     499     * @return bool True on success, false on failure.
    499500     */
    500501    public static function delete( $user_id, $group_id ) {
     
    511512        do_action( 'bp_groups_member_before_delete', $user_id, $group_id );
    512513
    513         $bp = buddypress();
     514        $bp     = buddypress();
    514515        $remove = $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name_members} WHERE user_id = %d AND group_id = %d", $user_id, $group_id ) );
    515516
     
    530531        do_action( 'bp_groups_member_after_delete', $user_id, $group_id );
    531532
    532         return $remove;
     533        return (bool) $remove;
    533534    }
    534535
  • trunk/src/bp-groups/screens/single/members.php

    r11923 r13103  
    1515function groups_screen_group_members() {
    1616
    17     if ( !bp_is_single_item() )
     17    if ( ! bp_is_single_item() ) {
    1818        return false;
     19    }
    1920
    2021    $bp = buddypress();
    21 
    22     // Refresh the group member count meta.
    23     groups_update_groupmeta( $bp->groups->current_group->id, 'total_member_count', groups_get_total_member_count( $bp->groups->current_group->id ) );
    2422
    2523    /**
  • trunk/tests/phpunit/testcases/groups/cache.php

    r11737 r13103  
    260260        $this->assertEquals( $first_query_count, $wpdb->num_queries );
    261261    }
     262
     263    /**
     264     * @group groups_get_total_group_count
     265     * @group counts
     266     */
     267    public function test_total_groups_count() {
     268        $u1 = self::factory()->user->create();
     269        $u2 = self::factory()->user->create();
     270        $u3 = self::factory()->user->create();
     271        self::factory()->group->create( array( 'creator_id' => $u1 ) );
     272        self::factory()->group->create( array( 'creator_id' => $u2 ) );
     273
     274        $this->assertEquals( 2, groups_get_total_group_count() );
     275        $this->assertEquals( 2, BP_Groups_Group::get_total_group_count() );
     276
     277        self::factory()->group->create( array( 'creator_id' => $u3 ) );
     278
     279        $this->assertEquals( 3, groups_get_total_group_count( true ) );
     280        $this->assertEquals( 3, BP_Groups_Group::get_total_group_count() );
     281    }
    262282}
  • trunk/tests/phpunit/testcases/groups/functions.php

    r12605 r13103  
    185185
    186186        groups_join_group( $g, $u2 );
    187         $this->assertEquals( 2, groups_get_groupmeta( $g, 'total_member_count' ) );
     187        $this->assertEquals( 2, groups_get_total_member_count( $g ) );
     188    }
     189
     190    /**
     191     * @group total_member_count
     192     */
     193    public function test_total_member_count_with_invalid_group() {
     194        $this->assertFalse( groups_get_total_member_count( 'invalid-group' ) );
     195        $this->assertFalse( groups_get_total_member_count( '' ) );
     196        $this->assertFalse( groups_get_total_member_count( 123456789 ) );
    188197    }
    189198
     
    194203    public function test_total_member_count_groups_leave_group() {
    195204        $u1 = self::factory()->user->create();
     205        $u2 = self::factory()->user->create();
    196206        $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
    197         groups_join_group( $g1, $u1 );
    198 
    199         groups_leave_group( $g1, $u1 );
    200         $this->assertEquals( 1, groups_get_groupmeta( $g1, 'total_member_count' ) );
     207
     208        groups_join_group( $g1, $u2 );
     209
     210        $this->assertEquals( 2, groups_get_total_member_count( $g1 ) );
     211
     212        groups_leave_group( $g1, $u2 );
     213
     214        $this->assertEquals( 1, groups_get_total_member_count( $g1 ) );
    201215    }
    202216
     
    215229        buddypress()->is_item_admin = true;
    216230
     231        $this->assertEquals( 2, groups_get_total_member_count( $g1 ) );
     232
    217233        groups_ban_member( $u2, $g1 );
    218234
    219         $this->assertEquals( 1, groups_get_groupmeta( $g1, 'total_member_count' ) );
     235        $this->assertEquals( 1, groups_get_total_member_count( $g1 ) );
    220236    }
    221237
     
    236252        groups_ban_member( $u2, $g1 );
    237253
     254        $this->assertEquals( 1, groups_get_total_member_count( $g1 ) );
     255
    238256        groups_unban_member( $u2, $g1 );
    239257
    240         $this->assertEquals( 2, groups_get_groupmeta( $g1, 'total_member_count' ) );
     258        $this->assertEquals( 2, groups_get_total_member_count( $g1 ) );
    241259    }
    242260
     
    256274        ) );
    257275
     276        $this->assertEquals( 1, groups_get_total_member_count( $g ) );
     277
    258278        groups_accept_invite( $u2, $g );
    259279
    260         $this->assertEquals( 2, groups_get_groupmeta( $g, 'total_member_count' ) );
     280        $this->assertEquals( 2, groups_get_total_member_count( $g ) );
    261281    }
    262282
     
    276296        groups_accept_membership_request( 0, $u2, $g );
    277297
    278         $this->assertEquals( 2, groups_get_groupmeta( $g, 'total_member_count' ) );
     298        $this->assertEquals( 2, groups_get_total_member_count( $g ) );
    279299    }
    280300
     
    295315        groups_remove_member( $u2, $g1 );
    296316
    297         $this->assertEquals( 1, groups_get_groupmeta( $g1, 'total_member_count' ) );
     317        $this->assertEquals( 1, groups_get_total_member_count( $g1 ));
     318    }
     319
     320    /**
     321     * @group total_member_count
     322     * @group groups_remove_member
     323     */
     324    public function test_total_member_count_groups_delete_member() {
     325        $u1 = self::factory()->user->create();
     326        $u2 = self::factory()->user->create();
     327        $u3 = self::factory()->user->create();
     328        $g1 = self::factory()->group->create( array( 'creator_id' => $u1 ) );
     329
     330        groups_join_group( $g1, $u2 );
     331        groups_join_group( $g1, $u3 );
     332
     333        $this->assertEquals( 3, groups_get_total_member_count( $g1 ) );
     334        $this->assertEquals( 3, BP_Groups_Group::get_total_member_count( $g1 ) );
     335
     336        add_filter( 'bp_remove_user_data_on_delete_user_hook', '__return_true' );
     337
     338        // Delete user.
     339        wp_delete_user( $u2 );
     340
     341        remove_filter( 'bp_remove_user_data_on_delete_user_hook', '__return_true' );
     342
     343        $this->assertEquals( 2, groups_get_total_member_count( $g1 ) );
     344        $this->assertEquals( 2, BP_Groups_Group::get_total_member_count( $g1 ) );
    298345    }
    299346
     
    314361        ) );
    315362
    316         $this->assertEquals( 1, groups_get_groupmeta( $g, 'total_member_count' ) );
     363        $this->assertEquals( 1, groups_get_total_member_count( $g ) );
    317364    }
    318365
  • trunk/tests/phpunit/testcases/groups/functions/get-group.php

    r13097 r13103  
    2323    }
    2424
     25    /**
     26     * @group bp_get_group
     27     */
    2528    public function test_bp_get_group_with_no_group() {
    2629        $this->assertFalse( bp_get_group() );
     
    2831    }
    2932
     33    /**
     34     * @group bp_get_group
     35     */
    3036    public function test_bp_get_group_with_id() {
    3137        $g = $this->factory->group->create();
     
    3642    }
    3743
     44    /**
     45     * @group bp_get_group
     46     */
    3847    public function test_bp_get_group_with_slug() {
    3948        $slug = 'test-group';
     
    5059    }
    5160
     61    /**
     62     * @group bp_get_group
     63     */
    5264    public function test_bp_get_group_with_object() {
    5365        $g = $this->factory->group->create_and_get();
     
    5668    }
    5769
     70    /**
     71     * @group bp_get_group
     72     */
    5873    public function test_bp_get_group_from_groups_template() {
    5974        $g = $this->factory->group->create( array( 'status' => 'private' ) );
    6075
    61         // Fake the current group.
    62         $GLOBALS['groups_template'] = new stdClass;
    63         $GLOBALS['groups_template']->group = groups_get_group( $g );
     76        if ( bp_has_groups( array( 'include' => array( $g ) ) ) ) {
     77            while ( bp_groups() ) {
     78                bp_the_group();
     79                $group = bp_get_group();
     80            }
     81        }
    6482
    65         $this->assertSame( $g, bp_get_group()->id );
     83        $this->assertSame( $g, $group->id );
     84    }
     85
     86    /**
     87     * @group bp_get_group
     88     */
     89    public function test_bp_get_group_from_current_group() {
     90        $bp = buddypress();
     91        $g  = $this->factory->group->create_and_get( array( 'name' => 'foo' ) );
     92
     93        // Set the current group.
     94        $bp->groups->current_group = $g;
     95
     96        // Change the name to check the current group was used.
     97        $bp->groups->current_group->name = 'bar';
     98
     99        // Override the name
     100        do_action( 'bp_groups_set_current_group' );
     101
     102        $this->assertSame( 'bar', bp_get_group( $g->id )->name );
    66103    }
    67104}
Note: See TracChangeset for help on using the changeset viewer.