Auto add product categories to a predefined menu and update it when term is created or updated - woocommerce

I am struggling to combine some function found over here to auto create and update a predefined menu based on product categories.Also it should keep the parent-child relation based on product categories and should trigger every time a new product category is added or edited.
Bellow part of the code.
Many thanks in advance.
function create_product_category_menu() {
$menu_name = 'ProductCat';
$menu_exists = wp_get_nav_menu_object( $menu_name );
// If the menu doesn't exist, let's create it
if( !$menu_exists){
$menu_id = wp_create_nav_menu($menu_name);
} else {
$menu_id = $menu_exists->term_id;
}
// Get all product categories in hierarchy order
$product_categories = get_terms( array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
'orderby' => 'parent',
'order' => 'ASC'
) );
// Exclude specific product categories by ID
$exclude_ids = array(123, 456, 789);
// Create an empty array to store menu items
$menu_items = array();
// Loop through product categories and add them to the menu
function add_menu_items( $parent_id, $menu_items, $exclude_ids ) {
$child_categories = get_terms( array(
'taxonomy' => 'product_cat',
'hide_empty' => false,
'parent' => $parent_id
) );
foreach ( $child_categories as $child_category ) {
if ( ! in_array( $child_category->term_id, $exclude_ids ) ) {
$menu_items[$child_category->term_id] = array(
'menu-item-object-id' => $child_category->term_id,
'menu-item-object' => 'product_cat',
'menu-item-parent-id' => $parent_id,
'menu-item-type' => 'taxonomy',
'menu-item-status' => 'publish'
);
add_menu_items( $child_category->term_id, $menu_items, $exclude_ids );
}
}
return $menu_items;
}
$menu_items = add_menu_items( 0, $menu_items, $exclude_ids );
// add all menu items to the menu
foreach ( $menu_items as $menu_item ) {
wp_update_nav_menu_item( $menu_id, 0, $menu_item );
}
}
// Register the function to be called when a term is created or updated
add_action( 'created_term', 'create_product_category_menu', 10, 3 );
add_action( 'edited_term', 'create_product_category_menu', 10, 3 );

Related

Modify WooCommerce related products to display Cross-Sell items, then tag, then category

I want to change related products to display first Cross-Sell items, then same tag items, then same category items.
The code below is based on https://stackoverflow.com/questions/62293670/show-cross-sells-before-same-category-on-related-products-in-woocommerce.
$related_product_list = array();
function filter_woocommerce_related_products( $related_posts, $product_id, $args ) {
print_r($related_posts); echo " -- related_posts<br/>";
print_r($product_id); echo " -- product_id<br/>";
print_r($args); echo " -- args<br/>";
// Number of related products to show
$show_products = 4;
// Get product
$product = wc_get_product( $product_id );
// Get cross sell IDs
$cross_sell_ids = $product->get_cross_sell_ids();
print_r($cross_sell_ids); echo " -- cross_sell_ids<br/>";
// Calculate how many filler products are needed
$product_needed_count = $show_products - count( $cross_sell_ids );
// If additional product needed
if ( $product_needed_count >= 1 ) {
// Retrieves product term ids for a tag taxonomy.
$product_tag_ids = wc_get_product_term_ids( $product_id, 'product_tag' );
// Get product id(s) from a certain tag, by tag-id
print_r($product_tag_ids); echo " -- product_tag_ids<br/>";
$product_ids_from_tag_ids = get_posts( array(
'post_type' => 'product',
'numberposts' => $show_products + 1,
'post_status' => 'publish',
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_tag',
'field' => 'id',
'terms' => $product_tag_ids,
'operator' => 'IN',
)
),
));
print_r($product_ids_from_tag_ids); echo " -- product_ids_from_tag_ids<br/>";
// Retrieves product term ids for a cat taxonomy.
$product_cat_ids = wc_get_product_term_ids( $product_id, 'product_cat' );
print_r($product_cat_ids); echo " -- product_cat_ids<br/>";
// Get product id(s) from a certain tag, by cat-id
$product_ids_from_cat_ids = get_posts( array(
'post_type' => 'product',
'numberposts' => $show_products + 1,
'post_status' => 'publish',
'fields' => 'ids',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $product_cat_ids,
'operator' => 'IN',
)
),
));
print_r($product_ids_from_cat_ids); echo " -- product_ids_from_cat_ids<br/>";
// Merge array, removing duplicates
$related_posts = array_unique( array_merge( $cross_sell_ids, $product_ids_from_tag_ids, $product_ids_from_cat_ids ) );
// Remove current product
$related_posts = array_diff( $related_posts, array($product_id) );
// Reduce number of items to show products
$related_posts = array_slice( $related_posts, 0, $show_products );
print_r($related_posts); echo " -- related_posts<br/>";
} else {
// Slice array until show products
$related_posts = array_slice( $cross_sell_ids, 0, $show_products );
}
global $related_product_list;
$related_product_list = $related_posts;
// Return
return $related_posts;
}
add_filter( 'woocommerce_related_products', 'filter_woocommerce_related_products', 10, 3 );
// Order by
function filter_woocommerce_output_related_products_args( $args ) {
global $related_product_list;
print_r($related_product_list); echo " -- related_product_list<br/>";
$args['post__in'] = $related_product_list;
$args['orderby'] = 'post__in';
//print_r($args);
return $args;
}
add_filter( 'woocommerce_output_related_products_args', 'filter_woocommerce_output_related_products_args', 10, 1 );
It works well except that the order_by function is called before the product list is generated, so the order of related items is not respected.

Display Woocommerce Related Products By Custom Taxonomy

I want to display related products based on Custom taxonomy. Is there a way to force related products to be displayed based on Custom taxonomy?
add_filter( 'woocommerce_output_related_products_args', 'prfx_change_related_products_count' );
function prfx_change_related_products_count( $args ) {
// Current post as global
global $post;
$terms = get_the_terms( $post->ID, 'your_custom_taxonomy' );
// Empty array
$ids = array();
foreach ( $terms as $term ) {
array_push($ids, $term->term_id);
}
$args['tax_query'] = array(
array(
'taxonomy' => 'your_custom_taxonomy',
'terms' => $ids,
'field' => 'term_id',
'include_children' => true,
'operator' => 'IN'
)
);
return $args;
}

WooCommerce: disable AJAX reload on product page when selecting an attribute

in WooCommerce 4.2.0, when the user selects an attribute on the product page (i.e. product size), the AJAX reloads the "other products" in WooCommerce tabs. It's painful for the user to wait for this. How to disable this AJAX reload please ?
The code for the "other colors" tabs in my Storefront child-theme's functions.php:
/*ADD custom "other colors" tab */
add_filter( 'woocommerce_product_tabs', 'wpb_new_product_tab_othercolors' );
function wpb_new_product_tab_othercolors( $tabs ) {
// Add the new tab
global $post;
$othercolorsbool = get_post_meta( $post->ID, '_othercolorsbool', true );
// var_dump('$othercolorsbool :');
// var_dump($othercolorsbool);
if ( $othercolorsbool === "false" || $othercolorsbool === "" || $othercolorsbool === "0" ) {
unset( $tabs['othercolors_tab'] );
return $tabs;
} else {
if( get_locale() == 'fr_FR' ) {
$tabs['othercolors_tab'] = array(
'title' => __( 'AUTRES COULEURS', 'text-domain' ),
'priority' => 0,
'callback' => 'wpb_new_product_tab_content_othercolors'
);
} else {
$tabs['othercolors_tab'] = array(
'title' => __( 'OTHER COLORS', 'text-domain' ),
'priority' => 0,
'callback' => 'wpb_new_product_tab_content_othercolors'
);
}
return $tabs;
}
}
function wpb_new_product_tab_content_othercolors() {
global $post;
$title = $post->post_title;
$terms = get_the_terms( $post->ID, 'product_cat' );
foreach ($terms as $term) {
$product_cat_id = $term->term_id;
break;
}
$splitted = product_name_split($title);
$productname = $splitted[0];
$productcolor = $splitted[1];
$args = array(
'posts_per_page' => -1,
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $product_cat_id
),
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $product_cat_id
)
),
'post_type' => 'product',
'orderby' => 'title',
);
$the_query = new WP_Query( $args );
// The Loop
$r = 0;
while ( $the_query->have_posts() ) {
$r = $r + 1;
$the_query->the_post();
$currenttitle = get_the_title();
if ( strpos($currenttitle, $productname) !== false) { //if iteration product has the same name as the productname, then find its color: $productcolorbis
$splitted = product_name_split($currenttitle);
$productnamebis = $splitted[0];
$productcolorbis = $splitted[1];
if ( ($productcolorbis !== $productcolor) ) { //if iteration product color is different than productcolor, then go
wc_get_template_part( 'content', 'product' );
}
}
}
wp_reset_postdata();
}

How do i tempoarily add a product to a category - woocommerce

I have users who have specific products for each user, so i'm trying to add a "My Products" category, where each user can see their products
function my_products_cat( $q ) {
global $post, $wpmem;
$products = array();
$args = array(
'limit' => 100,
);
$products = wc_get_products( $args );
foreach($products as $product){
if(wpmem_user_has_access($product)){
$product->addToCategories("My Products");
}
}
}
add_action( 'woocommerce_before_shop_loop', 'my_products_cat' );
Note I'm using wp-members to add some of the functionality. And for some reason 'pre_get_posts' crashes my site
I basically need the functionality to be able to tempoarily add a product to the "My Products" category
EDIT
Current progress:
I got it to only show the available products for the user. Now i need it to only work when on page 945 (page with woocommerce [products] shortcode), or when "My Products" category is selected. Either would be fine
function custom_pre_get_posts_query( $q ) {
if(is_page(945)){
global $post, $wpmem;
$posts = array();
$ids = array();
$args = array('post_type' => 'product',
'posts_per_page' => '-1',);
$posts = get_posts($args);
foreach($posts as $postss){
$temppik = $wpmem->membership->get_post_products( $postss->ID );
if(!wpmem_user_has_access($temppik)){
array_push($ids, strval($postss->ID));
}
}
$tax_query = (array) $q->get( 'tax_query' );
$tax_query[] = array(
'taxonomy' => 'product_tag',
'field' => 'slug',
'terms' => $ids,
'operator' => 'NOT IN'
);
$q->set( 'tax_query', $tax_query );
}
}
add_action( 'woocommerce_product_query', 'custom_pre_get_posts_query' );

Querying posts from same categories / tags

I want to find all posts from same categories and same tags like a specific post in a plugin. So I do it actually separately by querying for tags and categories:
$taxonomy_arr = wp_get_post_tags( $this->post->ID, array( "fields" => "ids" ) );
add_filter( 'posts_where', array( $this, 'additional_filter' ) );
foreach ( $taxonomy_arr as $tag_id ) {
$posts_arr = get_posts( array(
'posts_per_page' => $this->max_results,
'tag_id' => (int) $tag_id,
'post_type' => array( $this->included_post_types ),
'orderby' => 'rand',
'suppress_filters' => false
) );
// add to categories selection
if ( is_array( $posts_arr ) ) {
foreach ( $posts_arr as $post_obj ) {
if ( is_object( $post_obj ) ) {
$local_taxonomy_selection[] = (int) $post_obj->ID;
}
}
}
}
// get post categories
$category_array = get_the_category( $this->post->ID );
foreach ( $category_array as $category ) {
$posts_arr = get_posts( array(
'posts_per_page' => $this->max_results*2,
'category' => $category->cat_ID,
'post_type' => array( $this->included_post_types ),
'orderby' => 'rand',
'suppress_filters' => false
));
// add to categories selection
if ( is_array( $posts_arr ) ) {
foreach ( $posts_arr as $post_obj ) {
if ( is_object( $post_obj ) ) {
$local_category_selection[] = (int) $post_obj->ID;
}
}
}
}
// combine post id's arrays
$all_posts = $local_taxonomy_selection + $local_category_selection;
It's working but is there a way to do it in one query?
This question already has answer on wordpress.stackexchange. So copying same code here.
https://wordpress.stackexchange.com/questions/4201/how-to-query-posts-by-category-and-tag
global $wp_query;
$args = array(
'category__and' => 'category',
'tag__in' => 'post_tag', //must use tag id for this field
'posts_per_page' => -1
$posts = get_posts($args);
foreach ($posts as $post) :
//do stuff
endforeach;

Resources