Make future posts visible to the public—not just within WP_Query

I know I can publicly show future posts in a loop using 'post_status' => 'future' in WP_Query. But clicking on a future post’s permalink will result in a 404 if you are not a logged-in user.

Suppose I have a post called Apocalypse in the post_type ‘event’, scheduled for 12-12-2099. The permalink is mysite.com/event/apocalypse. Is it possible to make mysite.com/event/apocalypse and other future ‘event’ posts visitable now by the public?

Read More

Ideally I’d be able to restrict future post availability to the ‘event’ post type, but I would settle for a solution that makes all future posts available regardless of post_type.

Related posts

Leave a Reply

4 comments

  1. In short, you can make future posts visible by telling WordPress to mark them as 'published' instead of 'scheduled'. You do this by using a future_post hook, which gets called when a post changes status. Each post type automatically gets its own future hook; since the custom post type I’m using is event, I can use the future_event hook. Here is the code:

    function setup_future_hook() {
    // Replace native future_post function with replacement
        remove_action('future_event','_future_post_hook');
        add_action('future_event','publish_future_post_now');
    }
    
    function publish_future_post_now($id) {
    // Set new post's post_status to "publish" rather than "future."
        wp_publish_post($id);
    }
    
    add_action('init', 'setup_future_hook');
    

    This solution came from this SE question: Marking future dated post as published

    A caveat with this approach

    The caveat I will add is that this makes it more difficult to get a
    loop of just future posts. Before, I could simply use 'post_status'
    => 'future'
    ; but now, since we’ve set future posts’ post_status to
    published, that doesn’t work.

    To get around this you can use a posts_where filter on your loop
    (for example, see the date range examples on the codex here:
    http://codex.wordpress.org/Class_Reference/WP_Query#Time_Parameters),
    or you can compare the current date to the post date, something like
    this:

        // get the event time
        $event_time = get_the_time('U', $post->ID);
    
        // get the current time
        $server_time = date('U');
    
        // if the event time is older than (less than)
        // the current time, do something
        if ( $server_time > $event_time ){
           // do something
        }
    

    However, neither of these techniques is as easy as having a separate
    post_status for future posts. Perhaps a custom post_status would
    be a good solution here.

  2. I would like to give my answer all this time later. In the case of making all the ‘future’ posts for the ‘events’ post type visible to the public, I found this solution:

    add_filter('get_post_status', function($post_status, $post) {
        if ($post->post_type == 'events' && $post_status == 'future') {
            return "publish";
        }
        return $post_status;
    }, 10, 2);
    
  3. For me the given snippet didn’t worked, there were some errors in the post-edit.php, but I guess that $postatt is now null in 4.6.1.

    Anyways that’s the final solution that worked for me like a charm.

    add_filter('the_posts', 'show_all_future_posts');
    
    function show_all_future_posts($posts)
    {
       global $wp_query, $wpdb;
    
       if(is_single() && $wp_query->post_count == 0)
       {
          $posts = $wpdb->get_results($wp_query->request);
       }
    
       return $posts;
    }
    
  4. I forced the publish status from functions.php of a child theme

    global $wpdb;
    $wpdb->query("update ".$wpdb->prefix."posts set post_status='publish' where post_status='future' and post_type in ('post','customposttype1','customposttype2')");