Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add parent name to term list in dropdown (eg. coupon category list)

We have a WooCommerce clothing store and want to create coupons that have certain categories excluded. Our category structure is as follows (simplified):

– Men
– – Shirts
– – Jeans
– – Sale
– Women
– – Shirts
– – Jeans
– – Sale

However when we want to select [Men » Sale] from the Exclude categories dropdown picker in [WooCommerce » Marketing » Coupons » Usage Restriction] the list is flattened:

– Jeans
– Men
– Sale
– Sale
– Shirts
– Shirts
– Women

Now it is not clear which categories are actually the one we want to exclude. Have in min, this is a very simplified structure, in the live environment this is even worse.

I hoped for an apply_filter but the get_terms() apparently does have none in code, see source code on github here » (line #233)

$categories = get_terms('product_cat', 'orderby=name&hide_empty=0');

Since this is not filtered, I don’t see a way to add a parent category to have this as the desired outcome:

- Men
- Men » Jeans
- Men » Shirts
- Men » Sale
- Women
- Women » Jeans
- Women » Shirts
- Women » Sale

Any idea how to get that list now that there is no filter in the code?

For example, this is what we use for a third party plugin that also uses the WooCommerce category terms, but that actually does have a filter on the get_terms and the native WooCommerce code on coupons does not...

Example:

if (!function_exists('yith_wcbep_add_parent_category_name')) {
    function yith_wcbep_add_parent_category_name($terms, $args) {
        $term_name = '';
        $taxonomy  = isset($args['taxonomy']) ? $args['taxonomy'] : '';
        foreach ($terms as $term_id => $term_name) {
            $term = get_term_by('id', $term_id, $taxonomy);
            $term_name = isset($term->name) ? $term->name : '';
            if (isset($term->parent) && $term->parent > 0) {
                $parent = get_term_by('id', $term->parent, $term->taxonomy);
                $term_name = $parent->name . ' > ' . $term_name;
                $terms[$term_id] = $term_name;
            }
        }
        return $terms;
    }
    add_filter('yith_plugin_fw_json_search_found_terms', 'yith_wcbep_add_parent_category_name', 10, 2);
}
like image 907
Ronaldt Avatar asked Oct 16 '25 19:10

Ronaldt


2 Answers

To solve this issue, what you can do is to clone WooCommerce coupon product categories restrictions section, customizing the categories output as you like *(here I add the parent term name to the category name), removing with JavaScript the related HTML output from the default WooCommerce ones.

So you will get the following:

enter image description here

Here is the hooked function code:

// Prepend the parent term name to the term name output
function prepend_parent_term_name( $term, $sep = ' > ' ) {
    if (isset($term->parent) && $term->parent > 0) {
        $parent_name = get_term_by('id', $term->parent, $term->taxonomy)->name;
        return esc_html( $parent_name ) . $sep . esc_html( $term->name );
    } else {
        return esc_html( $term->name );
    }
}

// Replace WooCommerce Admin Coupon product categories restictions section with a custom one
add_action( 'woocommerce_coupon_options_usage_restriction', 'action_coupon_options_usage_restriction', 10, 2 );
function action_coupon_options_usage_restriction( $coupon_id, $coupon ) {
    echo '<div class="options_group">';

    // Categories.
    ?>
    <p class="form-field">
        <label for="product_categories2"><?php _e( 'Product categories', 'woocommerce' ); ?></label>
        <select id="product_categories2" name="product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'Any category', 'woocommerce' ); ?>">
            <?php
            $category_ids = $coupon->get_product_categories( 'edit' );
            $categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );

            if ( $categories ) {
                foreach ( $categories as $cat ) {
                    echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . prepend_parent_term_name( $cat ) . '</option>';
                }
            }
            ?>
        </select> <?php echo wc_help_tip( __( 'Product categories that the coupon will be applied to, or that need to be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
    </p>

    <?php // Exclude Categories. ?>
    <p class="form-field">
        <label for="exclude_product_categories2"><?php _e( 'Exclude categories', 'woocommerce' ); ?></label>
        <select id="exclude_product_categories2" name="exclude_product_categories[]" style="width: 50%;"  class="wc-enhanced-select" multiple="multiple" data-placeholder="<?php esc_attr_e( 'No categories', 'woocommerce' ); ?>">
            <?php
            $category_ids = $coupon->get_excluded_product_categories( 'edit' );
            $categories   = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );

            if ( $categories ) {
                foreach ( $categories as $cat ) {
                    echo '<option value="' . esc_attr( $cat->term_id ) . '"' . wc_selected( $cat->term_id, $category_ids ) . '>' . prepend_parent_term_name( $cat ) . '</option>';
                }
            }
            ?>
        </select>
        <?php echo wc_help_tip( __( 'Product categories that the coupon will not be applied to, or that cannot be in the cart in order for the "Fixed cart discount" to be applied.', 'woocommerce' ) ); ?>
    </p>
    <?php // Removing default product categories restrictions html  ?>
    <script>
    jQuery(function($){
        $('#product_categories').parent().parent().remove();
    });
    </script>
    <?php 
    echo '</div>';
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.

like image 52
LoicTheAztec Avatar answered Oct 18 '25 13:10

LoicTheAztec


This was an interesting feature to solve, seems kind of strange Woocommerce doesn't have hierarchy names in the coupons categories.
So I did some digging and found that the only appropriate filter seems to be get_terms, after some trial and error I came up with this.

if (!function_exists('btAddHierarchyNameToCouponsCat')) {
    function btAddHierarchyNameToCouponsCat($terms)
    {
        if (!is_admin()) {
            return $terms;
        }
    
        global $pagenow;
    
        if ($pagenow !== 'post-new.php' && $pagenow !== 'post.php') {
            return $terms;
        }
    
        if (
            (
                !empty($_GET['post_type'])
                && $_GET['post_type'] === 'shop_coupon'
            )
            || (
                !empty($_GET['post'])
                && get_post_type($_GET['post']) === 'shop_coupon'
                && !empty($_GET['action'])
                && $_GET['action'] === 'edit'
            )
        ) {
            foreach ($terms as &$term) {
                $term->name = (function ($term) {
                    $fullName = array_map(function ($ancestorId) {
                        $ancestor = get_term_by('term_id', $ancestorId, 'product_cat');
    
                        return $ancestor->name;
                    }, array_reverse(get_ancestors($term->term_id, 'product_cat')));
    
                    $fullName[] = $term->name;
    
                    return implode(' -> ', $fullName);
                })($term);
            }
    
            return $terms;
        }
    
        return $terms;
    }

    add_filter('get_terms', 'btAddHierarchyNameToCouponsCat');
}

Here is the before.

enter image description here

And here is the after.

enter image description here

The general idea of this filter is to specifically work only when creating or editing a coupon on the dashboard.
Then it updates the category name to contain the whole hierarchy of the categories names.
This might not be perfect but it's a starting point

like image 40
Buttered_Toast Avatar answered Oct 18 '25 11:10

Buttered_Toast



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!