Displaying WordPress Future Posts

WordPress doesn’t include future (scheduled) posts on Blog, Archive, Widget or Single post pages. That is the logical default. But if you ever need to display a list of future posts, and even show a future post on its single post page, here is a solution.

Shortcode to display the list of future posts

function future_postlist_shortcode( $atts ) {
    extract( shortcode_atts( array(
        'post_type' => 'post',
        'total'     => '-1',
        'order'     => 'DESC',
        'orderby'     => 'date',
    ), $atts ));


    $html  = '';
    $query = new WP_Query( array(
        'order'         => $order,
        'orderby'         => $orderby,
        'post_type'         => $post_type,
        'post_status'         => 'future',
        'posts_per_page'    => $total
    ));

    if( $query->have_posts() ):
    $html .= '<ul>';
        while( $query->have_posts()) : $query->the_post();
        $html .= sprintf(
            '<li><a href="%1$s">%2$s</a> -
            <span title="will be available within %3$s">in %3$s</span></li>',
            get_permalink(),
            get_the_title(),
            human_time_diff( strtotime(get_post()->post_date), current_time('timestamp') )
        );
        endwhile;
    $html .= '</ul>';
    wp_reset_postdata();
    endif;

    return $html;
}
add_shortcode( 'future_postlist', 'future_postlist_shortcode' );

The shortcode supports a few arguments – number of posts to show, order & orderby. You can use it like –

[future_postlist total='10' orderby='date' order='ASC']

This displays the list of future posts with a human readable publishing time, ex: in 9 hours, and the post title linked to the post page. But there is one problem – non logged-in users can not see future posts on the single post page, and for that we need some more code.

Display future posts for non logged-in users

On the single post page, non logged-in users do not see future posts. Here we filter the condition and allow non logged-in users to see a future post on its single post page.

add_filter( 'the_posts', 'myplugin_the_future_posts', 10, 2 );
function myplugin_the_future_posts( $posts, $query ) {
    global $wpdb;

    // We will skip if -
    // - there's already found posts
    // - or it isn't a single post page
    // - or User is loggedin
    if ( !empty($posts) || ! $query->is_singular() || is_user_logged_in() ) {
        return $posts;
    }

    if( $post_name = $query->get('name') ) {
        $post_type = $query->get('post_type') ? $query->get('post_type') : 'post';
        $post_status = 'future';
        $post_ID = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s AND post_status= %s", $post_name, $post_type, $post_status ) );
        if( $post_ID ){
            $posts = array( get_post($post_ID) );
        }
    }

    return $posts;
}

All of the code used here should be added to your plugin or your theme’s functions.php file.