Creating a function that receives the taxonomy terms that have been changed in a custom post type

After WordPress has updated a posts’ taxonomy terms it triggers the action:

set_object_terms

(see source) which passes 6 variables:

  1. Object ID
  2. Terms that were assigned to the post (or added depending on 5) (could be their slug or term ID).
  3. Taxonomy-term IDs of above (not term IDs)
  4. The taxonomy
  5. Append. If true – terms in 2 are added to existing terms. If false (default) terms replace the existing terms.
  6. The post’s terms before updating (as taxonomy-term IDs)

Problem 1

Unfortunately there is no way of knowing if that object refers to post, or something (like a user). That might be a way hooking onto set_object_terms only when you can be sure that when its next fired, it refers to a post.

Problem 2

The IDs are passed are taxonomy-term IDs, not term-IDs – and most WordPress functions use the term ID. So you’ll probably need to get the term ID (and taxonomy) from the taxonomy term ID to do anything useful. A potential work around is, since we know the taxonomy, list all the terms and do a simple foreach loop and filter them. Better suggestions are welcome

The following is untested.

 add_action('set_object_terms','wpse61678_terms_changed',10,6);

 function wpse61678_terms_changed($object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids){

      //Note problem 1 - we might not necessarily know what $object_id refers to. 

     //Added terms are specified terms, that did not already exist
     $added_tt_ids = array_diff($tt_ids, $old_tt_ids);

     if( $append ){
         //If appending terms - nothing was removed
         $removed_tt_ids = array();
     }else{
         //Removed terms will be old terms, that were not specified in $tt_ids
         $removed_tt_ids = array_diff($old_tt_ids, $tt_ids);
     }

    /*Note problem 2, we would preferably like the term objects / IDs, 
      Currently we have the taxonomy term IDs*/

    //Get all terms
    $all_terms = get_terms( $taxonomy, array('hide_empty'=>0));

    $removed_terms =array()
    $added_terms =array();
    foreach( $all_terms as $term ){
         $tt_id = (int) $term->term_taxonomy_id;
         if( in_array( $tt_id, $removed_tt_ids) ){
             $removed_terms[] = $term;
         }elseif( in_array( $tt_id, $added_tt_ids) ){
             $added_terms[] = $term;
         }
    }

    //$added_terms contains added term objects
    //$removed_terms contains removed term objects


 }