I like to display unit prices at variable products. I like it to do based on a product attribute whic contains the following: 5 kg, 2 l etc. So, I get the attribute, extract the numbers from it and do some math. The problem is, that all of the code displays the multipier number of 1. Here is my code:
function product_variation_unit_price( $data, $product, $variation ) {
$price = wc_get_price_to_display( $variation );
$unit = array_shift( wc_get_product_terms( $product->id, 'pa_unit', array( 'fields' => 'names' ) ) );
$unit_number_extracted = preg_replace('/[^0-9]/', '', $unit);
if ( (!empty($unit) ) AND $unit_number_extracted == 1 ) {
$unit_price = sprintf( __( 'Gross unit price: %s', 'loremipsum' ), wc_price($price * $unit_number_extracted) );
} else if( (!empty($unit) ) AND $unit_number_extracted > 1 ) {
$unit_price = sprintf( __( 'Gross unit price: %s', 'loremipsum' ), wc_price($price / $unit_number_extracted) );
}
$data['price_html'] .= '<span> ' . $unit_price . '</span>';
return $data;
}
add_filter( 'woocommerce_available_variation', 'product_variation_unit_price', 10, 3 );
I guess I should foreach the variations, but I don't know how to do that in this situation.
Thanks if you can help!
Related
So, I have a woocommerce shop where a 10% discount is applied to all products in the cart and at checkout if a certain payment gateway is used.
My shop has both simple and variable products, and they are all virtual products. I thought of showing on the product page the following information:
the lowest price (for variable products)
the 10% discounted price I could get at checkout.
To do this I used the following code for variable products:
add_filter( 'woocommerce_variable_sale_price_html', 'wpglorify_variation_price_format', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'wpglorify_variation_price_format', 10, 2 );
function wpglorify_variation_price_format( $price, $product ) {
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'A partire da: %1$s (' . $prices[0]*.9 . '€ se paghi online)' , 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( 'A partire da: %1$s (' . $prices[0]*.9 . '€ se paghi online)' , 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
return $price;
}
For simple products I used this snippet instead:
add_filter( 'woocommerce_get_price_html', 'change_displayed_price_html', 10, 2 );
function change_displayed_price_html( $price, $product ) {
if( $product->is_type('simple') ){
$regular_price = (float) $product->get_regular_price();
$saving_price = $regular_price*.9;
$price .= sprintf( __(' (€%s se paghi online)', 'woocommerce' ), $saving_price );
}
return $price;
}
Everything works fine, but on variable products I have a problem. When I select a variation, I would like to give the same information next to the price being shown and related to that variation. I tried with the following snippet:
add_filter('woocommerce_available_variation', 'variation_custom_text', 10, 3 );
function variation_custom_text( $price, $product, $variation ) {
$variation_price = (float) $product->get_variation_price();
$saving_price = $variation_price*.9;
$price['availability_html'] .= sprintf( __(' (€%s se paghi online)', 'woocommerce' ), $saving_price );
return $price;
}
The problem is that the discounted price is calculated on the price of the first variation, regardless of which variation I select. For example, if variation A = $100, a discounted price of $90 is shown. If I select variation B = $120, a discounted price of $90 is always shown. Where am I doing wrong?
Thanks for your answers.
Using "Reorder and customize product dimensions formatted output in WooCommerce" answer code il would like to make the output display as:
Size: D40 x W45 x H60 (cm)
Any help is appreciated.
Just add the follows code snippet in your active theme's functions.php to achieve the above -
function woocommerce_display_product_attributes( $product_attributes, $product ){
if( !isset( $product_attributes['dimensions'] ) ) return $product_attributes;
$modified_dimensions = array();
foreach ( $product->get_dimensions( false ) as $key => $value ) {
if( $key == 'length' )
$modified_dimensions[$key] = 'D'.$value;
if( $key == 'width' )
$modified_dimensions[$key] = 'W'.$value;
if( $key == 'height' )
$modified_dimensions[$key] = 'H'.$value;
}
$dimension_string = implode( ' × ', array_filter( array_map( 'wc_format_localized_decimal', $modified_dimensions ) ) );
if ( ! empty( $dimension_string ) ) {
$dimension_string .= ' (' . get_option( 'woocommerce_dimension_unit' ) . ')';
} else {
$dimension_string = __( 'N/A', 'woocommerce' );
}
// change dimensions label & value.
$product_attributes['dimensions']['label'] = __( 'Size', 'text-domain' );
$product_attributes['dimensions']['value'] = $dimension_string;
return $product_attributes;
}
add_filter( 'woocommerce_display_product_attributes', 'woocommerce_display_product_attributes', 99, 2 );
Welcome to StackOverflow!
Try a simpler code (tested):
add_filter( 'woocommerce_format_dimensions', 'custom_formated_product_dimentions', 10, 2 );
function custom_formated_product_dimentions( $dimension_string, $dimensions ){
if ( empty( $dimension_string ) )
return __( 'N/A', 'woocommerce' );
$dimensions = array_filter( array_map( 'wc_format_localized_decimal', $dimensions ) );
return 'D'.$dimensions['length'].' x W'.$dimensions['width'].' x H'.$dimensions['height'].' ('.get_option( 'woocommerce_dimension_unit' ).')';
}
I can't display crossed price for 0 priced variable products.
That is my code. Where I'm going wrong ?
add_filter( 'woocommerce_get_price_including_tax_html', 'woocommerce_get_regular_price_html', 'woocommerce_get_price_html', 'price_free_zero_empty', 9998, 2 );
function price_free_zero_empty( $price, $product ){
if ( '' === $product->get_price_including_tax() || 0 == $product->get_price_including_tax() ) {
$regular_price = $product->get_price_including_tax();
$price = '<del>' . wc_price( $regular_price ) . '</del> '. '<span class="woocommerce-Price-amount amount">'.__("Free", "woocommerce").'</span>';
}
return $price;
}
function wpglorify_price_free_zero_empty( $price, $product ) {
if ( $product->get_price() == 0 ) {
if ( $product->is_on_sale() && $product->get_regular_price() ) {
$regular_price = wc_get_price_to_display( $product, array( 'qty' => 1, 'price' => $product->get_regular_price() ) );
$price = wc_format_price_range( '<del>' . wc_price($regular_price) . '</del>', __( 'Omaggio!', 'woocommerce' ) );
} else {
$price = '<span class="amount">' . __( 'Omaggio!', 'woocommerce' ) . '</span>';
}
}
return $price;
}
add_filter( 'woocommerce_get_price_html', 'wpglorify_price_free_zero_empty', 10, 2 );
The scenario is Simple product, Variable product are woocommerce's two different product types.
The simple product will show you the regular and sale price.
The variation would give you a price range.
What I am trying to achieve is, there are some products which have over 50+ variations which have a different sale and regular prices. A price range for that product is fare.
But there are also products which's variations have same regular and sale prices. No difference in prices. I want the price to be shown just as
I agree the question arises that why shouldn't I go with simple products? Because in simple products I am not allowed to add the colors that are available in drop downs. Any suggestions please?
I was finding the exact hook to fix the problem with codeNinja snippet! This is how it is fixed:
function wc_ninja_custom_variable_price( $price, $product ) {
// Main Price
$prices = array( $product->get_variation_price( 'min', true ), $product->get_variation_price( 'max', true ) );
$price = $prices[0] !== $prices[1] ? sprintf( __( 'Starting From: %1$s', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
// Sale Price
$prices = array( $product->get_variation_regular_price( 'min', true ), $product->get_variation_regular_price( 'max', true ) );
sort( $prices );
$saleprice = $prices[0] !== $prices[1] ? sprintf( __( '', 'woocommerce' ), wc_price( $prices[0] ) ) : wc_price( $prices[0] );
if ( $price !== $saleprice ) {
$price = ' <ins class="highlight"> '. $price.' </ins> <del class="strike"> '.$saleprice .' </del> ';
}
return $price;
}
add_filter( 'woocommerce_variable_sale_price_html', 'wc_ninja_custom_variable_price', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'wc_ninja_custom_variable_price', 10, 2 );
I create a custom badge/bubble "New!" based on time published:
add_action( 'woocommerce_before_shop_loop_item', function() {
#add_action( 'woocommerce_single_product_image_html', function() {
$postdate = get_the_time( 'Y-m-d' ); // Post date
$postdatestamp = strtotime( $postdate ); // Timestamped post date
$newness = 10; // Newness in days
if ( ( time() - ( 60 * 60 * 24 * $newness ) ) < $postdatestamp ) {
echo '<div class="woo-entry-new-badge"><div class="woo-cust-new-badge">' . esc_html__( 'New!', 'woocommerce' ) . '</div></div>';
}
}, 20 );
But i want to add conditional to show if "on sale" is not set.
How should look like?
thanks!
WC_Product::is_on_sale() – Returns whether or not the product is on sale.
function my_callback_function() {
global $product;
$postdate = get_the_date( 'Y-m-d', $product->get_id() ); // Post date
$postdatestamp = strtotime( $postdate ); // Timestamped post date
$newness = 10; // Newness in days
$onsale = $product->is_on_sale();
if ( ( time() - ( 60 * 60 * 24 * $newness ) ) < $postdatestamp && !$onsale ) {
echo '<div class="woo-entry-new-badge"><div class="woo-cust-new-badge">' . esc_html__( 'New!', 'woocommerce' ) . '</div></div>';
}
}
add_action( 'woocommerce_before_shop_loop_item', 'my_callback_function', 10, 0 );