diff --git src/wp-admin/includes/class-wp-users-list-table.php src/wp-admin/includes/class-wp-users-list-table.php
index 61ea897c5a..90711e2f1b 100644
--- src/wp-admin/includes/class-wp-users-list-table.php
+++ 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_site() ) {
+ $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 src/wp-includes/default-filters.php src/wp-includes/default-filters.php
index a196f4ff19..4db2b37339 100644
--- src/wp-includes/default-filters.php
+++ src/wp-includes/default-filters.php
@@ -464,6 +464,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_maybe_update_active_user_count' );
+}
+
// Admin Bar
// Don't remove. Wrong way to disable.
add_action( 'template_redirect', '_wp_admin_bar_init', 0 );
diff --git src/wp-includes/functions.php src/wp-includes/functions.php
index 03c6126d5b..7629fea0e1 100644
--- src/wp-includes/functions.php
+++ src/wp-includes/functions.php
@@ -5734,3 +5734,87 @@ All at ###SITENAME###
$site_name
), $email_change_email['message'], $email_change_email['headers'] );
}
+
+/**
+ * Whether or not we have a large site.
+ *
+ * The default criteria for a large site is more than 10,000 users.
+ *
+ * @since x.x.x
+ *
+ * @return bool True if the site meets the criteria for large. False otherwise.
+ */
+function wp_is_large_site() {
+ $count = wp_get_active_user_count();
+ /**
+ * Filters whether the site is considered large.
+ *
+ * @since x.x.x
+ *
+ * @param bool $is_large_user_count Whether the site has more than 10000 users.
+ * @param int $count The count of items for the component.
+ */
+ return apply_filters( 'wp_is_large_user_count', $count > 10000, $count );
+}
+
+/**
+ * Update the active user count.
+ *
+ * @since x.x.x
+ *
+ * @global wpdb $wpdb WordPress database abstraction object.
+ */
+function wp_update_active_user_count() {
+ global $wpdb;
+
+ $count = $wpdb->get_var( "SELECT COUNT(ID) as c FROM $wpdb->users" );
+ update_option( 'active_user_count', $count );
+
+ return $count;
+}
+
+/**
+ * The number of active users.
+ *
+ * The count is cached for a minimum of twelve hours. This is not a live count.
+ *
+ * @since x.x.x
+ *
+ * @return int
+ */
+function wp_get_active_user_count() {
+
+ $count = get_option( 'active_user_count' );
+
+ if ( empty ( $count ) ){
+ $count = wp_update_active_user_count();
+ }
+ return (int) $count;
+}
+
+/**
+ * Update the user count.
+ *
+ * If enabled through the {@see 'enable_live_network_counts'} filter, update the sites count
+ * on a network when a site is created or its status is updated.
+ *
+ * @since x.x.x
+ */
+function wp_maybe_update_active_user_count() {
+ $is_small_site = ! wp_is_large_site();
+
+ /**
+ * Filters whether to update network site or user counts when a new site is created.
+ *
+ * @since x.x.x
+ *
+ * @see wp_is_large_site()
+ *
+ * @param bool $small_site Whether the site is considered small.
+ */
+ if ( ! apply_filters( 'enable_live_site_counts', $is_small_site ) ){
+ return;
+ }
+
+ wp_update_active_user_count();
+}
diff --git src/wp-includes/ms-functions.php src/wp-includes/ms-functions.php
index 7c28844e0c..472a239a1a 100644
--- src/wp-includes/ms-functions.php
+++ src/wp-includes/ms-functions.php
@@ -2550,6 +2550,9 @@ 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.
*
@@ -2561,7 +2564,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 src/wp-includes/update.php src/wp-includes/update.php
index f25e644d62..a14e050bd3 100644
--- src/wp-includes/update.php
+++ 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 tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php
index 252d890bbb..6816d1923e 100644
--- tests/phpunit/tests/functions.php
+++ tests/phpunit/tests/functions.php
@@ -1110,4 +1110,35 @@ class Tests_Functions extends WP_UnitTestCase {
return $data;
}
+
+ /*
+ * @ticket 38741
+ */
+
+ public function test_wp_get_active_user_count(){
+
+ // make twenty additional users to make 21 users
+ for( $i = 0; $i < 20; $i++ ){
+ self::factory()->user->create();
+ }
+
+ $user_count = wp_get_active_user_count();
+
+ $this->assertEquals( $user_count, 21 );
+ }
+
+ /*
+ * @ticket 38741
+ */
+ public function test_wp_is_large_site(){
+
+ if ( wp_using_ext_object_cache() ) {
+ $this->markTestSkipped( 'Not testable with an external object cache.' );
+ }
+
+ // set the 'active_user_count' transient to over 10000 to emulate a large site
+ update_option( 'active_user_count', 10001 );
+ $this->assertTrue( wp_is_large_site() );
+ delete_option( 'active_user_count' );
+ }
}