Skip to content

Instantly share code, notes, and snippets.

@RadGH
Last active July 16, 2020 10:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RadGH/cc8ceeaf2a413dac1b947c1cbfea1282 to your computer and use it in GitHub Desktop.
Save RadGH/cc8ceeaf2a413dac1b947c1cbfea1282 to your computer and use it in GitHub Desktop.
Queue an action that occurs after acf has completed saving a post, providing the callback, post id, and arguments up front. Useful if other fields that are saved with the post need to be overwritten.
<?php
/**
* Triggers an action after the "acf/save_post" action, priority 1000.
* If hooks are not called, they will be called at the end of the PHP thread
*
* Specify your callback as the first argument, and any arguments to pass to it as the second argument.
*
* @param callable Callback
* @param post_id The ACF-formatted post id you want to hook into
* @param mixed Additional parameters to pass to the callback
*
* @return array|null
*/
function add_action_after_save_post( $cb, $post_id, $args ) {
static $data = null;
if ( $data === null ) $data = array();
if ( $cb == "@get" ) {
// get data
return $data;
}else{
// add data
$data[] = array(
'callback' => $cb,
'post_id' => $post_id,
'args' => $args
);
}
}
// Trigger callbacks from above during acf/save_post priority 1000
// If hooks are not called, they will be called at the end of the PHP thread
function __after_saved_post( $post_id = null ) {
$data = add_action_after_save_post( '@get', 0, 0 );
if ( !$data ) return;
// Loop through registered hooks
foreach( $data as $i => $d ) {
$cb = $d['callback'];
// Ensure the callback is valid
if ( !is_callable($cb) ) {
wp_die( new WP_Error('invalid-callable', 'Invalid callable function passed to queue_after_save_post_callback()', array( 'data' => $d, 'post_id' => $post_id, 'all data' => $data )));
exit;
}
// Check that the post id matches (including prefix like user_1234)
if ( $post_id == $d['post_id'] ) {
call_user_func_array( $cb, $d['args'] );
unset( $data[$i] );
}
}
}
add_action( 'acf/save_post', '__after_saved_post', 1000 );
register_shutdown_function( '__after_saved_post', '_shutdown' );
@RadGH
Copy link
Author

RadGH commented Jul 16, 2020

This is a very niche solution. If you aren't sure what it does you probably want something else. The main reason you would need this is if you want to change some fields when a certain field is updated, but your changes get overwritten as ACF hasn't finished updating all other fields yet. You can use acf/save_post to get around this in most cases, but then you lose the ability to hook into direct field changes.

Usage:

<?php
// When a field changes
add_filter( 'acf/update_value/name=application_status', 'pre_save_application_status' ), 10, 3 );

// Queue our action AFTER acf has finished all data for the post
function pre_save_application_status( $value, $post_id, $field ) {
	add_action_after_save_post(
		'process_application_status_change', // Callback
		$post_id,                            // Post ID
		array($value, $post_id, $field)      // Args
	);

	return $value;
}

// Triggered after "application_status" was changed, but only when ACF finished saving all other meta fields
function process_application_status_change( $value, $post_id, $field ) {
	update_field( 'something_else', 'new value', $post_id );
}

And here is an example where that would be triggered (this method is thanks to register_shutdown_function because there is no acf/save_post):

<?php
update_field( 'application_status', 'New', 123 );

It will also be triggered when updating that field from the WP dashboard

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment