I'm trying to modify the content of a post when it is FIRST published (i.e. I don't want it to run if the post is updated later). However, whenever my code runs, the meta created by Toolset custom fields has not yet been created. I'm assuming Toolset must add the custom field values after the post is published, and therefore it hasn't been added yet using the hook below. Can you suggest a better alternative? Relevant code below:
add_action('transition_post_status', 'pp_digest_fetch_tags', 10, 3);
function pp_digest_fetch_tags($new_status, $old_status, $post) {
if (get_post_type($post) == 'digest' && $new_status == 'publish' && $old_status != 'publish') {
$post_id = $post->ID;
$url = get_post_meta($post_id, 'wpcf-digest-source-url');
.......
Thanks!
Hi,
Thank you for contacting us and I'd be happy to assist.
Your observation is correct and the hook "transition_post_status" seems to trigger before the Toolset custom field data has been saved.
In my tests, it is possible to use the "save_post" hook for this, for example:
( ref: https://developer.wordpress.org/reference/hooks/save_post/ )
function wpdocs_run_on_publish_only( $post_id, $post ){
if ( 'digest' == $post->post_type ) {
if ( (isset($_POST['original_post_status'])) && ($_POST['original_post_status'] == 'auto-draft' ) ) {
$url = get_post_meta($post_id, 'wpcf-digest-source-url');
}
}
}
add_action( 'save_post', 'wpdocs_run_on_publish_only', 30, 2 );
Note: The check for the post's "auto-draft" status ( i.e. $_POST['original_post_status'] == 'auto-draft' ), will make sure that the code is executed only the first time the post is published from the post edit screen and not for any subsequent updates.
I hope this helps and please let me know if you need any further assistance around this.
regards,
Waqar
Thanks. I've made progress based on your code, but unfortunately I think it's getting stuck in an infinite loop because it invokes the wp_update_post() function later in the code. Do you know a way to prevent this from happening?
add_action( 'save_post', 'pp_digest_fetch_tags', 30, 2 );
function pp_digest_fetch_tags( $post_id, $post ){
if (get_post_type($post) == 'digest') {
if ( (isset($_POST['original_post_status'])) && ($_POST['original_post_status'] != 'publish' ) ) {
// get URL of source content
$url = get_post_meta($post_id, 'wpcf-digest-source-url', true);
// get title
$url_contents = file_get_contents($url);
$new_title = preg_match('/<title[^>]*>(.*?)<\/title>/ims', $url_contents, $match) ? $match[1] : null;
// set new slug based on title
$new_slug = wp_unique_post_slug(
sanitize_title($new_title),
$post->ID,
$post->status,
$post->post_type,
$post->post_parent
);
// get meta
$tags = get_meta_tags($url);
$new_content = $tags['description'];
if (isset($tags['og:image'])) {
$new_image = $tags['og:image'];
} elseif (isset($tags['twitter:image'])) {
$new_image = $tags['twitter:image'];
} elseif (isset($tags['thumbnail'])) {
$new_image == $tags['thumbnail'];
} else {
$new_image == '';
}
// update post
$post_update = array(
'ID' => $post_id,
'post_title' => $new_title,
'post_content' => $new_content,
'post_name' => $new_slug
);
wp_update_post($post_update);
exit();
...
PS: I confirmed it is retaining "auto-draft" as the original status so that's why it's getting stuck in a loop.
Thanks for writing back.
To avoid going into the infinite loop, you can use a static variable, before the "wp_update_post" function, so that it can only execute, once.
For example:
....
// set a static variable to false, initially
static $updated = false;
// if wp_update_post has already run once, exit.
if ( $updated ) {
return;
}
// set the static variable to true, so the wp_update_post can run once
$updated = true;
// update post
$post_update = array(
'ID' => $post_id,
'post_title' => $new_title,
'post_content' => $new_content,
'post_name' => $new_slug
);
wp_update_post($post_update);
....
My issue is resolved now. Thank you!