I have a custom post type called "Envios". In it I've created a Custom Meta box which allows to select users and posts. When one of this custom post types is published it sends an email to the selected users with the content of the selected posts. To select the posts I use the ACF plugin, with the field Post Object.
The issue is that sometimes the emails are sent properly but in most cases nothing is delivered.
Here is the code:
// Adds Custom Meta Box
function email_delivery_munda_add_custom_box() {
$screens = ['envios', 'md_cpt'];
foreach ($screens as $screen) {
add_meta_box(
'md_email_delivery_box_id', // Unique ID
'Detalles de email', // Box title
'md_email_delivery_custom_box_html', // Content callback, must be of type callable
$screen, // Post type
'side',
'default'
);
}
}
add_action('add_meta_boxes', 'email_delivery_munda_add_custom_box');
// Adds the content of the Custom Meta Box
function md_email_delivery_custom_box_html($post)
{
$asunto = get_post_meta($post->ID, 'email_delivery_asunto', true);
wp_nonce_field( 'save_md_email', 'md_email_nonce' );
if ($asunto == "") {
$asunto = "Informe - " . date("d-m-Y");
}
?>
<div class="email-delivery-asunto">
<label for="email_delivery_asunto">Asunto</label>
<input type="text" name="email_delivery_asunto" id="email_delivery_asunto" class="postbox" value=" <?php echo $asunto ?>" placeholder="Informe - <?php echo date("d-m-Y") ?>">
</div>
<div class="email-delivery-receptores">
<label for="select-emails">Destinatarios</label>
<?php
$blogusers = get_users();
// Array of WP_User objects.
echo '<select name="clients-email-input[]" id="select-emails" class="admin-email-receptores" multiple="multiple"><option></option>';
foreach ( $blogusers as $user ) {
echo '<option value="'. esc_html( $user->user_email ) .'">' . esc_html( $user->display_name ) . '</option>';
}
echo '</select>';
?>
</div>
<?php $enviados = get_post_meta($post->ID, 'email_send', true); ?>
<div class="email-delivery-asunto">
<label for="email_send">Ultimo envio</label>
<p id="email_send"><?php echo $enviados ?></p>
</div>
<?php
}
// Saves post data
function md_email_save_postdata($post_id) {
if ( ! isset( $_POST['md_email_nonce'] ) ) {
return $post_id;
}
if ( ! wp_verify_nonce( $_POST['md_email_nonce'], 'save_md_email' ) ) {
return $post_id;
}
$asunto = sanitize_text_field( $_POST['email_delivery_asunto'] );
update_post_meta( $post_id, 'email_delivery_asunto', $asunto );
}
add_action('save_post', 'md_email_save_postdata');
// Sends an email when custom post type Envios is published
function md_email_publish_postdata($post_id) {
$asunto = sanitize_text_field( $_POST['email_delivery_asunto'] );
$headers = array(
'Content-Type: text/html; charset=UTF-8'
);
$enviados = sanitize_text_field( $_POST['email_send'] );
$blogusers = get_users();
foreach ($_REQUEST['clients-email-input'] as $selectedOption) {
array_push($headers, "BCC:" . $selectedOption);
foreach ( $blogusers as $user ) {
if ($user->user_email === $selectedOption) {
$enviados .= "<b>" . esc_html( $user->display_name ) . "</b> " . esc_html( $user->user_email) . "<br>";
}
}
}
update_post_meta( $post_id, 'email_send', $enviados );
$content = '';
// Removing from here makes it work.
$posts = get_field('casos',$post_id);
if( $posts ): ?>
<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
<?php setup_postdata($post);
$content .= '<h1>' . get_the_title( $post ) . '</h1><br>';
$content .= '<p>' . get_field( 'descripcion_breve', $post) . '</p><br>';
endforeach; ?>
<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
<?php endif;
// until here.
$clients_list = "[email protected]";
wp_mail( $clients_list, $asunto , $content, $headers );
}
add_action('publish_envios', 'md_email_publish_postdata', 10, 2 );
IF I remove the ACF part from // Removing from here makes it work. to // until here. the emails are sent okay every time but without the selected posts content.
I can't really tell which is the problem, but maybe you can impart some wisdom on the matter. Thanks in advance!
SOLUTION:
ACF use the action acf/save_post AFTER the post is published, so I was trying to get a value that wasn't there yet.
So I changed the action to the acf save_post and between it I use if (get_post_status($post_id) == 'publish') {
to check the status of the post.
Furthermore I update the Object Post output as follows:
$posts = get_field( 'casos', $post_id );
if( $posts ):
foreach( $posts as $post):
$content .= '<h1>' . get_the_title( $post ) . '</h1><br>';
if ( get_field( 'descripcion_breve', $post->ID )) {
$content .= '<p>' . get_field( 'descripcion_breve', $post->ID ) . '</p><br>';
} else {
$content .= '<p>Description empty</p><br>';
}
endforeach;
endif;
I have a custom post type called "Envios". In it I've created a Custom Meta box which allows to select users and posts. When one of this custom post types is published it sends an email to the selected users with the content of the selected posts. To select the posts I use the ACF plugin, with the field Post Object.
The issue is that sometimes the emails are sent properly but in most cases nothing is delivered.
Here is the code:
// Adds Custom Meta Box
function email_delivery_munda_add_custom_box() {
$screens = ['envios', 'md_cpt'];
foreach ($screens as $screen) {
add_meta_box(
'md_email_delivery_box_id', // Unique ID
'Detalles de email', // Box title
'md_email_delivery_custom_box_html', // Content callback, must be of type callable
$screen, // Post type
'side',
'default'
);
}
}
add_action('add_meta_boxes', 'email_delivery_munda_add_custom_box');
// Adds the content of the Custom Meta Box
function md_email_delivery_custom_box_html($post)
{
$asunto = get_post_meta($post->ID, 'email_delivery_asunto', true);
wp_nonce_field( 'save_md_email', 'md_email_nonce' );
if ($asunto == "") {
$asunto = "Informe - " . date("d-m-Y");
}
?>
<div class="email-delivery-asunto">
<label for="email_delivery_asunto">Asunto</label>
<input type="text" name="email_delivery_asunto" id="email_delivery_asunto" class="postbox" value=" <?php echo $asunto ?>" placeholder="Informe - <?php echo date("d-m-Y") ?>">
</div>
<div class="email-delivery-receptores">
<label for="select-emails">Destinatarios</label>
<?php
$blogusers = get_users();
// Array of WP_User objects.
echo '<select name="clients-email-input[]" id="select-emails" class="admin-email-receptores" multiple="multiple"><option></option>';
foreach ( $blogusers as $user ) {
echo '<option value="'. esc_html( $user->user_email ) .'">' . esc_html( $user->display_name ) . '</option>';
}
echo '</select>';
?>
</div>
<?php $enviados = get_post_meta($post->ID, 'email_send', true); ?>
<div class="email-delivery-asunto">
<label for="email_send">Ultimo envio</label>
<p id="email_send"><?php echo $enviados ?></p>
</div>
<?php
}
// Saves post data
function md_email_save_postdata($post_id) {
if ( ! isset( $_POST['md_email_nonce'] ) ) {
return $post_id;
}
if ( ! wp_verify_nonce( $_POST['md_email_nonce'], 'save_md_email' ) ) {
return $post_id;
}
$asunto = sanitize_text_field( $_POST['email_delivery_asunto'] );
update_post_meta( $post_id, 'email_delivery_asunto', $asunto );
}
add_action('save_post', 'md_email_save_postdata');
// Sends an email when custom post type Envios is published
function md_email_publish_postdata($post_id) {
$asunto = sanitize_text_field( $_POST['email_delivery_asunto'] );
$headers = array(
'Content-Type: text/html; charset=UTF-8'
);
$enviados = sanitize_text_field( $_POST['email_send'] );
$blogusers = get_users();
foreach ($_REQUEST['clients-email-input'] as $selectedOption) {
array_push($headers, "BCC:" . $selectedOption);
foreach ( $blogusers as $user ) {
if ($user->user_email === $selectedOption) {
$enviados .= "<b>" . esc_html( $user->display_name ) . "</b> " . esc_html( $user->user_email) . "<br>";
}
}
}
update_post_meta( $post_id, 'email_send', $enviados );
$content = '';
// Removing from here makes it work.
$posts = get_field('casos',$post_id);
if( $posts ): ?>
<?php foreach( $posts as $post): // variable must be called $post (IMPORTANT) ?>
<?php setup_postdata($post);
$content .= '<h1>' . get_the_title( $post ) . '</h1><br>';
$content .= '<p>' . get_field( 'descripcion_breve', $post) . '</p><br>';
endforeach; ?>
<?php wp_reset_postdata(); // IMPORTANT - reset the $post object so the rest of the page works correctly ?>
<?php endif;
// until here.
$clients_list = "[email protected]";
wp_mail( $clients_list, $asunto , $content, $headers );
}
add_action('publish_envios', 'md_email_publish_postdata', 10, 2 );
IF I remove the ACF part from // Removing from here makes it work. to // until here. the emails are sent okay every time but without the selected posts content.
I can't really tell which is the problem, but maybe you can impart some wisdom on the matter. Thanks in advance!
SOLUTION:
ACF use the action acf/save_post AFTER the post is published, so I was trying to get a value that wasn't there yet.
So I changed the action to the acf save_post and between it I use if (get_post_status($post_id) == 'publish') {
to check the status of the post.
Furthermore I update the Object Post output as follows:
$posts = get_field( 'casos', $post_id );
if( $posts ):
foreach( $posts as $post):
$content .= '<h1>' . get_the_title( $post ) . '</h1><br>';
if ( get_field( 'descripcion_breve', $post->ID )) {
$content .= '<p>' . get_field( 'descripcion_breve', $post->ID ) . '</p><br>';
} else {
$content .= '<p>Description empty</p><br>';
}
endforeach;
endif;
Share
Improve this question
edited Oct 18, 2018 at 16:50
Nicolas Landgraf
asked Oct 17, 2018 at 18:03
Nicolas LandgrafNicolas Landgraf
34 bronze badges
3
|
2 Answers
Reset to default 0...Removed my prior 'solutions'...
So, the real problem here is that this function is hooked to publish_post
action, at which point the post might not be saved yet, if it is a new post. Only if it is a post already saved but with some other status, we can access the ACF values using get_field()
.
Solution could be to use a hook acf/save_post
with priority of 10 or larger, since it fires after the post has been saved, therefore allowing us to get the values using get_field()
.
This is a short example of usage of this hook:
function my_acf_save_post( $post_id ) {
// bail if wrong post type
if( get_post_type( $post_id ) !== 'envios' ) {
return;
}
// get new value
$posts = get_field( 'casos', $post_id );
// do something
}
add_action('acf/save_post', 'my_acf_save_post', 20);
And even if I change my add_action to a "save_post_post-type" webhook instead of "publish_post-type" webhook acf fields still not populated until post is published and THEN updated!
setup_postdata
andwp_reset_postdata
are for front-end queries, they won't work reliably (or at all) on most admin pages. – Milo Commented Oct 18, 2018 at 3:22ACF use the action acf/save_post AFTER the post is published
- that is not entirely correct, it depends on the priority given. If the priority is less than 10, then it is called before the post save, but if it is greater than 10, it is called after the post is saved. Check the official documentation. – djboris Commented Oct 18, 2018 at 19:47