Replace "Sale" badge by "Out of Stock" in Woocommerce archive pages - php

I am working on woocommerce shop and here is the link of the website shop page
On this page the first product is out of stock. I would like to show Out of stock instead of "Sale!" badge on the image.
How can I do this?

If you look at the loop/sale-flash.php template you can see it has a filter for the sale flash. You can add this to your functions.php file to modify that output.
add_filter( 'woocommerce_sale_flash', 'sale_flash_stock_status' );
function sale_flash_stock_status( $output_html, $post, $product ){
if( $product->is_in_stock() ){
// Leave the sale flash unchanged if it's in stock.
return $output_html;
}
else {
// Change the html output custom stock status
$output_html = '<span class="stock-status">' . esc_html__( 'Out of stock', 'woocommerce' ) . '</span>'
return $output_html;
}
}

Add in the functions.php file of your theme:
add_filter('woocommerce_sale_flash', 'woocommerce_custom_sale_text', 10, 3);
function woocommerce_custom_sale_text($text, $post, $_product)
{
return '<span class="onsale">out of stock</span>';
}

The following code will add, on Woocommerce archives pages (as shop), a "Out of Stock" badge for out of stock products replacing the "Sale!" badge when products are on sale:
// Add badge "Out of stock" (and replace sale badge)
add_action('woocommerce_before_shop_loop_item_title','custom_before_shop_loop_item_title', 2 ); // Archives pages
function custom_before_shop_loop_item_title(){
remove_action('woocommerce_before_shop_loop_item_title','woocommerce_show_product_loop_sale_flash', 10 );
remove_action('woocommerce_after_shop_loop_item_title','woocommerce_show_product_loop_sale_flash', 6 ); // For storefront theme
add_action('woocommerce_before_shop_loop_item_title','show_product_loop_outofstock_badge', 10 );
}
function show_product_loop_outofstock_badge(){
global $post, $product;
if ( $product->get_stock_status() == 'outofstock' ) :
echo '<span class="onsale outofstock">'. esc_html__('Out of stock', 'woocommerce') .'</span>';
elseif ( $product->is_on_sale() ) :
echo '<span class="onsale">'. esc_html__( 'Sale!', 'woocommerce' ) .'</span>';
endif;
}
You might have to make some hook priority changes, depending on your theme. This code support also storefront theme.
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Related

Display "In Stock" notice for WooCommerce variations with no Managed Stock

I need help for a particular situation. In WooCommerce, if "Manage Stock" is enabled for a simple product or variation, then a notification is being displayed in the product page => such as [this example][1]
However, if "Manage Stock" is not enabled, then there is no notification which I find it a pity because I still want to inform my customers that it's precisely in stock even if I don't manage the stock quantities.
I've found the below code. For simple products, it works without any problem. However, for variable product, this message is being displayed even before that a variation is selected. This is of course not okay, this code should be displayed only after that a variation is selected.
Can someone help me to fix this? For variable products, this message should only be displayed after that a particular variation is selected.
I've made a video capture to be a bit more illustrative : https://sgevcen.tinytake.com/tt/NDQzNTU2OF8xNDAyNTU2NA
function mycustom_shop_display_stock() {
global $product;
if ( !$product->get_manage_stock() && $product->is_in_stock() ) {
echo '<p class="stock in-stock">In Stock</p>';
}
}
add_action( 'woocommerce_before_add_to_cart_button', 'mycustom_shop_display_stock', 11 );
[1]: https://i.stack.imgur.com/aFnN1.png
Try the following instead that should allow to display your custom stock availability only for the variations of a variable product (and also on simple products):
add_filter( 'woocommerce_get_stock_html', 'filter_wc_get_stock_html', 10, 2 );
function filter_wc_get_stock_html( $html, $product ) {
if ( ! $product->is_type('variable') && ! $product->get_manage_stock() && $product->is_in_stock() ) {
$html = '<p class="stock in-stock">' . __( "In Stock", "woocommerce" ) . '</p>';
}
return $html;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To exclude some product categories use the following (related to your comment):
add_filter( 'woocommerce_get_stock_html', 'filter_wc_get_stock_html', 10, 2 );
function filter_wc_get_stock_html( $html, $product ) {
// Here define the product categories to be excluded (can be term Ids, slugs or names)
$terms_excl = array('hoodies', 'albums');
$product_id = $product->is_type('variation') ? $product->get_parent_id() : $product->get_id();
if ( ! $product->is_type('variable') && ! $product->get_manage_stock() && $product->is_in_stock()
&& ! has_term( $terms_excl, 'product_cat', $product_id ) ) {
$html = '<p class="stock in-stock">' . __( "In Stock", "woocommerce" ) . '</p>';
}
return $html;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related thread: Display custom stock message if "Manage Stock" is not enabled in WooCommerce

Add an icon after product price on Woocommerce archive pages

I am trying to add a custom icon after the product price in Woocommerce for a specific product category on shop page. So I would like to add an icon of a "fast delivery truck" after the price on all products from "FAST SHIPPING" product category.
I would like it to display that like in wish.com web site, like in this screenshot:
This is what I've tried:
add_filter( 'woocommerce_price_html', 'prepend_append_icon_to_price', 10, 2 );
function prepend_append_icon_to_price( $price, $instance ) {
if(is_product_category( 'fast-shipping')){
$icon = ' <i class="fas fa-shipping-fast"></i> ';
$price = $icon . $price . $icon;
}
return $price;
}
But It doesn't display anything after the price.
Any help would be much appreciated.
You are using the wrong hook since Woocommerce 3 and there are some errors in your code.
To display an icon after the price on the right for "fast-shipping" product category, two cases:
1) On all Woocommerce archive pages:
add_filter( 'woocommerce_get_price_html', 'prepend_append_icon_to_price', 10, 2 );
function prepend_append_icon_to_price( $price, $product ) {
if( has_term( 'fast-shipping', 'product_cat', $product->get_id() ) && ! is_product() ){
$price .= '<span style="float:right"><i class="fas fa-shipping-fast"></i></span> ';
}
return $price;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
2) On a specific Woocommerce product category archive pages:
add_filter( 'woocommerce_get_price_html', 'append_icon_after_product_price', 10, 2 );
function append_icon_after_product_price( $price, $product ) {
if( is_product_category( 'fast-shipping' ) ){
$price .= '<span style="float:right"><i class="fas fa-shipping-fast"></i></span> ';
}
return $price;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Use css before or after belong to the price tag :
fa-shipping-fast:before{
content: url(.....);
width : ....;
height : ....;
....
}

Add a custom text to Woocommerce product availability and display it for cart items

I'm trying to find a way to place custom text before availability info (out of stock, in stock etc.) on woocommerce single product page.
I am using something like that:
add_filter( 'woocommerce_get_availability', 'change_product_availability_display' );
add_filter( 'unknown filter', 'change_product_availability_display' );
function change_product_availability_display( $availability ) {
// Additional text
$text = __('Availability:');
// returning the text before the availability
return $text . ' ' . $availability;
}
Its's based on: Add a custom text before the price display in WooCommerce.
In case of price filter named in my code "unknown filter" was woocommerce_cart_item_price. I've looked for this kind of filter for availability/stock item, but can't find it.
Maybe someone could review this code and help me to find this "unknown_filter" or have other idea how I can put custom text before availability info?
I have revisited your code as your are trying to merge a string with an array. Also I have added a 2nd hooked function that will allow to display your "labeled" availability to items in cart and checkout.
The code:
add_filter( 'woocommerce_get_availability', 'add_label_to_availability_display' );
function add_label_to_availability_display( $availability ) {
if( is_product() || is_cart() || is_checkout() ){
$label = __( 'Availability', 'woocommerce' ) . ': ';
$availability['availability'] = $label . $availability['availability'];
}
return $availability;
}
add_filter( 'woocommerce_cart_item_name', 'add_availability_below_cart_item_name', 10, 3);
function add_availability_below_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
$availability = $cart_item['data']->get_availability();
return $item_name . '<br>' . $availability['availability'];
}
Code goes in function.php file of your active child theme (active theme).
Tested and works.

Show total sales in WooCommerce shop archives for each product

I have added this code to my website to show the number of product buy by my clients for each products of my store.
I would like to show the number of sales only if the product has been bought maybe 5 times (to never show "buy 0 time")…
So I have this code:
add_action( 'woocommerce_after_shop_loop_item', 'wpm_product_sold_count', 11 );
function wpm_product_sold_count() {
global $product;
$units_sold = get_post_meta( $product->id, 'total_sales', true );
if ($units_sold > 5) {
echo '<p class="sold-product">' . sprintf( __( 'Produit vendu: %s fois', 'woocommerce' ), $units_sold ) . '</p>';
}
}
But it isn't working. Do you have any tips please?
Thanks
In WooCommerce 3+ you can't acces anymore to the W_Product object properties like the product ID. You need to use the available methods, so $product->id don't work.
Instead use the WC_Data get_id() method on it:
$product_id = $product->get_id();
For the product total sales use use directly the WC_Product get_total_sales() method this way:
add_action( 'woocommerce_after_shop_loop_item', 'wpm_product_sold_count', 11 );
function wpm_product_sold_count() {
global $product;
$units_sold = $product->get_total_sales();
if ($units_sold > 5) {
echo '<p class="sold-product">' . sprintf( __( 'Produit vendu: %s fois', 'woocommerce' ), $units_sold ) . '</p>';
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested with woocommerce 3+ and works.

Displaying the 'out of stock' string on shop page but not the stock quantity.

I'm using this piece of code in my functions.php file of my WordPress/WooCommerce site:
function envy_stock_catalog() {
global $product;
if ( $product->is_in_stock() ) {
echo $product->get_stock_quantity() ;
} else {
echo '<div class="out-of-stock" >' . __( 'out of stock', 'envy' ) . '</div>';
add_action('init','remove_loop_button');
}
}
add_action( 'woocommerce_after_shop_loop_item_title', 'envy_stock_catalog' );
This code displays the 'out of stock' notice on the shop page where all products are displayed like this:
The issue is that it also causes of the available inventory number of the products next to product titles like this:
I don't want this.
My question:
How I can change my code to still display the 'out of stock' notice (when product is out of stock) and not the inventory product availability on shop page (in left side of add-to-cart button)?
Thanks in advance!
Explanations about your code:
In first part (if) was displaying stock quantity as long as product was in stock (even using the working tricks of this answer and even for shop page)
Part two (else) was displaying 'out of stock' string and removing add-to-cart button (as the product was out stock).
With the code below, now we have:
an additional (if) condition with !is_shop() which displays stock quantity as long as product is is stock and is not in shop page.
an additional (else) for shop page, that get out of the function without displaying stock quantity.
and your untouched final else condition (just as before).
So here is the fully functional solution, as desired:
add_action( 'woocommerce_after_shop_loop_item_title', 'envy_stock_catalog' );
function envy_stock_catalog() {
global $product;
if ( $product->is_in_stock() ) { // If product is in stock
if ( !is_shop() ) { // If is NOT Shop page
// Displays the stock quantity
echo '<span class="qty">' . $product->get_stock_quantity() . '<span>';
} else { // If is shop page (and product is in stock)
return; // Don't display stock quantity (and removes nothing).
}
// If product is NOT in stock
} else {
// Display 'out of stock' string
echo '<div class="out-of-stock" >' . __( 'out of stock', 'envy' ) . '</div>';
// Removes "add to cart" button
add_action('init','remove_loop_button');
}
}
If you just want to display stock quantity on single product page, and 'out of stock' only in shop page, this will be your code:
add_action( 'woocommerce_after_shop_loop_item_title', 'envy_stock_catalog' );
function envy_stock_catalog() {
global $product;
// If product is in stock but is not shop page
if ( $product->is_in_stock() && !is_shop() ) {
// Displays the stock quantity
echo '<span class="qty">' . $product->get_stock_quantity() . '<span>';
// If product is NOT in stock and is shop page
} elseif ( !$product->is_in_stock() && is_shop() ) {
// Display 'out of stock' string
echo '<div class="out-of-stock" >' . __( 'out of stock', 'envy' ) . '</div>';
// Removes "add to cart" button
add_action('init','remove_loop_button');
}
// other cases goes out the function
return;
}
Now if you just don't want to display any stock quantity, your code will be like this:
add_action( 'woocommerce_after_shop_loop_item_title', 'envy_stock_catalog' );
function envy_stock_catalog() {
global $product;
if ( $product->is_in_stock() ) { // If product is in stock
return; // Don't display stock quantity (and removes nothing).
// If product is NOT in stock
} else {
// Display 'out of stock' string
echo '<div class="out-of-stock" >' . __( 'out of stock', 'envy' ) . '</div>';
// Removes "add to cart" button
add_action('init','remove_loop_button');
}
}
And in this case you could use all the working tricks from this answer:
Woocommerce - Remove the available product inventory number from the shop page
All code is tested and works perfectly.
The code goes on function.php file of your active child theme or theme…

Categories