Users: Introduce the concept of a large site in order to speed up the Users screen when there are many users.
Calling the `count_users()` function is expensive, regardless of the counting strategy that's used, and it gets slower the more users there are on a site. In order to speed up the Users screen in the admin area, calling `count_users()` can be avoided entirely while still displaying the total count for users. This introduces some new functions: * `wp_is_large_user_count()` * `wp_get_active_user_count()` * `wp_update_active_user_count()` A corresponding `wp_is_large_user_count` filter is also introduced. Props tharsheblows, johnbillion Fixes #38741 git-svn-id: https://develop.svn.wordpress.org/trunk@41613 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
0c1d3f62f3
commit
1507df9d59
|
@ -166,27 +166,48 @@ class WP_Users_List_Table extends WP_List_Table {
|
|||
global $role;
|
||||
|
||||
$wp_roles = wp_roles();
|
||||
$count_users = true;
|
||||
|
||||
if ( wp_is_large_user_count() ) {
|
||||
$count_users = false;
|
||||
} elseif ( is_multisite() && wp_is_large_network( 'users' ) ) {
|
||||
$count_users = false;
|
||||
}
|
||||
|
||||
if ( $this->is_site_users ) {
|
||||
$url = 'site-users.php?id=' . $this->site_id;
|
||||
if ( $count_users ) {
|
||||
switch_to_blog( $this->site_id );
|
||||
$users_of_blog = count_users( 'time', $this->site_id );
|
||||
restore_current_blog();
|
||||
}
|
||||
} else {
|
||||
$url = 'users.php';
|
||||
if ( $count_users ) {
|
||||
$users_of_blog = count_users();
|
||||
}
|
||||
}
|
||||
|
||||
if ( $count_users ) {
|
||||
$total_users = $users_of_blog['total_users'];
|
||||
$avail_roles =& $users_of_blog['avail_roles'];
|
||||
unset($users_of_blog);
|
||||
} else {
|
||||
$avail_roles = array();
|
||||
}
|
||||
|
||||
$class = empty($role) ? ' class="current"' : '';
|
||||
$role_links = array();
|
||||
|
||||
if ( $count_users ) {
|
||||
$role_links['all'] = "<a href='$url'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>';
|
||||
} else {
|
||||
$role_links['all'] = "<a href='$url'$class>" . _x( 'All', 'users' ) . '</a>';
|
||||
}
|
||||
foreach ( $wp_roles->get_names() as $this_role => $name ) {
|
||||
if ( !isset($avail_roles[$this_role]) )
|
||||
if ( $count_users && !isset($avail_roles[$this_role]) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$class = '';
|
||||
|
||||
|
@ -195,12 +216,14 @@ class WP_Users_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
$name = translate_user_role( $name );
|
||||
if ( $count_users ) {
|
||||
/* translators: User role name with count */
|
||||
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles[$this_role] ) );
|
||||
}
|
||||
$role_links[$this_role] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$class>$name</a>";
|
||||
}
|
||||
|
||||
if ( ! empty( $avail_roles['none' ] ) ) {
|
||||
if ( ! $count_users || ! empty( $avail_roles['none' ] ) ) {
|
||||
|
||||
$class = '';
|
||||
|
||||
|
@ -209,8 +232,10 @@ class WP_Users_List_Table extends WP_List_Table {
|
|||
}
|
||||
|
||||
$name = __( 'No role' );
|
||||
if ( $count_users ) {
|
||||
/* translators: User role name with count */
|
||||
$name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles['none' ] ) );
|
||||
}
|
||||
$role_links['none'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$class>$name</a>";
|
||||
|
||||
}
|
||||
|
|
|
@ -466,6 +466,11 @@ add_filter( 'nav_menu_item_id', '_nav_menu_item_id_use_once', 10, 2 );
|
|||
// Widgets
|
||||
add_action( 'init', 'wp_widgets_init', 1 );
|
||||
|
||||
// User counts
|
||||
foreach ( array( 'user_register', 'deleted_user' ) as $action ){
|
||||
add_action( $action, 'wp_update_active_user_count' );
|
||||
}
|
||||
|
||||
// Admin Bar
|
||||
// Don't remove. Wrong way to disable.
|
||||
add_action( 'template_redirect', '_wp_admin_bar_init', 0 );
|
||||
|
|
|
@ -5833,3 +5833,65 @@ All at ###SITENAME###
|
|||
$site_name
|
||||
), $email_change_email['message'], $email_change_email['headers'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not we have a large site, based on its number of users.
|
||||
*
|
||||
* The default criteria for a large site is more than 10,000 users.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @return bool True if the site meets the criteria for large. False otherwise.
|
||||
*/
|
||||
function wp_is_large_user_count() {
|
||||
$count = wp_get_active_user_count();
|
||||
|
||||
/**
|
||||
* Filters whether the site is considered large, based on its number of users.
|
||||
*
|
||||
* The default criteria for a large site is more than 10,000 users.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @param bool $is_large_user_count Whether the site is considered large.
|
||||
* @param int $count The number of users on the site.
|
||||
*/
|
||||
return apply_filters( 'wp_is_large_user_count', $count > 10000, $count );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the active user count.
|
||||
*
|
||||
* @since 4.9.0
|
||||
* @global wpdb $wpdb WordPress database abstraction object.
|
||||
*
|
||||
* @return int The active user count.
|
||||
*/
|
||||
function wp_update_active_user_count() {
|
||||
global $wpdb;
|
||||
|
||||
$count = $wpdb->get_var( "
|
||||
SELECT COUNT(ID) as c
|
||||
FROM {$wpdb->users}
|
||||
" );
|
||||
$count=12345;
|
||||
update_option( 'active_user_count', $count );
|
||||
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of active users.
|
||||
*
|
||||
* @since 4.9.0
|
||||
*
|
||||
* @return int The active user count.
|
||||
*/
|
||||
function wp_get_active_user_count() {
|
||||
$count = get_option( 'active_user_count', false );
|
||||
|
||||
if ( false === $count ) {
|
||||
$count = wp_update_active_user_count();
|
||||
}
|
||||
return (int) $count;
|
||||
}
|
||||
|
|
|
@ -2553,6 +2553,11 @@ function wp_is_large_network( $using = 'sites', $network_id = null ) {
|
|||
|
||||
if ( 'users' == $using ) {
|
||||
$count = get_user_count( $network_id );
|
||||
$is_large = ( $count > 10000 );
|
||||
|
||||
/** This filter is documented in wp-includes/functions.php */
|
||||
$is_large = apply_filters( 'wp_is_large_user_count', $is_large, $count );
|
||||
|
||||
/**
|
||||
* Filters whether the network is considered large.
|
||||
*
|
||||
|
@ -2564,7 +2569,7 @@ function wp_is_large_network( $using = 'sites', $network_id = null ) {
|
|||
* @param int $count The count of items for the component.
|
||||
* @param int $network_id The ID of the network being checked.
|
||||
*/
|
||||
return apply_filters( 'wp_is_large_network', $count > 10000, 'users', $count, $network_id );
|
||||
return apply_filters( 'wp_is_large_network', $is_large, 'users', $count, $network_id );
|
||||
}
|
||||
|
||||
$count = get_blog_count( $network_id );
|
||||
|
|
|
@ -78,8 +78,7 @@ function wp_version_check( $extra_stats = array(), $force_check = false ) {
|
|||
$wp_install = network_site_url();
|
||||
$multisite_enabled = 1;
|
||||
} else {
|
||||
$user_count = count_users();
|
||||
$user_count = $user_count['total_users'];
|
||||
$user_count = wp_get_active_user_count();
|
||||
$multisite_enabled = 0;
|
||||
$num_blogs = 1;
|
||||
$wp_install = home_url( '/' );
|
||||
|
|
|
@ -1160,4 +1160,58 @@ class Tests_Functions extends WP_UnitTestCase {
|
|||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 38741
|
||||
*/
|
||||
public function test_wp_get_active_user_count() {
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 1 );
|
||||
|
||||
// make twenty additional users to make 21 users
|
||||
self::factory()->user->create_many( 20 );
|
||||
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 21 );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 38741
|
||||
*/
|
||||
public function test_wp_get_active_user_count_caching() {
|
||||
global $wpdb;
|
||||
|
||||
// Ensure we start with 1 user
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 1 );
|
||||
|
||||
self::factory()->user->create();
|
||||
|
||||
delete_option( 'active_user_count' );
|
||||
|
||||
// Ensure we now have 2 users
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 2 );
|
||||
|
||||
$queries = $wpdb->num_queries;
|
||||
|
||||
// Ensure that caching inside wp_get_active_user_count() works as expected
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 2 );
|
||||
$this->assertSame( $queries, $wpdb->num_queries );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 38741
|
||||
*/
|
||||
public function test_wp_is_large_user_count() {
|
||||
// set the 'active_user_count' value to over 10000 to emulate a large site
|
||||
update_option( 'active_user_count', 10001 );
|
||||
$user_count = wp_get_active_user_count();
|
||||
$this->assertSame( $user_count, 10001 );
|
||||
$this->assertTrue( wp_is_large_user_count() );
|
||||
|
||||
delete_option( 'active_user_count' );
|
||||
$this->assertFalse( wp_is_large_user_count() );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue