I want to change the WooCommerce product description tab button and title "Description" into "Tracklist" when the page has a body class of "parent-product_cat-vinyl".
Here is my code so far:
<?php
if ( is_singular() ) {
$classes = get_body_class();
if (in_array('parent-product_cat-vinyl',$classes)) {
add_filter( 'woocommerce_product_description_tab_title','ps_rename_description_product_tab_label');
function ps_rename_description_product_tab_label() {
return 'Tracklist';
}
}
}
But it doesn't seem to work.
You can use the following composite filter hooks (where $tab_key is in your case description):
woocommerce_product_{$tab_key}_tab_title
woocommerce_product_{$tab_key}_heading
It can be done in 2 ways:
Conditionally with a defined body class:
add_filter( 'woocommerce_product_description_tab_title', 'change_product_description_tab_text' );
add_filter( 'woocommerce_product_description_heading', 'change_product_description_tab_text' );
function change_product_description_tab_text( $title ) {
global $product;
if( in_array( 'parent-product_cat-vinyl', get_body_class() ) ) {
return __('Tracklist', 'woocommerce');
}
return $title;
}
Or conditionally for a product category (including parent product categories):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_filter( 'woocommerce_product_description_tab_title', 'change_product_description_tab_text' );
add_filter( 'woocommerce_product_description_heading', 'change_product_description_tab_text' );
function change_product_description_tab_text( $title ) {
global $product;
// Here set in the array the targeted product categories
$categories = array('Vinyl');
if ( has_product_categories( $categories, $product->get_id() ) ) {
return __('Tracklist', 'woocommerce');
}
return $title;
}
Code goes in functions.php file of your active child theme (or active theme) . Tested and works.
Related
In my WooCommerce store I want to restrict and show payment gateway(cheque) only if the product has particular product category with the category ID "266". Now I have this snippet but it does the opposite - it disabled the gateway on the checkout for particular product category:
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_unset_gateway_by_category' );
function bbloomer_unset_gateway_by_category( $available_gateways ) {
if ( is_admin() ) return $available_gateways;
if ( ! is_checkout() ) return $available_gateways;
$unset = false;
$category_ids = array( 8, 37 );
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
$terms = get_the_terms( $values['product_id'], 'product_cat' );
foreach ( $terms as $term ) {
if ( in_array( $term->term_id, $category_ids ) ) {
$unset = true;
break;
}
}
}
if ( $unset == true ) unset( $available_gateways['cheque'] );
return $available_gateways;
}
Using has_term() WordPress conditional function that will simplify the code making it more effective, this way:
add_filter( 'woocommerce_available_payment_gateways', 'filter_available_payment_gateways' );
function filter_available_payment_gateways( $available_gateways ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) {
// Here define your product categories
$product_categories = array( 't-shirts', 'posters' ); // Can be term names, term slugs or term ids
$taxonomy = 'product_cat'; // For WooCommerce product category terms (or 'product_tag' for WooCommerce product tag terms)
$payment_method = 'cheque'; // Here define your payment method id to be removed
$hide_payment = false;
// Loop through cart items
foreach ( WC()->cart->get_cart_contents() as $item ) {
if ( ! has_term( $product_categories, $taxonomy, $item['product_id'] ) ) {
$hide_payment = true;
}
}
if ( $hide_payment ) {
unset( $available_gateways[$payment_method] );
}
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Handling product tags instead
Simply replace in the code the taxonomy 'product_cat' by 'product_tag'.
Targeting parent product category too
If you need to target the parent product categories too, you will have to use this instead:
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_available_payment_gateways' );
function filter_available_payment_gateways( $available_gateways ) {
// Only on checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) {
// Here define your product categories
$product_categories = array( 't-shirts', 'posters' ); // Can be term names, term slugs or term ids
$taxonomy = 'product_cat'; // For WooCommerce product category terms (or 'product_tag' for WooCommerce product tag terms)
$payment_method = 'cheque'; // Here define your payment method id to be removed
$hide_payment = false;
// Loop through cart items
foreach ( WC()->cart->get_cart_contents() as $item ) {
if ( ! has_product_categories( $product_categories, $item['product_id'] ) ) {
$hide_payment = true;
}
}
if ( $hide_payment ) {
unset( $available_gateways[$payment_method] );
}
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
can you change your condition in your code
if ( $unset == true ){
$index = 0;
foreach($available_gateways as $single){
if($single != "cheque"){
unset($available_gateways[$index]);
}
$index++;
}
}
I'm trying to make a condition, where a function displays on WooCommerce checkout page only, if any product from category ilutulestik is present in the shopping cart.
Currently, however, it does not seem to be able to obtain cart info. I assume that because, if I use if ( $cat_in_cart ) condition on a code, the function I use it on, does not display, even if I have a product from ilutulestik category present in the shopping cart.
I've tried many different methods to obtain cart info, but none have seemed to work. I'll include 2 ways of how I tried below:
Try 1
add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');
function kontrollime_ilutulestiku_olemasolu()
{
global $woocommerce;
$cat_in_cart = false;
foreach ( WC()->cart->get_cart() as $cart_item_key => $values )
{
$item = $values['data'];
$item_id = $item->id;
if ( has_term( 'ilutulestik-2', 'product_cat', $item_id ) )
{
$cat_in_cart = true;
break;
}
}
}
Try 2
add_action('woocommerce_before_cart', 'kontrollime_ilutulestiku_olemasolu');
function kontrollime_ilutulestiku_olemasolu($package)
{
global $woocommerce;
$cat_in_cart = false;
foreach ($package['contents'] as $product)
{
// get product categories
$product_cats = wp_get_post_terms(
$product['product_id'], 'product_cat', array('fields' => 'names') );
// if it has category_name unset flat rate
if( in_array('ilutulestik-2', $product_cats) )
{
$cat_in_cart = true;
break;
}
}
}
I expect this piece of code to check if there is a product in cart that belongs to category Ilutulestik (or slug ilutulestik-2) and if it does, change $cat_in_cart value to true, so later I could activate any code with if ( $cat_in_cart ).
The correct way for cart items to be used with product categories is:
add_action('woocommerce_before_cart', 'action_before_cart');
function action_before_cart() {
$categories = array('ilutulestik-2');
$has_category = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Check for product categories
if ( has_term( $categories, 'product_cat', $cart_item['product_id'] ) ) {
$has_category = true;
break;
}
}
// Testing output (display a notice)
if ( $has_category ) {
wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If you need to check also for parent terms with product categories, you will use instead:
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_action('woocommerce_before_cart', 'action_before_cart');
function action_before_cart() {
$categories = array('ilutulestik-2');
$has_category = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Check for product categories
if ( has_product_categories( $cart_item['product_id'], $categories ) ) {
$has_category = true;
break;
}
}
// Testing output (display a notice)
if ( $has_category ) {
wc_print_notice( sprintf( 'Product category "%s" is in cart!', reset($categories)), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
In woocommerce I am using Hide “remove item” from cart for WooCommerce product category answer code and I would like to disable the cart quantity field too, avoiding customer to change the item quantity to zero.
Is that possible? Any track on this will be appreciated.
The following code will remove the "quantity field" from cart for items from a specific product category (that you will define in the 2nd function):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
add_filter( 'woocommerce_quantity_input_args', 'hide_cart_quantity_input_field', 20, 2 );
function hide_cart_quantity_input_field( $args, $product ) {
// HERE your specific products categories
$categories = array( 'clothing' );
// Handling product variation
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
// Only on cart page for a specific product category
if( is_cart() && has_product_categories( $product_id, $categories ) ){
$input_value = $args['input_value'];
$args['min_value'] = $args['max_value'] = $input_value;
}
return $args;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Note: If you are using also your other answer code, the first function is already defined and doesn"t have to be twice on your function php file…
I would like to Hide "remove item" from cart for a specific product category in WooCommerce, just like in "Hide "remove item" from cart for a specific product in WooCommerce" answer thread, but for a specific product category.
Any help would be appreciated.
The following code will hide "remove item" from cart for a specific product category (that you will define in the 2nd function):
// Custom conditional function that handle parent product categories too
function has_product_categories( $categories, $product_id = 0 ) {
$parent_term_ids = $categories_ids = array(); // Initializing
$taxonomy = 'product_cat';
$product_id = $product_id == 0 ? get_the_id() : $product_id;
if( is_string( $categories ) ) {
$categories = (array) $categories; // Convert string to array
}
// Convert categories term names and slugs to categories term ids
foreach ( $categories as $category ){
$result = (array) term_exists( $category, $taxonomy );
if ( ! empty( $result ) ) {
$categories_ids[] = reset($result);
}
}
// Loop through the current product category terms to get only parent main category term
foreach( get_the_terms( $product_id, $taxonomy ) as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
$parent_term_ids[] = $term->term_id; // (and the child)
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, array_unique($parent_term_ids) ) ? true : false;
}
// Hiding "remove item" for specific product category
add_filter('woocommerce_cart_item_remove_link', 'filter_cart_item_remove_link', 20, 2 );
function filter_cart_item_remove_link( $button_link, $cart_item_key ){
// HERE your specific products categories
$categories = array( 'clothing' );
// Get the current cart item
$cart_item = WC()->cart->get_cart()[$cart_item_key];
// If the targeted product is in cart we remove the button link
if( has_product_categories( $cart_item['product_id'], $categories ) )
$button_link = '';
return $button_link;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
The below code will work as you want it : just change the category id in if clause:
function tristup_woocommerce_cart_item_remove_link($link){
preg_match('/data-product_id=\"(.*?)\"/', $link, $matches);
$flag=0;
if($matches)
{
$product_id=$matches[1];
$terms = get_the_terms ( $product_id, 'product_cat' );
foreach ( $terms as $term )
{
if($term->term_id=='210') // change with your category id or add more with in proper syntaxes
{
return '';
}
}
}
return $link;
}
add_filter('woocommerce_cart_item_remove_link', 'tristup_woocommerce_cart_item_remove_link');
With woocommerce, I used some code based on my previous thread: Allow backorders and notify customer for specific product categories in Woocommerce
add_filter( 'woocommerce_product_is_in_stock', 'filter_product_is_in_stock', 10, 2 );
function filter_product_is_in_stock( $is_in_stock, $product ){
// Here set the products categories in the array (can be terms ids, slugs or names)
$categories = array("clothing");
if( has_term( $categories, 'product_cat', $product->get_id() ) ){
$is_in_stock = true;
}
return $is_in_stock;
}
add_filter( 'woocommerce_product_backorders_allowed', 'filter_products_backorders_allowed', 10, 3 );
function filter_products_backorders_allowed( $backorder_allowed, $product_id, $product ){
// Here set the products categories in the array (can be terms ids, slugs or names)
$categories = array("clothing");
if( has_term( $categories, 'product_cat', $product_id ) ){
$backorder_allowed = true;
}
return $backorder_allowed;
}
add_filter( 'woocommerce_product_backorders_require_notification', 'filter_product_backorders_require_notification', 10, 2 );
function filter_product_backorders_require_notification( $notify, $product ){
// Here set the products categories in the array (can be terms ids, slugs or names)
$categories = array("clothing");
if( has_term( $categories, 'product_cat', $product->get_id() ) ){
$notify = true;
}
return $notify;
}
But it seems to be not working when I used the root product categories.
How can I get the root product categories in the if statements of the code?
Update 2 - 2018 Nov 17th (removed a bug and cleaned a bit)
To make it work for the parent categories, we add a custom conditional function that checks for parent product categories (where you will define your targeted parent product categories):
// Custom conditional function that checks for parent product categories
function has_parent_terms( $product_id ) {
// HERE define the parent products categories SLUGS in the array
$categories = array("clothing", "posters");
$parent_term_ids = $categories_ids = array(); // Initializing
// Convert categories term slugs to categories term ids
foreach ( $categories as $category ){
$categories_ids[] = get_term_by('slug', $category, 'product_cat')->term_id;
}
$terms = get_the_terms( $product_id, 'product_cat' );
if( ! $terms ) return false; // Check that is not empty
// Loop through the current product category terms to get only parent main category term
foreach( $terms as $term ){
if( $term->parent > 0 ){
$parent_term_ids[] = $term->parent; // Set the parent product category
} else {
$parent_term_ids[] = $term->term_id; // It is the Main category term and we set it.
}
}
return array_intersect( $categories_ids, $parent_term_ids ) ? true : false;
}
add_filter( 'woocommerce_product_is_in_stock', 'filter_product_is_in_stock', 10, 2 );
function filter_product_is_in_stock( $is_in_stock, $product ){
// For product variations
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
if( has_parent_terms( $product->get_id() ) ){
$is_in_stock = true;
}
return $is_in_stock;
}
add_filter( 'woocommerce_product_backorders_allowed', 'filter_products_backorders_allowed', 10, 3 );
function filter_products_backorders_allowed( $backorder_allowed, $product_id, $product ){
// For product variations
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product_id;
if( has_parent_terms( $product_id ) ){
$backorder_allowed = true;
}
return $backorder_allowed;
}
add_filter( 'woocommerce_product_backorders_require_notification', 'filter_product_backorders_require_notification', 10, 2 );
function filter_product_backorders_require_notification( $notify, $product ){
// For product variations
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
if( has_parent_terms( $product->get_id() ) ){
$notify = true;
}
return $notify;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Related: Allow backorders and notify customer for specific product categories in Woocommerce