wp_count_posts

The timeline below displays how wordpress function wp_count_posts has changed across different WordPress versions. If a version is not listed, refer to the next available version below.

WordPress Version: 6.3

/**
 * Counts number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return stdClass An object containing the number of posts for each status,
 *                  or an empty object if the post type does not exist.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        // We may have cached this before every status was registered.
        foreach (get_post_stati() as $status) {
            if (!isset($counts->{$status})) {
                $counts->{$status} = 0;
            }
        }
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Filters the post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param stdClass $counts An object containing the current post_type's post
     *                         counts by status.
     * @param string   $type   Post type.
     * @param string   $perm   The permission to determine if the posts are 'readable'
     *                         by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 6.2

/**
 * Counts number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return stdClass Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        // We may have cached this before every status was registered.
        foreach (get_post_stati() as $status) {
            if (!isset($counts->{$status})) {
                $counts->{$status} = 0;
            }
        }
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Filters the post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param stdClass $counts An object containing the current post_type's post
     *                         counts by status.
     * @param string   $type   Post type.
     * @param string   $perm   The permission to determine if the posts are 'readable'
     *                         by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 6.1

/**
 * Counts number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return stdClass Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        // We may have cached this before every status was registered.
        foreach (get_post_stati() as $status) {
            if (!isset($counts->{$status})) {
                $counts->{$status} = 0;
            }
        }
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modifies returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param stdClass $counts An object containing the current post_type's post
     *                         counts by status.
     * @param string   $type   Post type.
     * @param string   $perm   The permission to determine if the posts are 'readable'
     *                         by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 5.9

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return stdClass Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        // We may have cached this before every status was registered.
        foreach (get_post_stati() as $status) {
            if (!isset($counts->{$status})) {
                $counts->{$status} = 0;
            }
        }
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param stdClass $counts An object containing the current post_type's post
     *                         counts by status.
     * @param string   $type   Post type.
     * @param string   $perm   The permission to determine if the posts are 'readable'
     *                         by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 5.5

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return object Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        // We may have cached this before every status was registered.
        foreach (get_post_stati() as $status) {
            if (!isset($counts->{$status})) {
                $counts->{$status} = 0;
            }
        }
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 4.4

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return object Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 4.3

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return object Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 4.2

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return object Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $cache_key = _count_posts_cache_key($type, $perm);
    $counts = wp_cache_get($cache_key, 'counts');
    if (false !== $counts) {
        /** This filter is documented in wp-includes/post.php */
        return apply_filters('wp_count_posts', $counts, $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
    $counts = array_fill_keys(get_post_stati(), 0);
    foreach ($results as $row) {
        $counts[$row['post_status']] = $row['num_posts'];
    }
    $counts = (object) $counts;
    wp_cache_set($cache_key, $counts, 'counts');
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 4.0

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @since 2.5.0
 *
 * @param string $type Optional. Post type to retrieve count. Default 'post'.
 * @param string $perm Optional. 'readable' or empty. Default empty.
 * @return object Number of posts for each status.
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $counts = wp_cache_get($cache_key, 'counts');
    if (false === $counts) {
        $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
        $counts = array_fill_keys(get_post_stati(), 0);
        foreach ($results as $row) {
            $counts[$row['post_status']] = $row['num_posts'];
        }
        $counts = (object) $counts;
        wp_cache_set($cache_key, $counts, 'counts');
    }
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 3.9

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @link http://codex.wordpress.org/Template_Tags/wp_count_posts
 *
 * @since 2.5.0
 *
 * @param string $type Optional. Post type to retrieve count
 * @param string $perm Optional. 'readable' or empty.
 * @return object Number of posts for each status
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $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)) {
            $query .= $wpdb->prepare(" AND (post_status != 'private' OR ( post_author = %d AND post_status = 'private' ))", get_current_user_id());
        }
    }
    $query .= ' GROUP BY post_status';
    $counts = wp_cache_get($cache_key, 'counts');
    if (false === $counts) {
        $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
        $counts = array_fill_keys(get_post_stati(), 0);
        foreach ($results as $row) {
            $counts[$row['post_status']] = $row['num_posts'];
        }
        $counts = (object) $counts;
        wp_cache_set($cache_key, $counts, 'counts');
    }
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post
     *                       counts by status.
     * @param string $type   Post type.
     * @param string $perm   The permission to determine if the posts are 'readable'
     *                       by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}

WordPress Version: 3.7

/**
 * Count number of posts of a post type and if user has permissions to view.
 *
 * This function provides an efficient method of finding the amount of post's
 * type a blog has. Another method is to count the amount of items in
 * get_posts(), but that method has a lot of overhead with doing so. Therefore,
 * when developing for 2.5+, use this function instead.
 *
 * The $perm parameter checks for 'readable' value and if the user can read
 * private posts, it will display that for the user that is signed in.
 *
 * @link http://codex.wordpress.org/Template_Tags/wp_count_posts
 *
 * @since 2.5.0
 *
 * @param string $type Optional. Post type to retrieve count
 * @param string $perm Optional. 'readable' or empty.
 * @return object Number of posts for each status
 */
function wp_count_posts($type = 'post', $perm = '')
{
    global $wpdb;
    if (!post_type_exists($type)) {
        return new stdClass();
    }
    $user = wp_get_current_user();
    $cache_key = 'posts-' . $type;
    $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' ))";
        }
    }
    $query .= ' GROUP BY post_status';
    $counts = wp_cache_get($cache_key, 'counts');
    if (false === $counts) {
        $results = (array) $wpdb->get_results($wpdb->prepare($query, $type), ARRAY_A);
        $counts = array_fill_keys(get_post_stati(), 0);
        foreach ($results as $row) {
            $counts[$row['post_status']] = $row['num_posts'];
        }
        $counts = (object) $counts;
        wp_cache_set($cache_key, $counts, 'counts');
    }
    /**
     * Modify returned post counts by status for the current post type.
     *
     * @since 3.7.0
     *
     * @param object $counts An object containing the current post_type's post counts by status.
     * @param string $type   The post type.
     * @param string $perm   The permission to determine if the posts are 'readable' by the current user.
     */
    return apply_filters('wp_count_posts', $counts, $type, $perm);
}