Skip to content
Advertisement

Woocommerce: hide category in shop

I have a category with products not visible to everyone. I already have a script in place, that removes this category from the sidebar widget, when no items in the category are visible to the user.

I created a function that puts the exclude term_id in a global variable. Now I need something that excludes them from view in the shop.

    $GLOBALS['cat_exclude'] = NULL;

    function getExcludedCats(  ) {

        //if( ! is_admin() && (is_product_category() || is_shop())){    

            $current_tax = get_query_var( 'product_cat' );
            $term =get_term_by( 'slug', $current_tax, 'product_cat');
            $parentid = $term->term_id;

            $args = array(
                'hide_empty' => true,
                'parent' => $parentid
            );  

            $product_categories = get_terms( 'product_cat', $args );

            $exclude = array();
            foreach ( $product_categories as $category ) {

                $posts         = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $category->slug, 'fields' => 'ids' ) );
                $show_category = false;

                foreach ( $posts as $post ) {

                    $product         = new WC_Product( $post );
                    $visible_product = $product->is_visible();

                    if ( true === $visible_product ) {
                        $show_category = true;
                        break;
                    }

                }

                if ( false === $show_category ) {
                    $exclude[] = $category->term_id;
                }

            }

            if ( ! empty( $exclude ) ) {
                $GLOBALS['cat_exclude'] = implode( ',', $exclude );
            }
        //}
    }

    add_action('wp_head', 'getExcludedCats');

However, in the shop view itself, the category is still visible. How can I remove it there, when no items in this category are visible to the user.

I have tried: https://gist.github.com/rynaldos/a9d357b1e3791afd9bea48833ff95994 But it removes the category ALWAYS, in both widget and shop.

Products are being displayed by group membership of the customer: https://wordpress.org/plugins/groups/

Advertisement

Answer

I think I managed to create a script that made this possible: https://gist.github.com/DarkAllMan/cffb114eb97c6f26882e54793e023587

    <?php
    /**
    Plugin Name: WooCommerce - Hide categories where no products are visible to user
    Plugin URI: https://www.randall.nl
    Description: Excludes categories with no visible products from the WooCommerce category overview in shop
    Version: 0.1
    Author: Randall Kam
    Author URI: https://www.randall.nl
    */

    if ( ! defined( 'ABSPATH' ) ) {
        exit; // Exit if accessed directly
    }

    if ( !class_exists( 'ExcludeCats' ) ) :

    class ExcludeCats {

        public $version = '0.1',
               $exclude = array();

        protected static $_instance = null;

        /**
         * Main Plugin Instance
         *
         * Ensures only one instance of plugin is loaded or can be loaded.
         */
        public static function instance() {
            if ( is_null( self::$_instance ) ) {
                self::$_instance = new self();
            }
            return self::$_instance;
        }

        /**
         * Constructor
         */
        public function __construct() {
            // CHECK CATEGORIES FOR VISIBLE PRODUCTS
            add_action('wp_head', array( $this, 'get_excluded_cats' ), 10, 3 );

            // ADD THE WIDGET SIDEBAR FILTER
            add_filter( 'woocommerce_product_categories_widget_args', array( $this, 'kfg_exclude_categories_from_widget'), 10, 1 );

            // ADD THE SHOP FILTER
            add_filter( 'woocommerce_product_subcategories_args', array( $this, 'filter_woocommerce_product_subcategories_args'), 10, 1 ); 
        }

        // GET CATEGORIES WITH NO VISIBLE PRODUCTS AND PUT IN GLOBAL IF GLOBAL FALSE
        public function get_excluded_cats( $terms, $taxonomies, $args ) {

            $current_tax = get_query_var( 'product_cat' );
            $term =get_term_by( 'slug', $current_tax, 'product_cat');
            $term_id = $term->term_id;

            $args = array(
                'parent' => $term_id,
                'hide_empty' => false,
                'hierarchical' => false,
            );

            $product_categories = get_terms( 'product_cat', $args );        

            // if a product category and on the shop page
            //if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() && is_shop() ) {
            if ( ! is_admin() && is_shop() ) {

                foreach ( $product_categories as $key => $term ) {

                    unset($this->exclude);

                    if($term->taxonomy=='product_cat'){

                        $posts         = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $term->slug, 'fields' => 'ids' ) );
                        $show_category = false;

                        foreach ( $posts as $post ) {

                            $product         = new WC_Product( $post );
                            $visible_product = $product->is_visible();

                            if ( true === $visible_product ) {
                                $show_category = true;
                                break;
                            }

                        }


                    }

                    if ( false === $show_category ) {
                        $this->exclude[] = $term->term_id;
                    }
                }
            }
        }   

        public function get_parent_cats ($cat_termid, $found = array()) {
            array_push ($found, $cat_termid);
            $term =get_term_by( 'term_id', $cat_termid, 'product_cat');

            if($term->parent > 0){
                return get_parent_cats($term->parent, $found);
            }
            return $found;
        }   

        // ADD FILTERS FOR CATEGORIES AND EXCLUDE EMPTY
        public function filter_woocommerce_product_subcategories_args( $temp_args = array() ) { 

            $current_tax = get_query_var( 'product_cat' );
            $term =get_term_by( 'slug', $current_tax, 'product_cat');
            $term_id = $term->term_id;

            $temp_args = array(
                'parent'       => $term_id,
                'menu_order'   => 'ASC',
                'hide_empty'   => 1,
                'hierarchical' => 1,
                'taxonomy'     => 'product_cat',
                'pad_counts'   => 1,
                'include'       => NULl,
                'exclude'       => $this->exclude,
            );

            return $temp_args; 
        }

        public function kfg_exclude_categories_from_widget( $category_list_args ) {

            $current_tax    = get_query_var( 'product_cat' );
            $term           = get_term_by( 'slug', $current_tax, 'product_cat');
            $term_id        = $term->term_id;

            $parents = $this->get_parent_cats($term_id);

            $args = array(
                'hide_empty' => false,
                'hierarchical' => true,
            );

            $product_categories = get_terms( 'product_cat', $args );
            $wexclude = array();

            foreach ( $product_categories as $category ) {
                $posts         = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $category->slug, 'fields' => 'ids' ) );
                $show_category = false;
                foreach ( $posts as $post ) {
                    $product         = new wC_Product( $post );
                    $visible_product = $product->is_visible();
                    if ( true === $visible_product ) {
                        $show_category = true;
                        break;
                    }
                }
                if ( false === $show_category || ( $category->parent > 0 && !in_array($category->parent,$parents) ) ) {
                    $wexclude[] = $category->term_id;
                }
            }
            if ( ! empty( $wexclude ) ) {
                $category_list_args['exclude'] = implode( ',', $wexclude );
                unset( $category_list_args['include'] );
            }
            return $category_list_args;
        }   

    } // class ExcludeCats

    endif; // class_exists

    /**
     * Returns the main instance of the plugin class to prevent the need to use globals.
     *
     * @since  2.0
     * @return WooCommerce_PostcodeAPInu
     */
    function ExcludeCats() {
        return ExcludeCats::instance();
    }

    ExcludeCats(); // load plugin
User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement