Properly invalidate the cache for `wp_count_posts()` on insert, trash, or when transitioning `post_status` inside of `_transition_post_status()`. Introduces `_count_posts_cache_key()`. Adds unit tests.
Props mark8barnes, for bringing this to our attention in an initial patch. Fixes #21879. Built from https://develop.svn.wordpress.org/trunk@27081 git-svn-id: http://core.svn.wordpress.org/trunk@26954 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
parent
2f6d9d37cc
commit
4830eeb9ad
|
@ -2076,6 +2076,26 @@ function unstick_post($post_id) {
|
|||
update_option('sticky_posts', $stickies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache key for wp_count_posts() based on the passed arguments
|
||||
*
|
||||
* @since 3.9.0
|
||||
*
|
||||
* @param string $type Optional. Post type to retrieve count
|
||||
* @param string $perm Optional. 'readable' or empty.
|
||||
* @return string The cache key.
|
||||
*/
|
||||
function _count_posts_cache_key( $type = 'post', $perm = '' ) {
|
||||
$cache_key = 'posts-' . $type;
|
||||
if ( 'readable' == $perm && is_user_logged_in() ) {
|
||||
$post_type_object = get_post_type_object( $type );
|
||||
if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
|
||||
$cache_key .= '_' . $perm . '_' . get_current_user_id();
|
||||
}
|
||||
}
|
||||
return $cache_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of posts of a post type and if user has permissions to view.
|
||||
*
|
||||
|
@ -2101,16 +2121,15 @@ function wp_count_posts( $type = 'post', $perm = '' ) {
|
|||
if ( ! post_type_exists( $type ) )
|
||||
return new stdClass;
|
||||
|
||||
$user = wp_get_current_user();
|
||||
|
||||
$cache_key = 'posts-' . $type;
|
||||
$cache_key = _count_posts_cache_key( $type, $perm );
|
||||
|
||||
$query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
|
||||
if ( 'readable' == $perm && is_user_logged_in() ) {
|
||||
$post_type_object = get_post_type_object($type);
|
||||
if ( !current_user_can( $post_type_object->cap->read_private_posts ) ) {
|
||||
$cache_key .= '_' . $perm . '_' . $user->ID;
|
||||
$query .= " AND (post_status != 'private' OR ( post_author = '$user->ID' AND post_status = 'private' ))";
|
||||
if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
|
||||
$query .= $wpdb->prepare( " AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
|
||||
get_current_user_id()
|
||||
);
|
||||
}
|
||||
}
|
||||
$query .= ' GROUP BY post_status';
|
||||
|
@ -4885,6 +4904,11 @@ function _transition_post_status($new_status, $old_status, $post) {
|
|||
}
|
||||
}
|
||||
|
||||
if ( $new_status !== $old_status ) {
|
||||
wp_cache_delete( _count_posts_cache_key( $post->post_type ), 'counts' );
|
||||
wp_cache_delete( _count_posts_cache_key( $post->post_type, 'readable' ), 'counts' );
|
||||
}
|
||||
|
||||
// Always clears the hook in case the post status bounced from future to draft.
|
||||
wp_clear_scheduled_hook('publish_future_post', array( $post->ID ) );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue