Query: Allow plugins to supply post results instead of having WP_Query fetch them from the database.

Returning a non-null value from the new `posts_pre_query` filter will cause
`WP_Query` to skip its database query, so that posts data can be provided from
elsewhere. This is useful in cases where post data may be mirrored in a
separate location, such as an external search application.

Developers should note that the `WP_Query` properties generally used to
calculate pagination - specifically, `found_posts` and `max_num_pages`, which
are determined by default in `set_found_posts()` - must be provided explicitly
when using the `posts_pre_query` filter; since `WP_Query` will not be
contacting the database, it will have no access to `SELECT FOUND_ROWS()`.
The `WP_Query` instance is passed to `posts_pre_query` by reference, so that
these properties can be set manually if needed.

Props jpdavoutian, tlovett1.
Fixes #36687.
Built from https://develop.svn.wordpress.org/trunk@37692


git-svn-id: http://core.svn.wordpress.org/trunk@37658 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
Boone Gorges 2016-06-14 02:00:29 +00:00
parent 6d05c7521b
commit 486961626c
2 changed files with 64 additions and 38 deletions

View File

@ -3556,8 +3556,29 @@ class WP_Query {
$this->request = apply_filters_ref_array( 'posts_request', array( $this->request, &$this ) );
}
/**
* Filters the posts array before the query takes place.
*
* Return a non-null value to bypass WordPress's default post queries.
*
* Filtering functions that require pagination information are encouraged to set
* the `found_posts` and `max_num_pages` properties of the WP_Query object,
* passed to the filter by reference. If WP_Query does not perform a database
* query, it will not have enough information to generate these values itself.
*
* @since 4.6.0
*
* @param array|null $posts Return an array of post data to short-circuit WP's query,
* or null to allow WP to run its normal queries.
* @param WP_Query $this The WP_Query instance, passed by reference.
*/
$this->posts = apply_filters_ref_array( 'posts_pre_query', array( null, &$this ) );
if ( 'ids' == $q['fields'] ) {
if ( null === $this->posts ) {
$this->posts = $wpdb->get_col( $this->request );
}
$this->posts = array_map( 'intval', $this->posts );
$this->post_count = count( $this->posts );
$this->set_found_posts( $q, $limits );
@ -3566,7 +3587,10 @@ class WP_Query {
}
if ( 'id=>parent' == $q['fields'] ) {
if ( null === $this->posts ) {
$this->posts = $wpdb->get_results( $this->request );
}
$this->post_count = count( $this->posts );
$this->set_found_posts( $q, $limits );
@ -3581,6 +3605,7 @@ class WP_Query {
return $r;
}
if ( null === $this->posts ) {
$split_the_query = ( $old_request == $this->request && "$wpdb->posts.*" == $fields && !empty( $limits ) && $q['posts_per_page'] < 500 );
/**
@ -3616,19 +3641,20 @@ class WP_Query {
if ( $ids ) {
$this->posts = $ids;
$this->set_found_posts( $q, $limits );
_prime_post_caches( $ids, $q['update_post_term_cache'], $q['update_post_meta_cache'] );
} else {
$this->posts = array();
}
} else {
$this->posts = $wpdb->get_results( $this->request );
$this->set_found_posts( $q, $limits );
}
}
// Convert to WP_Post objects
if ( $this->posts )
// Convert to WP_Post objects and set the found-post totals.
if ( $this->posts ) {
$this->posts = array_map( 'get_post', $this->posts );
$this->set_found_posts( $q, $limits );
}
if ( ! $q['suppress_filters'] ) {
/**

View File

@ -4,7 +4,7 @@
*
* @global string $wp_version
*/
$wp_version = '4.6-alpha-37691';
$wp_version = '4.6-alpha-37692';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.