4

My aim is to use the Heartbeat API to check if new posts have been published since the blog's homepage was loaded. If new posts have been published, I will display a link at the top of the screen "16 new posts" which, when clicked, will insert the new posts into the DOM.

My problem:

How can I check if new posts have been published since the blog's homepage was loaded?

My PHP so far:

function new_post_check( $response, $data, $screen_id ) {

    // Do some processing here.

    // Respond.
    return $response;
}
add_filter( 'heartbeat_received', 'new_post_check', 10, 3 );
add_filter( 'heartbeat_nopriv_received', 'new_post_check', 10, 3 );

My script so far:

$( document ).on( 'heartbeat-tick.poll', function( event, data ) {
    // Print data to the console.
    console.log( data );
});
0

2 Answers 2

3

Determining the current time

There's the current_time() function in core that allows to pass three different values as first argument and gmt (the offset) as second argument. About the 1st:

  1. mysql -> gmdate( 'Y-m-d H:i:s' ), human readable e.g 2004/07/8 13:35:19

  2. timestamp -> time(), the UNIX timestamp for e.g. 1335939007

  3. A custom argument that is a valid formatting string for PHPs date() function,

    for e.g. D, d M Y H:i:s

Now we will just go with

$now = current_time( 'mysql' );

to not get the UNIX timestamp of (pretty much) now, as the WP_Query will need something that she can transform to a UNIX timestamp using strtotime().

Querying for newer posts

Then we will use the date_query clause with after to query posts later than now. I use the fields argument there to reduce the impact on the database. That means that the result will just be used to check if we got newer posts and only fetch the IDs instead of whole rows.

$newer_posts_IDs = new WP_Query( array(
    'post_type'  => 'post',
    'fields'     => 'ids',
    'date_query' => array(
        'after' => current_time( 'mysql' ),
    ),
) );

...then $newer_posts_IDs->found_posts will hold the amount of posts for the query.

Where to go from here?

What you consider to be "finished" is up to you. You could add above query/check to something like the jQuery ( document ).ready() event, add it to the shutdown hook or whatever pleases you.

Finally you will need to repeat above query with a whole set of rows, fetched via . Search through my answers on that topic.

You probably want to insert them on a specific point in DOM and add an empty container there as placeholder. jQuery offers the .before() API function in case you already got posts. Else you will probably just use .html() to insert your content.

2
  • 2
    Thanks @kaiser, both current_time( 'mysql' ) and date_query are hugely helpful pointers. Regarding where to go from here, I'm using Heartbeat so can perform the query just once inside my new_post_check() function. I'll pass the initial current_time( 'mysql' ) into my script using wp_localize_script then each time new_post_check() is executed I'll update the time. Sep 3, 2014 at 18:43
  • @henrywright That's a very good plan. I wouldn't do otherwise myself :)
    – kaiser
    Sep 3, 2014 at 19:21
1

First you need to give him the date to send when the ticks comes:

// Hook into the heartbeat-send and give him the milliseconds timestamp since epoch
$(document).on('heartbeat-send', function(e, data) {
    data['now'] = new Date().getTime();
});

We have prepared the field, now lets listen for when the heart ticks:

$(document).on('heartbeat-tick', function(e, data) {
    alert(data);
});

Now the php part:

$then = 0;
function my_heartbeat($response, $data)
{
    global $then;

    $then = date("Y-m-d H:i:s", $data['then']);

    add_filter('posts_where', 'filter_where_date');

    $query = new WP_Query(array('post_type' => 'post'));        
    $response['number'] = $query->found_posts;

    remove_filter('posts_where', 'filter_where_date');

    return $response;
}
add_filter('heartbeat_received', 'my_heartbeat', 10, 3);

function filter_where($where = '')
{
    global $then;

    $where .= " AND post_date >= {$then} AND post_date < NOW()";
    return $where;
}

Hope this helps.

3
  • 2
    Why not use a date_query?
    – kaiser
    Sep 3, 2014 at 17:53
  • Thank you for this answer, I've decided to use date_query as pointed out by @kaiser. Sep 3, 2014 at 18:45
  • You are welcome. I copy-pasted an old filter I once used =D
    – aifrim
    Sep 4, 2014 at 9:17

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.