How to set a custom post type to have viewable future posts

I’ve setup a CPT to act the same ways as posts but used to post event details.

Thing is that some of the posts are in the future and such have a future date set on them. Problem is that normal users cannot see these posts.

Read More

So:

  • How do I alter archive-events.php to list future posts too? Showing far future posts first and oldest posts last while maintaining pagination.
  • How do I make it so that when a user clicks a future post they don’t get a 404 page not found as the post is not technically published yet?

Related posts

Leave a Reply

3 comments

  1. I’ve been able to solve this myself. My entire code for registering the CPT:

    <?php
    add_action( 'init', 'events_post_type_register' );
    function events_post_type_register() {
    
        $post_type = "events";
    
        $labels = array(
            'name' => _x('Events', 'post type general name', 'project_X'),
            'singular_name' => _x('Event', 'post type singular name', 'project_X'),
            'add_new' => _x('Add New', 'event', 'project_X'),
            'add_new_item' => __('Add New Event', 'project_X'),
            'edit_item' => __('Edit Event', 'project_X'),
            'new_item' => __('New Event', 'project_X'),
            'all_items' => __('All Events', 'project_X'),
            'view_item' => __('View Event', 'project_X'),
            'search_items' => __('Search Events', 'project_X'),
            'not_found' =>  __('No events found', 'project_X'),
            'not_found_in_trash' => __('No events found in trash', 'project_X'),
            'parent_item_colon' => '',
            'menu_name' => 'Events'
        );
    
        $args = array(
            'labels' => $labels,
            'public' => true,
            'hierarchical' => false,
            'has_archive' => true,
            'rewrite' => array(
                'with_front' => false,
                'slug' => "news/{$post_type}"
            ),
            'supports' => array( 'title', 'editor', 'thumbnail' )
        );
        register_post_type($post_type, $args);
    
        remove_action("future_{$post_type}", '_future_post_hook');
        add_action("future_{$post_type}", 'sc_ps_publish_future_events_now', 2, 10);
    }
    
    function sc_ps_publish_future_events_now($depreciated, $post) {
        wp_publish_post($post);
    }
    
    add_filter('posts_where', 'sc_ps_show_future_events_where', 2, 10);
    function sc_ps_show_future_events_where($where, $that) {
        global $wpdb;
        if("events" == $that->query_vars['post_type'] && is_archive())
            $where = str_replace( "{$wpdb->posts}.post_status = 'publish'", "{$wpdb->posts}.post_status = 'publish' OR $wpdb->posts.post_status = 'future'", $where);
        return $where;
    }
    ?>
    

    So to allow posts to be visable to all users even if they are set in the future you need to do the following:

    remove_action("future_{$post_type}", '_future_post_hook');
    add_action("future_{$post_type}", 'sc_ps_publish_future_events_now', 2, 10);
    

    We remove the action that deals with posting later and apply our own action to force it to be published despite it having a future date with:

    wp_publish_post($post);
    

    Then all we now need to do is show future posts on the archive page by filtering posts_where:

    function sc_ps_show_future_events_where($where, $that) {
        global $wpdb;
        if("events" == $that->query_vars['post_type'] && is_archive())
            $where = str_replace( "{$wpdb->posts}.post_status = 'publish'", "{$wpdb->posts}.post_status = 'publish' OR $wpdb->posts.post_status = 'future'", $where);
        return $where;
    }
    
  2. Brady, I can’t thank you enough for leading me to this solution. My client had already set all of the event dates without a custom field, and I wasn’t about to go back and change everything. Your code initially threw an error when trying to post, but it worked with the following slight modifications (made to match the format used in wp-includes/post.php):

    remove_action( 'future_' . $post_type, '_future_post_hook', 5, 2 );
    add_action( 'future_' . $post_type, 'my_future_post_hook', 5, 2);
    

    and

    function my_future_post_hook( $deprecated = '', $post ) {
        wp_publish_post( $post->ID );
    }
    

    I spent awhile trying to figure this out. Hope it helps someone else!

  3. Without change the post status you can display future posts single and archive with pre_get_posts too:

    add_action( 'pre_get_posts', 'joesz_include_future_posts' );
    function joesz_include_future_posts( $query ) {
    
        if ( $query->is_main_query() && 
               ( $query->query_vars['post_type'] == 'your-post-type' || // for single
             is_post_type_archive( 'your-post-type' ) ) ) {         // for archive
    
            $query->set( 'post_status', array( 'future', 'publish' ) );
    
        }
    
    }