diff --git a/src/wp-admin/includes/class-wp-users-list-table.php b/src/wp-admin/includes/class-wp-users-list-table.php
index 61ea897c5a..6825bca5f0 100644
--- a/src/wp-admin/includes/class-wp-users-list-table.php
+++ b/src/wp-admin/includes/class-wp-users-list-table.php
@@ -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;
- switch_to_blog( $this->site_id );
- $users_of_blog = count_users( 'time', $this->site_id );
- restore_current_blog();
+ 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';
- $users_of_blog = count_users();
+ if ( $count_users ) {
+ $users_of_blog = count_users();
+ }
}
- $total_users = $users_of_blog['total_users'];
- $avail_roles =& $users_of_blog['avail_roles'];
- unset($users_of_blog);
+ 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();
- $role_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '';
+
+ if ( $count_users ) {
+ $role_links['all'] = "" . sprintf( _nx( 'All (%s)', 'All (%s)', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '';
+ } else {
+ $role_links['all'] = "" . _x( 'All', 'users' ) . '';
+ }
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 );
- /* translators: User role name with count */
- $name = sprintf( __('%1$s (%2$s)'), $name, number_format_i18n( $avail_roles[$this_role] ) );
+ if ( $count_users ) {
+ /* translators: User role name with count */
+ $name = sprintf( __('%1$s (%2$s)'), $name, number_format_i18n( $avail_roles[$this_role] ) );
+ }
$role_links[$this_role] = "$name";
}
- 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' );
- /* translators: User role name with count */
- $name = sprintf( __('%1$s (%2$s)'), $name, number_format_i18n( $avail_roles['none' ] ) );
+ if ( $count_users ) {
+ /* translators: User role name with count */
+ $name = sprintf( __('%1$s (%2$s)'), $name, number_format_i18n( $avail_roles['none' ] ) );
+ }
$role_links['none'] = "$name";
}
diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php
index 0ed4be9056..a725221381 100644
--- a/src/wp-includes/default-filters.php
+++ b/src/wp-includes/default-filters.php
@@ -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 );
diff --git a/src/wp-includes/functions.php b/src/wp-includes/functions.php
index 2559613fbc..63551a227b 100644
--- a/src/wp-includes/functions.php
+++ b/src/wp-includes/functions.php
@@ -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;
+}
diff --git a/src/wp-includes/ms-functions.php b/src/wp-includes/ms-functions.php
index 7bfd9f968e..03c376836a 100644
--- a/src/wp-includes/ms-functions.php
+++ b/src/wp-includes/ms-functions.php
@@ -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 );
diff --git a/src/wp-includes/update.php b/src/wp-includes/update.php
index f178470a36..13c20b7ad8 100644
--- a/src/wp-includes/update.php
+++ b/src/wp-includes/update.php
@@ -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( '/' );
diff --git a/tests/phpunit/tests/functions.php b/tests/phpunit/tests/functions.php
index 3fa9fbcc74..4ab59c3c5a 100644
--- a/tests/phpunit/tests/functions.php
+++ b/tests/phpunit/tests/functions.php
@@ -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() );
+ }
}