Search code examples
wordpresswordpress-gutenbergwordpress-hook

Code for making scheduled posts available breaks preview in Wordpress


Problem

There is a pice of code that makes scheduled posts available for outside users via URL. The code itself works just fine - however it seems to mess with the preview feature for the editor. What causes this problem and how can it be fixed?

The code

The code below is what I use for making schedulesd Posts available:

//this is inside the functions.php
function show_future_posts($posts)
{
    global $wp_query, $wpdb;

    if (is_single() && $wp_query->post_count == 0) {
        $posts = $wpdb->get_results($wp_query->request);
        for ($i = 0; $i < sizeof($posts); $i++) {
            if ($posts[$i]->post_status == 'trash') {
                unset($posts[$i]);
                $posts = array_values($posts);
            }
        }
    }
    return $posts;
}

add_filter('the_posts', 'show_future_posts');

Steps to reproduce

  1. create new post
  2. schedule post
  3. edit somthing
  4. hit preview

Some observations:

  • as long as the post is marked as draft, the preview works fine.
  • after updating/saving (ctrl + s) the preview is correct
  • I dont think this is related to already known issues like this. When removing the code in question the autosave-feature works just fine
  • published posts show the same behaviour as scheduled ones
  • the editor (gutenberg/default) doesn`t seem to matter in this case

any help is much appreciated. Thanks!


Solution

  • I found a solution:
    The problem was that $posts was overwritten inside the condition with a new posts array. The new posts array didd´t contain the recent changes for previewing. So I did a check, wather the post is in prview mode and then overwrite the post content in the new posts array.
    The code below is what I came up with. It is not optimized yet but works. Feel free to share your optimizations in the comments. I`ll make sure to include them in this solution.

    function show_future_posts($posts)
    {
        global $wp_query, $wpdb;
    
        if (is_single() && $wp_query->post_count == 0) {
    
            $initial_posts = $posts; //save initial posts, in case we need to overwrite the new $posts content
            $posts = $wpdb->get_results($wp_query->request);
            /*
             * $initial_posts_exists_and_has_content is true when previewing scheduled posts.
             * We then can overwrite the post-content with the initial content
             * When viewing already published posts it is also true, but doesn`t contain the latest changes.
             * The content will still be overwritten, but this wont have any effect, since $initial_posts and $posts are
             * equal in this case.
             */
            $initial_posts_exists_and_has_content = !empty($initial_posts) && !is_null($initial_posts[0]->post_content);
            if($initial_posts_exists_and_has_content){
                $posts[0]->post_content = $initial_posts[0]->post_content;
            }
    
            for ($i = 0; $i < sizeof($posts); $i++) {
                if ($posts[$i]->post_status == 'trash') {
                    unset($posts[$i]);
                    $posts = array_values($posts);
                }
            }
        }
        return $posts;
    }