[wp-trac] [WordPress Trac] #32472: is_user_member_of_blog() can be very slow when a user is a member of hundreds of sites

WordPress Trac noreply at wordpress.org
Sat May 23 15:44:22 UTC 2015


#32472: is_user_member_of_blog() can be very slow when a user is a member of
hundreds of sites
------------------------------------+-----------------------------
 Reporter:  sammybeats              |      Owner:
     Type:  defect (bug)            |     Status:  new
 Priority:  normal                  |  Milestone:  Awaiting Review
Component:  Users                   |    Version:  3.0
 Severity:  normal                  |   Keywords:
  Focuses:  multisite, performance  |
------------------------------------+-----------------------------
 This problem would partly be fixed if the solution in #31746 were adopted,
 however it is still a separate issue.

 `is_user_member_of_blog()` uses `get_blogs_of_user()` which is very slow
 when the user is a member of hundreds of sites. And because
 `is_user_member_of_blog()` is called on every admin page load by
 `wp_user_settings()` in `admin-header.php`, this adds a TON of database
 queries to every admin page load.

 `get_blog_details()`, which is called on every blog of which the user is a
 member in `get_blogs_of_user()`, only needs to be done on the blog in
 question when `is_user_member_of_blog()` is called. I propose a solution
 like this, though it may duplicate too much code from
 `get_blogs_of_user()`:


 {{{
 function is_user_member_of_blog( $user_id = 0, $blog_id = 0 ) {
     global $wpdb;

     $user_id = (int) $user_id;
     $blog_id = (int) $blog_id;

     if ( empty( $user_id ) )
         $user_id = get_current_user_id();

     if ( empty( $blog_id ) )
         $blog_id = get_current_blog_id();

     if ( empty( $user_id ) )
         return false;

     if( ! is_multisite() )
         return true;

     $keys = get_user_meta( $user_id );
     if ( empty( $keys ) )
         return false;

     $blog = get_blog_details( $blog_id );

     if( ! $blog || ! isset( $blog->domain ) || $blog->archived ||
 $blog->spam || $blog->deleted )
         return false;

     if ( isset( $keys[ $wpdb->base_prefix . 'capabilities' ] ) && defined(
 'MULTISITE' ) && $blog_id == 1 )
         return true;

     $is_member = false;

     $keys = array_keys( $keys );

     foreach ( $keys as $key ) {
         if ( 'capabilities' !== substr( $key, -12 ) )
             continue;
         if ( $wpdb->base_prefix && 0 !== strpos( $key, $wpdb->base_prefix
 ) )
             continue;
         $key_blog_id = str_replace( array( $wpdb->base_prefix,
 '_capabilities' ), '', $key );
         if ( ! is_numeric( $key_blog_id ) )
             continue;
         if ( $key_blog_id == $blog_id ) {
             $is_member = true;
             break;
         }
     }

     return $is_member;

 }
 }}}

 I just tested it and it reduced my admin page load time by 5 seconds.

--
Ticket URL: <https://core.trac.wordpress.org/ticket/32472>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list