This problem has been bothering me for a while now, and I only just came across the solution this week. The issue was that when you schedule a post for the future, when it does finally post it was seemingly not running the publish_post hook that I had set. Multiple solutions suggested using future_to_publish as a hook, and that did not work either. The actual solution was to hook to publish_future_post, but in addition the function I was executing had to be modified a bit.
The original function was something along these lines: When a post is published for the first time, post a link to it on Twitter. publish_post also fires when you update a post, so to make sure it was only posted on the original posting the accepted solution was to make sure post_date and post_modified dates were equal. Here is an simple example.
PHP Code:<?php
// accepted solution, but this will not work as expected
// on scheduled posts.
add_action('publish_post','bob_on_publish_post');
add_action('publish_future_post','bob_on_publish_post');
function bob_on_publish_post($id) {
$post = get_post($id);
if($post->post_modified != $post->post_date) return;
// la de da, doing stuff.
return;
}
?>
The reason this fails is that it turns out when a post is scheduled for future posting, post_date and post_modified are not equal after all. This issue caught me by surprise because it does not exist when working with Drafts. If the post is marked as draft, saved, and then manually published later, this test will still allow the hook to run. This is probably due to how WordPress handles filling up your database with redundant revisions, but it even works if you have a Plugin disabling revisions (like me).
A drawback of the WordPress hook system – there is no way to add arguments to the add_action function to get passed to the callback. This means I cannot do something like add an action, and mark it as “now” or “future” and receive that as a second argument on bob_on_post_publish.
The way around this is to write two additional functions. I personally do not find that very palatable, but we do what we have to do. Both functions will simply wrap the main post_publish function. This way I can pass the value of if the post is being published now or if it was marked future, and then only check if the dates match if the choice was now.
PHP Code:<?php
add_action('publish_post','bob_on_publish_now');
add_action('publish_future_post','bob_on_publish_future');
function bob_on_publish_now($id) {
return bob_on_publish_post($id,'now');
}
function bob_on_publish_future($id) {
return bob_on_publish_post($id,'future');
}
function bob_on_publish_post($id,$when) {
$post = get_post($id);
if($when == 'now' and $post->post_modified != $post->post_date) return;
// la de da, doing stuff.
return;
}
?>
Originally instead of creating two new named functions, I was going to pass a lambda function to add_action and say “screw your old PHP support”, however WordPress has a limitation where it cannot later remove_action unless it is a named function. I decided to stick with supporting that purely in the interest of later if I write another plugin or modify this one to decide “I changed my mind I do not want to run this on Publish” and disable the hook callback for some obscure condition.
