Woocommerce Conditional Product Tabs - php

Okay, I'm trying to show certain tab content depending on what category a product is listed in.
I have created a custom "Size Chart" tab and want to show for example:
Footwear size chart when product is in "Footwear" category
Clothing size chart when product is in "Clothing" category
No size chart when product is in "Accessories" category.
I've created a custom tab like this:
add_filter( 'woocommerce_product_tabs', 'woo_rename_tabs', 98 );
function woo_rename_tabs( $tabs ) {
$tabs['new_tab'] = array(
'title' => __( 'Size Chart', 'woocommerce' ),
'priority' => 55,
'callback' => 'woo_tab_content'
);
return $tabs;
}
Then added the custom tab content like this:
function woo_tab_content() {
echo 'This is the size chart';
}
Does anyone know how to add a conditional statement to this code to allow me to specify what content is displayed depending on what category a product is placed in i.e.
is_product_category( 'footwear' )
Thanks!

in you woo_tab_content function simple add what you have done above so it would like this this:
function woo_tab_content() {
if (is_product_category( 'footwear' )){
echo 'This is the size chart';
} else {
//do something else
}
}

Okay, I managed to fix it using the following code:
function woo_tab_content() {
global $post;
$terms = wp_get_post_terms( $post->ID, 'product_cat' );
foreach ( $terms as $term ) $categories[] = $term->slug;
if ( in_array( 'clothing', $categories ) ) {
echo 'this is the clothing tab content!';
} elseif ( in_array( 'shoes', $categories ) ) {
echo 'this is the shoes tab content!';
} else {
echo 'all other tabs';
}
}
It turns out that is_product_category does not work for the single product pages. Only for the category page itself.

Related

How to remove product categories from breadcrumb on WooCommerce product page

Please pardon me if there's a better way to do this as I am not very familiar with this code. I would like to display only the link to the homepage and the current product on the breadcrumb.
Desire result:
Currently:
I found the code for the breadcrumb, is there a way to only display the first and last crumb regardless of the hierarchy?
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key ) {
echo '' . esc_html( $crumb[0] ) . '';
} else if(!is_product() && !flatsome_option('wc_category_page_title')) {
echo esc_html( $crumb[0] );
}
echo $after;
// Single product or Active title
if(is_product() || flatsome_option('wc_category_page_title')){
$key = $key+1;
if ( sizeof( $breadcrumb ) > $key) {
echo ' <span class="divider">'.$delimiter.'</span> ';
}
} else{
// Category pages
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo ' <span class="divider">'.$delimiter.'</span> ';
}
}
}
The reason why I am doing this is that some of the products have multiple categories and by default, it will only show the breadcrumb for the primary category. I would rather make a truncated version as suggested by the owner.
I was also wondering if I can simply dynamically retrieve the product title and link + static homepage link, make it into a shortcode so that I can paste it in the product page.
Hi – the first example in the answer above, also removes the shop from woocommerce breadcrumb. Here is a working example, that only removes the category:
// remove only the category from woocommerce breadcrumbs
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
//print the array and look for the key with the category
//echo '<pre>';
//print_r($crumbs);
//echo '</pre>';
//unset($crumbs[2]); in my case it is key 2
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
} else {
unset($crumbs[2]); // this isn't enough, it would leave a trailing delimiter
$newBreadC = array_values($crumbs); //therefore create new array
return $newBreadC; //return the new array
}
}
If you want to remove categories and subcategories from product breadcrumbs on the product page you can use the woocommerce_get_breadcrumb hook.
// change the breadcrumb on the product page
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
}
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
return $new_crumbs;
}
The code has been tested and works. Add it to your active theme's functions.php.
A good alternative is to set the primary product category for each product. You can do this by installing the Yoast SEO plugin.
You can use the _yoast_wpseo_primary_product_cat product meta to set the id of the primary product category.
After setting the primary category id by editing the product in the
backend or importing a .csv file you will only need to change the
permalink and breadcrumbs based on the primary product category.
To update the product permalink:
// update the product permalink based on the primary product category
add_filter( 'wc_product_post_type_link_product_cat', 'change_product_permalink_by_cat', 10, 3 );
function change_product_permalink_by_cat( $term, $terms, $post ) {
// get the primary term as saved by Yoast
$primary_cat_id = get_post_meta( $post->ID, '_yoast_wpseo_primary_product_cat', true );
// if there is a primary and it's not currently chosen as primary
if ( $primary_cat_id && $term->term_id != $primary_cat_id ) {
// find the primary term in the term list
foreach ( $terms as $term_key => $term_object ) {
if ( $term_object->term_id == $primary_cat_id ) {
// return this as the primary term
$term = $terms[ $term_key ];
break;
}
}
}
return $term;
}
To update the product breadcrumbs on the product page:
// change the breadcrumb on the product page
add_filter( 'woocommerce_get_breadcrumb', 'custom_breadcrumb', 20, 2 );
function custom_breadcrumb( $crumbs, $breadcrumb ) {
// only on the single product page
if ( ! is_product() ) {
return $crumbs;
}
global $product;
$new_crumbs = array();
if ( $product->get_meta( '_yoast_wpseo_primary_product_cat', true ) ) {
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the id of the primary product category
$primary_cat_id = $product->get_meta( '_yoast_wpseo_primary_product_cat', true );
// create an array with all parent categories (based on the id of the primary product category)
$parent_categories = get_ancestors( $primary_cat_id, 'product_cat' );
$parent_categories = array_reverse($parent_categories);
$parent_categories[] = $primary_cat_id;
// for each product category it gets the name and the permalink
foreach ( $parent_categories as $cat_id ) {
$term = get_term_by( 'id', $cat_id, 'product_cat' );
$new_crumbs[] = array(
0 => $term->name,
1 => esc_url( get_term_link( $term, 'product_cat' ) )
);
}
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
} else {
// gets the first element of the array "$crumbs"
$new_crumbs[] = reset( $crumbs );
// gets the last element of the array "$crumbs"
$new_crumbs[] = end( $crumbs );
}
return $new_crumbs;
}
The code has been tested and works. Add it to your active theme's functions.php.

Hide all products with a specific stock status from WooCommerce catalog

I'm using Flatsome template on Wordpress and Woocommerce site. I also create custom stock status (example noproduzione, used when a product is not created anymore from manufacturer). But I don't want to show this products (noproduzione stock status) on my site (only in admin pages).
I'm using this code that I write here (I put it in my functions.php file), but it seems that on flatsome does not works. How to apply it on this template?
add_action( 'woocommerce_product_query', 'qc_action_product_query', 10, 2 );
function qc_action_product_query( $q, $query ) {
// Get any existing meta query
$meta_query = $q->get( 'meta_query');
// Define an additional meta query
$q->set( 'meta_query', array( array(
'key' => '_stock_status',
'value' => 'noproduzione',
'compare' => 'NOT LIKE',
) ) );
// Set the new merged meta query
$q->set( 'meta_query', $meta_query );
}
To create custom code I used some of codes found on StackOverflow
// Add new stock status options
add_filter( 'woocommerce_product_stock_status_options', 'filter_woocommerce_product_stock_status_options', 10, 1 );
function filter_woocommerce_product_stock_status_options( $status ) {
// Add new statuses
$status['10days'] = __( 'Disponibile entro 10 giorni', 'woocommerce' );
$status['inarrivo'] = __( 'In arrivo', 'woocommerce' );
$status['noproduzione'] = __( 'Fuori produzione', 'woocommerce' );
return $status;
}
// Availability text
add_filter( 'woocommerce_get_availability_text', 'filter_woocommerce_get_availability_text', 10, 2 );
function filter_woocommerce_get_availability_text( $availability, $product) {
switch( $product->get_stock_status() ) {
case '10days':
$availability = __( 'Disponibile entro 10 giorni', 'woocommerce' );
break;
case 'inarrivo':
$availability = __( 'In arrivo', 'woocommerce' );
break;
case 'noproduzione':
$availability = __( 'Fuori produzione', 'woocommerce' );
break;
}
return $availability;
}
I added code to show the text of availability, and also to hide the cart button if the product is noproduzione stock status
// Display the stock status on other page
add_action( 'woocommerce_after_shop_loop_item_title', 'wcs_stock_text_shop_page', 25 );
function wcs_stock_text_shop_page() {
//returns an array with 2 items availability and class for CSS
global $product;
$availability = $product->get_stock_status();
//check if availability in the array = string 'noproduzione'
//if so display on page.//if you want to display the 'in stock' messages as well just leave out this, == 'Out of stock'
if ( $product->get_stock_status() === 'noproduzione') {
echo '<span style="color:#b20000;">Fuori produzione!</span>';
}
else if ( $product->get_stock_status() === 'onbackorder') {
echo '<span style="color:#13b200;">Disponibile su ordinazione</span>';
}
else if ( $product->get_stock_status() === '10days') {
echo '<span style="color:#13b200;">Disponibile in 10 giorni</span>';
}
else if ( $product->get_stock_status() === 'inarrivo') {
echo '<span style="color:#e0c81d;">In arrivo</span>';
}
else if ( $product->get_stock_status() === 'outofstock') {
echo '<span style="color:#b20000;">Terminato!</span>';
}
else {
echo '<span style="color:#53af00;">Disponibile!</span>';
}
}
// Hide the cart button if stock status is 'noproduzione'
add_filter('woocommerce_is_purchasable', 'filter_is_purchasable_callback', 10, 2 );
add_filter('woocommerce_variation_is_purchasable', 'filter_is_purchasable_callback', 10, 2 );
function filter_is_purchasable_callback( $purchasable, $product ) {
if ( $product->get_stock_status() === 'noproduzione' ) {
return false;
}
return $purchasable;
}
Last, I also added this code, is useful because order the RELATED PRODUCT by "instock" status, and for me is good because do not show the other custom stock status. But I want to apply this to all of my frontend site.
//show, in the related products, only instock products!
add_filter( 'woocommerce_related_products', 'filter_woocommerce_related_products', 10, 3 );
function filter_woocommerce_related_products( $related_posts, $product_id, $args ) {
foreach( $related_posts as $key => $related_post ) {
// Get product
$related_product = wc_get_product( $related_post );
// Is a WC product
if ( is_a( $related_product, 'WC_Product' ) ) {
// Stock status
$stock_status = $related_product->get_stock_status();
// NOT instock
if ( $stock_status != 'instock' ) {
unset( $related_posts[$key] );
}
}
}
return $related_posts;
}
So, the question is: how to hide this products (noproduzione stock status) on my site (and show only in admin pages)? Noproduzione is different from OUTOFSTOCK!
You should better use dedicated woocommerce_product_query_meta_query filter hook as follows, to hide, from your store, all products that have a specific stock status (works with custom stock status):
add_action( 'woocommerce_product_query_meta_query', 'custom_product_query_meta_query', 1000 );
function custom_product_query_meta_query( $meta_query ) {
if ( ! is_admin() ) {
$meta_query[] = array(
'key' => '_stock_status',
'value' => 'noproduzione',
'compare' => '!=',
);
}
return $meta_query;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works on all versions since WooCommerce 3.

Check if current Download is in a specific category

So I'm working with the sinlge-download.php page and I'm trying to check if the specific product is in a specific category.
Here is what I tried but I only get the ELSE result even if the download is a book.
if( in_category( 'Books' ) ) {
echo 'This product is a book';
} else {
echo 'This product is not a book';
}
According to EDD docs, the category is: download_category Easy Digital Download Docs
For this... use function has_term since in_category refers to WordPress post type posts and not for custom post types like the downloads.
if( has_term( 'Books', 'download_category' ) ) {
echo 'This product is a book';
} else {
echo 'This product is not a book';
}
You can use this
if( has_term( $term = '', $taxonomy = '', $post = null ) ) {
// do something
}
// $term = Category OR Taxonomy name $taxonomy = Taxonomy Name. OR
// "category" if its default WP category $post = Post ID to check. Leave
// empty to pull this from global query
https://developer.wordpress.org/reference/functions/has_term/

Show Woocommerce product pages default description for empty descriptions

Is it possible to add Woocommerce Product Default Description for all new added product pages in the backend product description area as a default text for example ( free of charge ) or a default function which will generate a certain action but only for the products who doesn't have a product description value
All that is needed is to get the description have a default added value for the new added products in the description below
Can anyone help in this ?
I found this which do the magic but for the product short description, but i want it to the product description itself
add_action( 'woocommerce_single_product_summary', 'bbloomer_echo_short_desc_if_empty', 21 );
function bbloomer_echo_short_desc_if_empty() {
global $post;
if ( empty ( $post->post_excerpt ) ) {
$post_excerpt = '<p class="default-short-desc">';
$post_excerpt .= 'This is the default, global, short description.<br>It will show if <b>no short description has been entered!</b>';
$post_excerpt .= '</p>';
echo $post_excerpt;
}
}
function woocommerce_default_description($content) {
$empty = empty($content) || trim($content) === '';
if(is_product() && $empty) {
$content = 'default text content';
}
return $content;
}
add_filter( 'the_content', 'woocommerce_default_description' );
function rmg_woocommerce_default_product_tabs($tabs) {
if (empty($tabs['description'])) {
$tabs['description'] = array(
'title' => __( 'Description', 'woocommerce' ),
'priority' => 10,
'callback' => 'woocommerce_product_description_tab',
);
}
return $tabs;
}
add_filter( 'woocommerce_product_tabs', 'rmg_woocommerce_default_product_tabs' );
something like above should work.
Try this:
add_action( 'woocommerce_single_product_summary', 'bbloomer_echo_desc_if_empty', 21 );
function bbloomer_echo_desc_if_empty() {
global $post;
if ( empty ( $post->post_content ) ) {
$post_description = '<p class="default-content">';
$post_description .= 'This is the default, global, description.<br>It will show if <b>description has been entered!</b>';
$post_description .= '</p>';
echo $post_description;
}
}

Change back-order message for products with certain SKU's in WooCommerce

I would like to have a custom back-order message for certain WooCommerce products based on their ID, SKU or something else unique.
Right now I have this, and this works fine for all products that have back-order enabled, but what if I want this logic conditional for only certain product variations?
function backorder_text($availability) {
if($product->get_sku() == "111100"){
foreach($availability as $i) {
//$availability = str_replace('Available on backorder', 'Yo, allow 3-4 weeks for your shiz!', $availability);
$availability = str_replace('Beschikbaar via nabestelling', 'UITVERKOCHT (U kunt wel bestellen, maar de levertijd is 2-3 werkdagen).', $availability);
}
return $availability;
}
}
add_filter('woocommerce_get_availability', 'backorder_text');
if( $product->is_type( 'variable' ) ){
$available_variations = $product->get_available_variations()
foreach( $available_variations as $i => $variation ) {
//Do your code here by checking specific
}
}
This actually worked best for me:
function backorder_text_prikkabel_zonder_fittingen( $availability, $product ) {
$product_ids = array( 7631, 7631, 8612, 7629, 7628, 7627 );
if ( in_array( $product->get_id(), $product_ids ) ){
foreach( $availability as $i ) {
$availability = str_replace( 'Default back-order message', 'Your custom back-order message', $availability );
}
}
return $availability;
}
add_filter('woocommerce_get_availability', 'backorder_text_prikkabel_zonder_fittingen', 10, 2 );
Explanation: the array contains a list of product variation ID's. If you echo $product->get_id(), somewhere around the bottom of the page, you will see a list of ID's for each of the products variations for that product.
Make sure the default order message exactly matches the message you get on your product page so the custom message will be used instead.

Categories