We can utilize the add_term_relationship
action to check if the current post is already assigned as popular
. add_term_relationship
fires before a term is inserted.
I also think that you are using the wrong hook here to send your mail on. added_term_relationship
fires quite early before any error checking. You can still encounter a failure after added_term_relationship
which means that the term insertion will not happen successfully and will return an error. set_object_terms
is a better hook to use as it only fires if a term was successfully inserted.
/**
* Fires immediately before an object-term relationship is added.
*
* @since 2.9.0
*
* @param int $object_id Object ID.
* @param int $tt_id Term taxonomy ID.
*/
do_action( 'add_term_relationship', $object_id, $tt_id );
$wpdb->insert( $wpdb->term_relationships, array( 'object_id' => $object_id, 'term_taxonomy_id' => $tt_id ) );
/**
* Fires immediately after an object-term relationship is added.
*
* @since 2.9.0
*
* @param int $object_id Object ID.
* @param int $tt_id Term taxonomy ID.
*/
do_action( 'added_term_relationship', $object_id, $tt_id );
We can try the following (NOTE: This is untested)
add_action( 'add_term_relationship', function ( $object_id, $tt_id )
{
// Check if the post is already in the popular term, if so, bail
if ( has_term( 'popular', 'song_category', $object_id ) )
return;
// Check if our post is going to be added as popular, if not, bail
if ( 1 !== $tt_id ) // Set the correct ID for popular term
return;
/**
* We are now sure that our post is not yet popular, and we will be
* making it popular, so lets continue
*
* We will be sending a mail when the term is inserted. We will use the
* set_object_terms hook as it fires on successful insertion of the term
*/
add_action( 'set_object_terms', function ( $object_id )
{
$post = get_post( $object_id );
$author = get_userdata( $post->post_author );
$terms = get_the_terms( $post->ID, 'song_category' );
$email = get_post_meta( $post->ID, 'custom_email', true );
$message = 'Hi ' . $author->display_name;
wp_mail( $email, "Your song is now in the popular section!", $message );
});
}, 10, 2 );
EDIT
Make sure that you change 1
in 1 !== $tt_id
to the exact ID of your term. I have also just copied and pasted your code into my code, so I'm not sure if that is your complete code or if that is working as-is
EDIT 2
You can use the following if you do not know the ID of the popular term (I accept that popular
ids the term slug)
$term_object = get_term_by( 'slug', 'popular', 'song_category' );
$term_id = $term_object->term_id;
Lets rewrite the code to incorporate that
add_action( 'add_term_relationship', function ( $object_id, $tt_id )
{
// Check if the post is already in the popular term, if so, bail
if ( has_term( 'popular', 'song_category', $object_id ) )
return;
// Get the term ID of the popular term. We will get the term object by term slug.
$term_object = get_term_by( 'slug', 'popular', 'song_category' );
$term_id = $term_object->term_id;
// Check if our post is going to be added as popular, if not, bail
if ( $term_id != $tt_id ) // Set the correct ID for popular term
return;
/**
* We are now sure that our post is not yet popular, and we will be
* making it popular, so lets continue
*
* We will be sending a mail when the term is inserted. We will use the
* set_object_terms hook as it fires on successful insertion of the term
*/
add_action( 'set_object_terms', function ( $object_id )
{
$post = get_post( $object_id );
$author = get_userdata( $post->post_author );
$terms = get_the_terms( $post->ID, 'song_category' );
$email = get_post_meta( $post->ID, 'custom_email', true );
$message = 'Hi ' . $author->display_name;
wp_mail( $email, "Your song is now in the popular section!", $message );
});
}, 10, 2 );