10

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.

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?
2
  • 4
    Would it be possible to use custom fields for the date rather than using the default wordpress functions as like you say essentially the posts with future dates aren't actually published in the view of WP.
    – Vince P
    Commented Mar 2, 2012 at 11:42
  • Although saying that it would seem like it is a user access level thing so you could possibly add something to the functions.php file to grant all users the ability to view future posts
    – Vince P
    Commented Mar 2, 2012 at 11:43

3 Answers 3

5

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;
}
3
  • 2
    Add a text domain to your __() calls or don’t use function.
    – fuxia
    Commented Mar 2, 2012 at 12:45
  • 3
    -1 for approach. :) As per discussion in chat it would be more reliable to track event date separately in custom field over bending internal mechanics to makes use of post's date.
    – Rarst
    Commented Mar 2, 2012 at 12:47
  • 1
    +1 for alternative approach :) I totally agree with @Rarst but I'm also finding this approach interesting and I'll be happy to have it well documented here on WPSE.
    – Michal Mau
    Commented Mar 2, 2012 at 12:59
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!

0

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' ) );

    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.