New User Related Short Circuit Filters

WordPress 5.1 introduces new short circuit filters to WP_User_Query and count_users().

The users_pre_query filter was introduced in #44373 and runs before the database query takes place. This enables short-circuiting the database query entirely to return custom results. Returning a non-null value from the filter will bypass WordPress’s default user query (similar to the posts_pre_query filter for WP_Query added in #36687).

Developers should note that filtering functions that require pagination information are encouraged to set the total_users property of the WP_User_Query object (which is passed to the filter by reference). If WP_User_Query does not perform a database query, it will not have enough information to generate these values itself.

Using the users_pre_query Filter

Below is a rough example of how a plugin can use the filter to replace the default behavior of WP_User_Query with a call to a remote data store.

function myplugin_do_external_users_query( $users, $user_query ) {
	$response = wp_remote_get( 'https://my-remote-data-store/foo/bar' );

	if ( 200 === wp_remote_response_code( $response ) ) {
		$response           = json_decode( wp_remote_retrieve_body( $response ) );
		$users              = array_map( 'intval', $response->user_ids );
		$query->found_users = (int) $response->found_users;
	}

	return $users;
}
add_filter( 'users_pre_query', 'myplugin_do_external_users_query', 10, 2 );

Similar to posts_pre_query, callbacks must be careful about fields – the external API may have to return user IDs or quasi-WP_User objects, depending on the value of fields.

A more in-depth example of how this filter can be utilized can be found in this project, which enables user query caching.

Filtering the count_users() Function

In addition, a pre_count_users filter was added in #43693 which enables short-circuiting the count_users function before the database query takes place. Returning a non-null value from the filter will bypass the default queries.

Using the pre_count_users Filter

Here is a sample code snippet showing how to use this filter:

function myplugin_do_external_users_count( $user_count) {
	$response = wp_remote_get( 'https://my-remote-data-store/foo/bar' );

	if ( 200 === wp_remote_response_code( $response ) ) {
		$response = json_decode( wp_remote_retrieve_body( $response ) );
		$user_count    = $response->user_count;
	}

	return $user_count;
}
add_filter( 'pre_count_users', 'myplugin_do_external_users_count', 10, 2 );

More Filters Coming Soon…

Several additional filters for similar query objects are currently being explored and worked on, and are currently slated for a future release:

  • A short circuit for WP_Comment_Query (#45800).
  • A short circuit for WP_Site_Query and WP_Network_Query with a plan to add a sites_pre_query filter (#45749).
  • A short circuit for WP_Term_Query with a plan to add a terms_pre_query filter (#41246).

Why Add These Filters?

These query pre-filters enable plugins to use an alternate database store for queries, for example returning results from an external service such as an Elasticsearch server. The process started with the main post query, and these are now being expanded that to other queries in WordPress.

#5-1, #dev-notes