Reputation: 37
I have checked from Woocommerce--> Inventory the option to hide "out of stock" products from my eshop. Now, i am trying to find out how i can hide a category from category list menu widget that has only out of stock products. Any idea? Thanks in advance. i use iks menu plugin.
I tried
function exclude_categories( $category_list_args ) {
$args = array(
'hide_empty' => false,
'hierarchical' => true,
);
$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 ) ) {
$category_list_args['exclude'] = implode( ',', $exclude );
unset( $category_list_args['include'] );
}
return $category_list_args;
}
add_filter( 'woocommerce_product_categories_widget_args', 'exclude_categories', 10, 1 );
Which hook should i use instead of woocommerce_product_categories_widget_args ? I use iks menus plugin to show on accordion the list of products categories. The code above works on Woocommerce Product Categories Widget but not on iks menu widget...
On iks menu plugin, the function that is responsible for showing the categories on widget sidebar is
private function get_WP_terms() {
$taxonomy = $this->get_taxonomy();
if ( $taxonomy ) {
$this->args = [
"taxonomy" => $taxonomy,
];
$this->save_args( [
"orderby",
"order",
"hide_empty",
"hierarchical",
"include",
"exclude",
"search",
"child_of",
"parent",
"childless",
] );
if ( version_compare( get_bloginfo( 'version' ), '4.5', '>=' ) ) {
$items = get_terms( $this->args );
} else {
$items = get_terms( $taxonomy, $this->args );
}
if ( is_array( $items ) ) {
if ( ! empty( $items ) ) {
$index = 0;
$show_posts = $this->settings_manager->get_value( "show_posts" );
/* Posts */
if ( $show_posts ) {
$post_type = Utils::get_post_type_by_taxonomy( $taxonomy );
$include = $this->settings_manager->get_value( "include" );
$has_include = ! empty( $include );
$posts = get_posts( [
'post_type' => $post_type,
'posts_per_page' => - 1,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => [
[
'taxonomy' => $taxonomy,
'operator' => $has_include ? 'IN' : 'EXISTS',
'terms' => $has_include ? Utils::get_terms_ids( $items ) : [],
]
],
'suppress_filters' => false // [Fix] WPML compatibility
] );
$posts_by_terms = [];
foreach ( $posts as $post ) {
$terms = get_the_terms( $post, $taxonomy );
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
if ( ! isset( $posts_by_terms[ $term->term_id ] ) ) {
$posts_by_terms[ $term->term_id ] = [];
}
$posts_by_terms[ $term->term_id ][] = $post;
}
}
}
}
foreach ( $items as $key => $item ) {
$id = (int) $item->term_id;
$link = get_term_link( $id );
$item_data = [
"id" => $id,
"title" => $item->name,
"link" => $link,
"parent" => (int) $item->parent,
"is_current" => $this->is_current_page_url( $link ) || $this->get_queried_object_term_id() === $id,
"is_term_includes_post" => $this->is_term_includes_post( $id, $this->get_taxonomy() ),
"is_page_includes_post" => false,
"index" => $index,
"is_expanded" => false,
"posts_count" => $item->count,
"is_post" => false,
"target" => null,
];
$index ++;
$this->data[] = $item_data;
if ( $show_posts ) {
if ( isset( $posts_by_terms[ $id ] ) ) {
$result_posts = $posts_by_terms[ $id ];
foreach ( $result_posts as $post ) {
$post_link = get_permalink( $post->ID );
$this->data[] = [
"id" => $post->ID,
"title" => $post->post_title,
"link" => $post_link,
"parent" => $id,
"is_current" => $this->is_current_page_url( $post_link ),
"is_term_includes_post" => false,
"is_page_includes_post" => false,
"index" => $index,
"is_expanded" => false,
"posts_count" => false,
"is_post" => true,
"target" => null,
];
$index ++;
}
}
}
}
}
i suppose that i need something like
'meta_query' => array(
array(
'key' => '_stock_status',
'value' => 'instock',
'compare' => '=',
)
)
but i am a little bit confused...
Upvotes: 0
Views: 1127
Reputation: 1913
The only way we can find the post count per category was by getting all categories (terms
) of product_cat
. Then we looped through them - each time calling my function get_count
and passing term_id
. In the get_count
we run a query to get all posts associated with it and we also pass post meta _stock_status = instock
. This return all products where the stock status is in stock. Then we return found_posts
attribute back - the IF statement then checks is the post count is bigger than 0.
The code (tested):
add_shortcode('test_test','test_test');
function test_test() {
$terms = get_terms('product_cat');
foreach($terms as $term) {
$post_count = get_count($term->term_id);
if($post_count > 0) {
echo $term->name . '<br>'; //This is where you put your category details
}
}
}
function get_count($cat_id) {
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => array($cat_id),
'include_children' => false
)
),
'posts_per_page' => -1,
'post_type' => 'product',
'post_status' => 'publish',
'meta_key' => '_stock_status',
'meta_value' => 'instock',
'meta_compare' => '='
);
$wp_query = new WP_Query($args);
wp_reset_postdata();
return $wp_query->found_posts;
}
Upvotes: 0