5

I have a page set up with six posts per page with two rows of three posts. If I only have one post up, I would like the other five to have "placeholder images" letting the viewers know that more posts are coming. Kind of like this:

enter image description here

I would create the placeholder images to put in there.

Here is how my blog is set up. Pretty basic. Has anybody ever done anything like this before?

<div id="article-list">

    <?php if ( have_posts() ) : ?>

        <?php while ( have_posts() ) : the_post(); ?>

        <article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
            <div class="post-info">
                <?php the_title( sprintf( '<h1 class="entry-title"><a href="%s" rel="bookmark">', esc_url( get_permalink() ) ), '</a></h1>' ); ?>
                <?php mobile_mix_posted_on(); ?>
            </div>

            <?php if ( '' != get_the_post_thumbnail() ) {
                the_post_thumbnail();
            } ?>

        </article><!-- #post-## -->

        <?php endwhile; ?>

        <?php mobile_mix_paging_nav(); ?>

    <?php else : ?>

        <?php get_template_part( 'content', 'none' ); ?>

    <?php endif; ?>

</div>
6

You can add a filter to 'loop_start', count how may posts you have and inject the needed number of "fake" posts that are intances of WP_Post not having a reference in DB.

add_filter( 'loop_start', function( $query ) {
  $module = $query->post_count % 6;
  $to_fill = $module === 0 ? 0 : 6 - $module ;
  if (
    (int) $query->post_count === 0
    || (int) $to_fill === 0
    || ! $query->is_main_query()
    || $query->is_singular()
    // probably you need to put other conditions here e.g. $query->is_front_page()
    // to affect only specific pages and not all...
  ) { 
    return;
  }
  $query->post_count += $to_fill;
  $query->found_posts += $to_fill;
  $fake = clone $query->posts[0];
  $fake->post_title = 'Coming Soon';
  $fake->post_name = 'coming-soon';
  $fake->is_fake = TRUE;
  $fake->ID = 0;
  $fake_posts = array_fill( 0, $to_fill, $fake );
  $query->posts = array_merge( $query->posts, $fake_posts );

} );

Edit: avoid template editing

Now we have to prevent fake posts to have a permalink

add_filter( 'the_permalink', function( $permalink ) {
  if ( isset($GLOBALS['post']->is_fake) ) {
    return '#';
  }
  return $permalink;
} );

And use coming soon image as post thumbnail:

add_filter( 'get_post_metadata', function( $check, $pid, $key ) {
  global $post;
  if ( $key === '_thumbnail_id' && empty($pid) && isset( $post->is_fake ) ) {
    $check = 1; // just a non falsey number to pass has_thumbnail check
  }
  return $check;
}, PHP_INT_MAX, 3 );

add_filter( 'post_thumbnail_html', function( $html, $pid ) {
  global $post;
  if ( empty($pid) && isset( $post->is_fake ) ) {
    $html = '<img src="http://example.com/path/to/coming-soon.png" alt="coming Soon" />';
  }
  return $html;
}, PHP_INT_MAX, 2 );
  • Thanks, that fixed the issue with the 7th post getting added, but it looks like the second page still only gets 1 'coming soon' post added when there should be 5. Also, the 'fake' posts look like they still have permalinks. The hashtag doesn't get attributed to the href, or will that get covered up once I post an actual coming soon image? – Desi Sep 14 '14 at 0:03
  • Thank you! That took care of the posts. As far as the links in the coming soon posts, I think it would be logical to just get rid of the .post-info div that reveals the info and just leave the coming soon image. I can do this with CSS but I was wondering if it was more efficient to just implement that into the function itself. – Desi Sep 14 '14 at 0:34
  • Just noticed an issue with this. Everything works fine, but when I get to the single blog pages, I notice that five articles get added to the single post that's supposed to be there. So to clarify, on the single pages, my blog post is there, followed by the navigation, then followed by five additional 'coming soon' posts. How can I get rid of these for the single pages? – Desi Sep 18 '14 at 3:42
  • In my code there is this omment: // probably you need to put other conditions here e.g. $query->is_front_page() to affect only specific pages and not all... because you have to set where to apply the addition of coming soon posts. At least add || $query->is_singular() (I have updated answer to include that), but it may not be enough: only you know where the routine should be ran and where not. @Desi – gmazzap Sep 18 '14 at 5:29
  • Is it possible to switch out the ID for a class? The multiple duplicate IDs are throwing out errors. If it's a lot of work, it doesn't matter much. After all, the site doesn't necessarily have to be 100% valid. – Desi Sep 26 '14 at 23:43
1

Here's one idea how one could play with the the_posts filter in a way that you don't have to modify your current template code:

/**
 * Append "Coming Soon" posts, if there are not enough posts
 *
 * @see http://wordpress.stackexchange.com/a/161275/26350
 */
add_filter( 'the_posts',
    function( $posts, $q )
    {
        if( ! is_admin() && $q->is_main_query() )
        { 
            $count = count( $posts );
            $ppp   = $q->query_vars['posts_per_page'];

            // Assume there's at least one post available, before filling up:
            if( $count > 0 && $count <= $ppp  )
            {
                // Cet "Coming Soon" post
                $tmp = get_post( 123 ); // Adjust this ID to your needs

                // Fill up with the "Coming Soon" post:
                for( $i = $count + 1 ; $i <= $ppp; $i++ )
                {
                    $posts[] = $tmp;
                }
            }
        }
        return $posts;
    }
,99, 2 );

This assumes you have a Coming Soon! post/page, you just have to modify the post ID.

Notice that this is for PHP versions 5.3+.

Update: Thanks to @G.M. for the tip about skipping the pre_get_posts hook.

I hope you can modify this to your needs.

  • That was my first thought. Problem with it is that if a real "Coming Soon" post exists, hide it from feeds or from other main and secondaries queries is very hard. Also, just a tip, you don't need here to nest 2 filters, 'the_posts' filter pass as second argument the query, so you can do there what you do in 'pre_get_posts'. – gmazzap Sep 13 '14 at 13:27
  • @G.M. thanks for the tips. I avoided the virtual approach because I thought it would be handy to be able to click on the "Coming Soon" (like an Ad) and easily change the thumbnail without coding. But you're right, it's hard if you need to hide the post, but ideal if it's an Ad like post. +1 to your idea. – birgire Sep 13 '14 at 14:24
  • Yes, in my code the hardcoded thumbnail image can be changed with an url of an attachment post image, or a set of attachment images using an attachment taxonomy. But that too much for an answer :) – gmazzap Sep 13 '14 at 14:28
  • yes, agree, the weekend answers should be short & jolly ;-) – birgire Sep 13 '14 at 14:31
1

Having spent 50 minutes unsuccessfully explaining accepted answer to colleague...

I want to point out that for simple case the basic check of post count might be perfectly sufficient to template such output:

if ( 6 > $wp_query->post_count ) {

    // placeholder output
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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