Skip to:
Content

Opened 8 months ago

Closed 7 months ago

#7382 closed enhancement (fixed)

groups_promote_member() shouldn't attempt to fetch `BP_Core_User` object

Reported by: r-a-y Owned by: boonebgorges
Milestone: 2.8 Priority: normal
Severity: normal Version: 1.0
Component: Groups Keywords: has-patch needs-unit-tests
Cc:

Description

When a member is being promoted and if the XProfile and Friends components are active, four DB queries are being run for no reason.

Here's a captured DB query log when a member is being promoted:


    [18] => Array
        (
            [0] => SELECT * FROM wp_bp_groups_members WHERE user_id = 7670 AND group_id = 1218
            [1] => 0.0004730224609375
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->__construct, BP_Groups_Member->populate
        )

    [19] => Array
        (
            [0] => SELECT DISTINCT g.id FROM wp_bp_xprofile_groups g INNER JOIN wp_bp_xprofile_fields f ON g.id = f.group_id  ORDER BY g.group_order ASC
            [1] => 0.00040388107299805
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->__construct, BP_Groups_Member->populate, BP_Core_User->__construct, BP_Core_User->populate, BP_Core_User->get_profile_data, BP_XProfile_ProfileData::get_all_for_user, bp_xprofile_get_groups, BP_XProfile_Group::get
        )

    [20] => Array
        (
            [0] => SELECT id, initiator_user_id, is_confirmed FROM wp_bp_friends WHERE (initiator_user_id = 7670 AND friend_user_id = 6178) OR (initiator_user_id = 6178 AND friend_user_id = 7670)
            [1] => 0.00040698051452637
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->__construct, BP_Groups_Member->populate, BP_Core_User->__construct, BP_Core_User->populate, BP_Core_User->get_profile_data, BP_XProfile_ProfileData::get_all_for_user, bp_xprofile_get_groups, BP_XProfile_Group::get, bp_xprofile_get_hidden_fields_for_user, bp_xprofile_get_hidden_field_types_for_user, friends_check_friendship, BP_Friends_Friendship::check_is_friend
        )

    [21] => Array
        (
            [0] => SELECT id FROM wp_bp_xprofile_fields WHERE group_id IN ( 1 ) AND parent_id = 0   ORDER BY field_order
            [1] => 0.00043106079101562
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->__construct, BP_Groups_Member->populate, BP_Core_User->__construct, BP_Core_User->populate, BP_Core_User->get_profile_data, BP_XProfile_ProfileData::get_all_for_user, bp_xprofile_get_groups, BP_XProfile_Group::get
        )

    [22] => Array
        (
            [0] => SELECT object_id, object_type, meta_key, meta_value FROM wp_bp_xprofile_meta WHERE ( object_type = '0' AND object_id IN (0) ) OR ( object_type = '1' AND object_id IN (0) ) OR ( object_type = '2' AND object_id IN (0) ) OR ( object_type = 'group' AND object_id IN (1) ) OR ( object_type = 'data' AND object_id IN (51126,0,51127) )
            [1] => 0.00044393539428711
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->__construct, BP_Groups_Member->populate, BP_Core_User->__construct, BP_Core_User->populate, BP_Core_User->get_profile_data, BP_XProfile_ProfileData::get_all_for_user, bp_xprofile_get_groups, BP_XProfile_Group::get, bp_xprofile_update_meta_cache
        )

    [23] => Array
        (
            [0] => UPDATE wp_bp_groups_members SET inviter_id = 0, is_admin = 1, is_mod = 0, is_banned = 0, user_title = 'Group Admin', date_modified = '2016-11-15 20:43:13', is_confirmed = 1, comments = '', invite_sent = 0 WHERE id = 33812
            [1] => 0.00058197975158691
            [2] => require('wp-blog-header.php'), require_once('wp-includes/template-loader.php'), do_action('template_redirect'), call_user_func_array, bp_template_redirect, do_action('bp_template_redirect'), call_user_func_array, bp_screens, do_action('bp_screens'), call_user_func_array, groups_screen_group_admin_manage_members, groups_promote_member, BP_Groups_Member->promote, BP_Groups_Member->save

The following patch makes it so we can remove these four unnecessary DB queries by adding some options to disable populating the user object in the BP_Groups_Member::populate() method.

Let me know if you have any questions about the technique.

Attachments (3)

7382.01.patch (3.3 KB) - added by r-a-y 8 months ago.
7382.02.patch (3.7 KB) - added by r-a-y 8 months ago.
7382.diff (1.4 KB) - added by boonebgorges 8 months ago.

Download all attachments as: .zip

Change History (11)

@r-a-y
8 months ago

@r-a-y
8 months ago

#1 @r-a-y
8 months ago

02.patch does the same thing, but with the groups_send_invites() function as well.

#2 @boonebgorges
8 months ago

Rather than adding a new parameter/option, how about making user magic? We've done this elsewhere in BP. It keeps the method signatures simpler, and gives us more general performance improvements. See 7382.diff.

@boonebgorges
8 months ago

#3 follow-up: @DJPaul
8 months ago

How does 7382.diff prevent the extra queries being made? I can't see it.

#4 in reply to: ↑ 3 @boonebgorges
8 months ago

Replying to DJPaul:

How does 7382.diff prevent the extra queries being made? I can't see it.

  1. The user property is not populated by default
  2. If some piece of code requests something from $member_object->user, __get() is invoked because user is protected
  3. __get() fetches the user object just in time

In my tests, this cuts out 25(!) queries from group member promotion.

#5 @dcavins
7 months ago

I like the concept of lazy loading the user object--it's not needed as often as it seems. It seems like the simpler answer, and should yield benefits on many group screens. Thanks for highlighting this inefficiency, @r-a-y.

This ticket was mentioned in Slack in #buddypress by slaffik. View the logs.


7 months ago

#7 @mercime
7 months ago

  • Keywords needs-unit-tests added
  • Owner set to boonebgorges
  • Status changed from new to assigned

Per https://wordpress.slack.com/archives/buddypress/p1482955785002263 adding needs-unit-tests keyword and assigning to @boonebgorges :)

#8 @boonebgorges
7 months ago

  • Resolution set to fixed
  • Status changed from assigned to closed

In 11378:

Lazy-load user property in BP_Groups_Member.

The user property is a BP_Core_User object, but is rarely
used by BP core. Only loading it when needed can save database
queries in certain cases, such as when a user is being promoted
or demoted within a group.

Props r-a-y.
Fixes #7382.

Note: See TracTickets for help on using tickets.