wordpressadvanced-custom-fields

WP save_post_{$post->post_type} with ACF custom post type leads to infinite loop


I'm using ACF Pro to easily register a custom post type for an internal use purpose (no frontend). Every feature is disabled (content, title, slug, ...) as I need to set a UUID as the post_title and post_name, and every other bit of data is handled by ACF.

I used the save_post_{$post->post_type} hook, with a priority of 25, in order to hook into the post save and format the title to a UUIDv4 string, and came with the code below :

<?php 
// ...
public function wprc_set_post_title_to_uuid4($post_id)
{
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    if (wp_is_post_revision($post_id)) return;

    $post_type = get_post_type($post_id);
    if ($post_type != 'wprc_machinery_fleet') return;

    remove_action('save_post', 'wpse51363_save_post', 10);
    wp_update_post(array('ID' => $post_id, 'post_title' => uuidv4()));
    add_action('save_post', 'wpse51363_save_post', 10);
}
add_action('save_post', array($this, 'wprc_set_post_title_to_uuid4'), 10);

I'm now turning mad not being able to figure out why I trigger an infinite loop upon post creation (add new) and post update (edit).

As soon as I hit the Add New button, a post is effectively created in the DB with the auto-draft status, but instantly loops: post_title is constantly updated (checked with PHPMyAdmin). Same effect runs on an existing post update.

I checked so many times, did use the remove_action() and add_action() hooks, but this seems ignored ...

What am I doing wrong here ? Is there a way to achieve this by other means ? I imagined creating a text field with ACF and dynamically inserting a UUID in it and using this to edit my post title, but I would face the same issue?

EDIT: Solved.

For anyone looking, corrected code below (function names and callback format):

<?php 
// ...
public function wprc_set_post_title_to_uuid4($post_id)
{
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;

    if (wp_is_post_revision($post_id)) return;

    remove_action('save_post_wprc_machinery_fleet', array($this, 'wprc_set_post_title_to_uuid4'), 10);
    wp_update_post(array('ID' => $post_id, 'post_title' => uuidv4()));
    add_action('save_post_wprc_machinery_fleet', array($this, 'wprc_set_post_title_to_uuid4'), 10);
}
add_action('save_post_wprc_machinery_fleet', array($this, 'wprc_set_post_title_to_uuid4'), 10);


Solution

  • Looks like you're removing the incorrect function name. Try this:

    <?php
    
    public function wprc_set_post_title_to_uuid4($post_id)
    {
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
    
        if (wp_is_post_revision($post_id)) return;
    
        $post_type = get_post_type($post_id);
        if ($post_type != 'wprc_machinery_fleet') return;
    
        remove_action('save_post', array( $this, 'wprc_set_post_title_to_uuid4' ), 10);
        wp_update_post(array('ID' => $post_id, 'post_title' => uuidv4()));
        add_action('save_post', array( $this, 'wprc_set_post_title_to_uuid4' ), 10);
    }
    add_action('save_post', array($this, 'wprc_set_post_title_to_uuid4'), 10);