Make WordPress Core


Ignore:
Timestamp:
02/03/2014 07:41:40 PM (11 years ago)
Author:
wonderboymusic
Message:

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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/post.php

    r26911 r27081  
    20782078
    20792079/**
     2080 * Return the cache key for wp_count_posts() based on the passed arguments
     2081 *
     2082 * @since 3.9.0
     2083 *
     2084 * @param string $type Optional. Post type to retrieve count
     2085 * @param string $perm Optional. 'readable' or empty.
     2086 * @return string The cache key.
     2087 */
     2088function _count_posts_cache_key( $type = 'post', $perm = '' ) {
     2089    $cache_key = 'posts-' . $type;
     2090    if ( 'readable' == $perm && is_user_logged_in() ) {
     2091        $post_type_object = get_post_type_object( $type );
     2092        if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
     2093            $cache_key .= '_' . $perm . '_' . get_current_user_id();
     2094        }
     2095    }
     2096    return $cache_key;
     2097}
     2098
     2099/**
    20802100 * Count number of posts of a post type and if user has permissions to view.
    20812101 *
     
    21022122        return new stdClass;
    21032123
    2104     $user = wp_get_current_user();
    2105 
    2106     $cache_key = 'posts-' . $type;
     2124    $cache_key = _count_posts_cache_key( $type, $perm );
    21072125
    21082126    $query = "SELECT post_status, COUNT( * ) AS num_posts FROM {$wpdb->posts} WHERE post_type = %s";
    21092127    if ( 'readable' == $perm && is_user_logged_in() ) {
    21102128        $post_type_object = get_post_type_object($type);
    2111         if ( !current_user_can( $post_type_object->cap->read_private_posts ) ) {
    2112             $cache_key .= '_' . $perm . '_' . $user->ID;
    2113             $query .= " AND (post_status != 'private' OR ( post_author = '$user->ID' AND post_status = 'private' ))";
     2129        if ( ! current_user_can( $post_type_object->cap->read_private_posts ) ) {
     2130            $query .= $wpdb->prepare( " AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))",
     2131                get_current_user_id()
     2132            );
    21142133        }
    21152134    }
     
    48864905    }
    48874906
     4907    if ( $new_status !== $old_status ) {
     4908        wp_cache_delete( _count_posts_cache_key( $post->post_type ), 'counts' );
     4909        wp_cache_delete( _count_posts_cache_key( $post->post_type, 'readable' ), 'counts' );
     4910    }
     4911
    48884912    // Always clears the hook in case the post status bounced from future to draft.
    48894913    wp_clear_scheduled_hook('publish_future_post', array( $post->ID ) );
Note: See TracChangeset for help on using the changeset viewer.