Automatically Assign Parent Terms When A Child Term is Selected

I have deep hierarchical taxonomy and I want to have all parent term assigned when I select a child term. I need it for category structure on a online listing/classified site.

CPT name: product

Taxonomy Name: product_cat

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Hooking into save_post action.

add_action('save_post', 'assign_parent_terms', 10, 2);

function assign_parent_terms($post_id, $post){

    if($post->post_type != 'product')
        return $post_id;

    // get all assigned terms   
    $terms = wp_get_post_terms($post_id, 'product_cat' );
    foreach($terms as $term){
        while($term->parent != 0 && !has_term( $term->parent, 'product_cat', $post )){
            // move upward until we get to 0 level terms
            wp_set_post_terms($post_id, array($term->parent), 'product_cat', true);
            $term = get_term($term->parent, 'product_cat');
        }
    }
}

While loop ensures we go upward until we hit top level terms.

Method 2

The options above should work, this function will work for any object whenever terms are set, and using set_object_terms allows you to let the action handle traversing up the hierarchy

add_action( 'set_object_terms', 'auto_set_parent_terms', 9999, 6 );

/**
 * Automatically set/assign parent taxonomy terms to posts
 * 
 * This function will automatically set parent taxonomy terms whenever terms are set on a post,
 * with the option to configure specific post types, and/or taxonomies.
 *
 *
 * @param int    $object_id  Object ID.
 * @param array  $terms      An array of object terms.
 * @param array  $tt_ids     An array of term taxonomy IDs.
 * @param string $taxonomy   Taxonomy slug.
 * @param bool   $append     Whether to append new terms to the old terms.
 * @param array  $old_tt_ids Old array of term taxonomy IDs.
 */
function auto_set_parent_terms( $object_id, $terms, $tt_ids, $taxonomy, $append, $old_tt_ids ) {

    /**
     * We only want to move forward if there are taxonomies to set
     */
    if( empty( $tt_ids ) ) return FALSE;

    /**
     * Set specific post types to only set parents on.  Set $post_types = FALSE to set parents for ALL post types.
     */
    $post_types = array( 'product' );
    if( $post_types !== FALSE && ! in_array( get_post_type( $object_id ), $post_types ) ) return FALSE;

    /**
     * Set specific taxonomy types to only set parents on.  Set $tax_types = FALSE to set parents for ALL taxonomies of this post types.
     */
    $tax_types = array( 'product_cat' );
    if( $tax_types !== FALSE && ! in_array( get_post_type( $object_id ), $post_types ) ) return FALSE;

    foreach( $tt_ids as $tt_id ) {

        $parent = wp_get_term_taxonomy_parent_id( $tt_id, $taxonomy );

        if( $parent ) {
            wp_set_post_terms( $object_id, array($parent), $taxonomy, TRUE );
        }

    }

}

This gist will have any updates or patches if I add them later:
https://gist.github.com/tripflex/65dbffc4342cf7077e49d641462b46ad

Method 3

The code has some bugs as provided above. Use the following code to also make in working in the quick edit modus: How to hook into the quick edit action? (provided by Pieter Goosen)

add_action('save_post', 'assign_parent_terms');

function assign_parent_terms($post_id){
global $post;

if(isset($post) && $post->post_type != 'product')
return $post_id;

// get all assigned terms   
$terms = wp_get_post_terms($post_id, 'product_cat' );
foreach($terms as $term){
while($term->parent != 0 && !has_term( $term->parent, 'product_cat', $post )){
    // move upward until we get to 0 level terms
    wp_set_object_terms($post_id, array($term->parent), 'product_cat', true);
    $term = get_term($term->parent, 'product_cat');
     }
  }
}

Method 4

Improved! Thks @Sisir

Now, you can define more than one post type and term.

You can define Allowed Post Types in ($arrayPostTypeAllowed) array, and Allowed Terms in ($arrayTermsAllowed) array.

add_action('save_post', 'assign_parent_terms', 10, 2);

function assign_parent_terms($post_id, $post){
    $arrayPostTypeAllowed = array('product');
    $arrayTermsAllowed = array('product_cat');

    //Check post type
    if(!in_array($post->post_type, $arrayPostTypeAllowed)){
        return $post_id;
    }else{

        // get all assigned terms   
        foreach($arrayTermsAllowed AS $t_name){
            $terms = wp_get_post_terms($post_id, $t_name );

            foreach($terms as $term){

                while($term->parent != 0 && !has_term( $term->parent, $t_name, $post )){

                    // move upward until we get to 0 level terms
                    wp_set_post_terms($post_id, array($term->parent), $t_name, true);
                    $term = get_term($term->parent, $t_name);
                }
            }
        }
    }
}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x