Frage

Context: I'm using a plugin that allows me to add author boxes throughout my site (Simple Author Box), while providing an easy way for any user to update their social media links and profile pictures. I figured I could also leverage that plugin to dynamically show the team members in the site's about section.

However, I didn't want to have author archives for the team members that won't be publishing any posts in the future (designer, myself etc.), so I used the solution from this question as a starting point to disable specific users' author archives and from there I created a few additional functions in order to automate that functionality (author archives are now automatically being disabled/enabled according to the number of posts each user has published).

One of these functions is hooked to post_updated, which according to the docs: "Fires once an existing post has been updated." [emphasis added]

Here's the function's code (please forgive any lack of good practices, I'm new to PHP and not an experienced programmer):

/* 
* This function does the checks and the actual value update, if needed.
* It's called from inside the callback.
*/
function maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled) {
    if ($published_posts == 0 && $author_archive_disabled != 'on') {
        update_user_meta($user_id, '_author_archive_disabled', 'on');
    } elseif ($published_posts != 0 && $author_archive_disabled != 'off') {
        update_user_meta($user_id, '_author_archive_disabled', 'off');
    }
}

/* 
* The callback itself.
*/
function maybe_update_author_archive_status_on_post_update($post_id, $post_after, $post_before) {
    if($post_before->post_status != 'publish' && $post_after->post_status != 'publish') {
        return;
    }
    
    $old_author = $post_before->post_author;
    $new_author = $post_after->post_author;
    $authors = array($old_author);
    
    /* If the post author has changed, I might need to update both author archive status */
    if($new_author != $old_author) {
        $authors[] = $new_author;
    }

    foreach($authors as $author) {
        $user_id = intval($author, 10);
        $author_archive_disabled = get_user_meta($user_id, '_author_archive_disabled', true);
        $published_posts = count_user_posts($user_id);

        maybe_update_author_archive_status($user_id, $published_posts, $author_archive_disabled);
    }
}
add_action('post_updated', 'maybe_update_author_archive_status_on_post_update', 10, 3);

However, to my surprise (and delight actually), it's also firing when I create and publish a new post. Can anyone explain me why? Under which circumstances this function wouldn't be fired? Even though this is the behavior I desired and everything is working as I wanted it to, this is not what I expected it would happen after reading the documentation.

War es hilfreich?

Lösung

also firing when I create and publish a new post

If you mean something like, you clicked the "Add New" button (which brings you to the post add new page at /wp-admin/post.php), and then you composed your post and finally hit the "Publish" button, then it's actually normal for the post_updated hook to get fired twice or more.

Why so or what happens is:

  • After you clicked the "Add New" button, WordPress will automagically create a post with the auto-draft status (post_status = auto-draft).

  • While composing your post, WordPress will auto-save the post so that you don't lose what you've composed thus far, and for each auto-save, the post_updated hook will be fired. And note that, during an auto-save, the post status is set to draft.

  • And after you hit the "Publish" button, WordPress updates the post (with the status changed from auto-draft or draft to publish), and then the post_updated hook will be fired once more.

So as you could see, the hook could get fired at least twice when you manually create and publish a post.

But if you do that programmatically, e.g. using wp_insert_post(), then the hook will not be fired. Note though, if you have plugins or custom code in your theme, the hook might be fired, e.g. a code that runs via save_post and modifies the post slug then call wp_update_post():

// In a default WordPress setup/installation:

// This will not fire the post_updated hook.
$id = wp_insert_post( array(
    'post_title'  => 'Just testing',
    'post_status' => 'publish',
) );

// And this will fire it, but just once.
wp_update_post( array(
    'ID'           => $id,
    'post_content' => 'Sample content',
) );

And I think you might want to execute your code only if the post is not being auto-saved, either as an auto-draft or revision.

So for that purpose, you can check if the constant DOING_AUTOSAVE is defined and that it's true-ish:

// In your function (maybe_update_author_archive_status_on_post_update()), at the top:
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
    return;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit wordpress.stackexchange
scroll top