My following code allows a product that is on sale to display the regular price followed by the discounted price. The discounted price is excluding tax but the regular price is set to include tax (as per Woocommerce settings), as only this product type needs to show '+tax'.
How can I get $product->regular_price; to be displayed excluding tax?
if( $product->is_on_sale() ) {
echo '<div style="text-decoration: line-through" class="original_price">£';
echo $product->regular_price;
echo ' </div>';
}
echo wc_price( wc_get_price_excluding_tax( $product ) );
if ( $product->is_taxable() ) {
echo ' +VAT';
}
You can change the following line
echo $product->regular_price;
To
echo wc_get_price_excluding_tax( $product, array(
'price' => $product->regular_price
);
Related
What I'm trying to achieve in WooCommerce is that on the single product page, the Description tab, I'm trying to add the product page title before the word Description.
Here is my current WooCommerce code:
defined( 'ABSPATH' ) || exit;
global $post;
$heading = apply_filters( 'woocommerce_product_description_heading', __( 'Description', 'woocommerce' ) ); ?>
<?php if ( $heading ) : ?>
<h2>PRODUCT PAGE TITLE HERE <?php echo esc_html( $heading ); ?></h2>
<?php endif; ?>
<?php the_content(); ?>
The problem here, however, is that:
I have to overwrite the template file, is it possible via a hook?
The product title is not dynamic.
As a result, id like the tab to go from Description to BLACK NIKE SHOES Description
Example:
Any advice?
You can use the woocommerce_product_{$tab_key}_tab_title composite filter hook. Where $tab_key is in your case description
Use global $product and $product->get_name() to get the product title. This result can then be added to the existing string.
So you get:
function filter_woocommerce_product_description_tab_title( $title ) {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get title and append to existing string
$title = $product->get_name() . ' ' . $title;
}
return $title;
}
add_filter( 'woocommerce_product_description_tab_title', 'filter_woocommerce_product_description_tab_title', 10, 1 );
Optional: to change the WooCommerce product description heading instead, use the woocommerce_product_description_heading filter hook:
function filter_woocommerce_product_description_heading( $heading ) {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get title and append to existing string
$heading = $product->get_name() . ' ' . $heading;
}
return $heading;
}
add_filter( 'woocommerce_product_description_heading', 'filter_woocommerce_product_description_heading', 10, 1 );
I'm currently adding the below code in woocommerce/cart/cart-shipping.php to change the no shipping method message for a country that is not in the shipping country list of WooCommerce.
<?php
add_filter( 'woocommerce_cart_no_shipping_available_html', 'custom_no_shipping_available_html' );
add_filter( 'woocommerce_no_shipping_available_html', 'custom_no_shipping_available_html' );
function custom_no_shipping_available_html( $message ) {
$country = WC()->customer->get_shipping_country();
if ( !empty( $country ) ) {
$all_countries = WC()->countries->get_countries();
return sprintf( "Unfortunately, we don't ship to %s. Please contact our Support if you need any help.", $all_countries[ $country ] );
}
return sprintf( "Unfortunately, we don't ship to this location. Please contact our Support if you need any help.", $all_countries[ $country ] );
}
?>
After this piece of code the default code in cart-shipping.php is:
$formatted_destination = isset($formatted_destination) ? $formatted_destination : WC()->countries->get_formatted_address($package['destination'], ', ');
$has_calculated_shipping = !empty($has_calculated_shipping);
$show_shipping_calculator = !empty($show_shipping_calculator);
$calculator_text = '';
?>
<tr class="woocommerce-shipping-totals shipping">
<th><?php echo wp_kses_post($package_name); ?></th>
<td data-title="<?php echo esc_attr($package_name); ?>">
<?php if ($available_methods) : ?>
<ul id="shipping_method" class="woocommerce-shipping-methods">
<?php foreach ($available_methods as $method) : ?>
<li>
<?php
if (1 < count($available_methods)) {
printf('<input type="radio" name="shipping_method[%1$d]" data-index="%1$d" id="shipping_method_%1$d_%2$s" value="%3$s" class="shipping_method" %4$s />', $index, esc_attr(sanitize_title($method->id)), esc_attr($method->id), checked($method->id, $chosen_method, false)); // WPCS: XSS ok.
} else {
printf('<input type="hidden" name="shipping_method[%1$d]" data-index="%1$d" id="shipping_method_%1$d_%2$s" value="%3$s" class="shipping_method" />', $index, esc_attr(sanitize_title($method->id)), esc_attr($method->id)); // WPCS: XSS ok.
}
printf('<label for="shipping_method_%1$s_%2$s">%3$s</label>', $index, esc_attr(sanitize_title($method->id)), wc_cart_totals_shipping_method_label($method)); // WPCS: XSS ok.
do_action('woocommerce_after_shipping_rate', $method, $index);
?>
</li>
<?php endforeach; ?>
</ul>
<?php if (is_cart()) : ?>
<p class="woocommerce-shipping-destination">
<?php
if ($formatted_destination) {
// Translators: $s shipping destination.
printf(esc_html__('Shipping to %s.', 'woocommerce') . ' ', '<strong>' . esc_html($formatted_destination) . '</strong>');
$calculator_text = esc_html__('Change address', 'woocommerce');
} else {
echo wp_kses_post(apply_filters('woocommerce_shipping_estimate_html', __('Shipping options will be updated during checkout.', 'woocommerce')));
}
?>
</p>
<?php endif; ?>
<?php
elseif (!$has_calculated_shipping || !$formatted_destination) :
if (is_cart() && 'no' === get_option('woocommerce_enable_shipping_calc')) {
echo wp_kses_post(apply_filters('woocommerce_shipping_not_enabled_on_cart_html', __('Shipping costs are calculated during checkout.', 'woocommerce')));
} else {
echo wp_kses_post(apply_filters('woocommerce_shipping_may_be_available_html', __('Enter your address to view shipping options.', 'woocommerce')));
}
elseif (!is_cart()) :
echo wp_kses_post(apply_filters('woocommerce_no_shipping_available_html', __('There are no shipping options available. Please ensure that your address has been entered correctly, or Please contact our Support if you need any help.', 'woocommerce')));
else :
// Translators: $s shipping destination.
echo wp_kses_post(apply_filters('woocommerce_cart_no_shipping_available_html', sprintf(esc_html__('No shipping options were found for %s.', 'woocommerce') . ' ', '<strong>' . esc_html($formatted_destination) . '</strong>')));
$calculator_text = esc_html__('Enter a different address', 'woocommerce');
endif;
?>
<?php if ($show_package_details) : ?>
<?php echo '<p class="woocommerce-shipping-contents"><small>' . esc_html($package_details) . '</small></p>'; ?>
<?php endif; ?>
<?php if ($show_shipping_calculator) : ?>
<?php woocommerce_shipping_calculator($calculator_text); ?>
<?php endif; ?>
</td>
</tr>
But the problem is that I have to complete all the billing address fields including phone and zip code to get my message that the selected country is not supported.
I think this happens because by default WooCommerce is checking the $formatted_destination variable set in the same PHP file.
My question is how can I have the message in a way that is directly shown once the country is selected and it is not part of the shipping country?
To answer your question, first some explanation. I copied a piece of code from templates/cart/cart-shipping.php line 66 - 72 #version 3.6.0
elseif ( ! is_cart() ) :
echo wp_kses_post( apply_filters( 'woocommerce_no_shipping_available_html', __( 'There are no shipping options available. Please ensure that your address has been entered correctly, or contact us if you need any help.', 'woocommerce' ) ) );
else :
// Translators: $s shipping destination.
echo wp_kses_post( apply_filters( 'woocommerce_cart_no_shipping_available_html', sprintf( esc_html__( 'No shipping options were found for %s.', 'woocommerce' ) . ' ', '<strong>' . esc_html( $formatted_destination ) . '</strong>' ) ) );
$calculator_text = esc_html__( 'Enter a different address', 'woocommerce' );
endif;
As you can see this contains 2 filters hook, namely:
woocommerce_no_shipping_available_html
woocommerce_cart_no_shipping_available_html
While the second hook, in the message shows $formatted_destination, the first one doesn't.
So to answer your question, you can use the hooks like this:
The message displayed on the cart page
function filter_woocommerce_cart_no_shipping_available_html( $sprintf ) {
// Get packages
$packages = WC()->shipping()->get_packages();
// Loop through
foreach ( $packages as $i => $package ) {
$formatted_destination = WC()->countries->get_formatted_address( $package['destination'], ', ' );
}
// Message
$sprintf = sprintf( esc_html__( 'Unfortunately, we don\'t ship to %s. Please contact our Support if you need any help.', 'woocommerce' ) . ' ', '<strong>' . esc_html( $formatted_destination ) . '</strong>' );
return $sprintf;
}
add_filter( 'woocommerce_cart_no_shipping_available_html', 'filter_woocommerce_cart_no_shipping_available_html', 10, 1 );
The message displayed on the checkout page
function filter_woocommerce_no_shipping_available_html( $html ) {
// Message
$html = __( 'My new message', 'woocommerce' )
return $html;
}
add_filter( 'woocommerce_no_shipping_available_html', 'filter_woocommerce_no_shipping_available_html', 10, 1 );
With both answers there is no need to modify/overwrite template files, code goes in functions.php file of the active child theme (or active theme).
Woocommerce in wordpress, I want to show number of customers who are ordering that product (has not yet been processed)
Demo: http://i.imgur.com/f7Iicu2.jpg
put the below code in your function.PHP file
add_action( 'woocommerce_single_product_summary', 'bbloomer_product_sold_count', 11 );
add_action( 'woocommerce_after_shop_loop_item', 'bbloomer_product_sold_count', 11 );
function bbloomer_product_sold_count() {
global $product;
$units_sold = get_post_meta( $product->id, 'total_sales', true );
echo '<p>' . sprintf( __( 'Units Sold: %s', 'woocommerce' ), $units_sold ) . '</p>';
}
in above code you can see the units sold in product single page/ Product detail page and looping page.
I am using Woocommerce Product Add-on plugin to allow visitor to select multiple options on simple product. As the product is simple product Woocommerce display an Add to cart button on products page view instead of Choose option button linking on Product detail page where visitor can choose options.
I am looking to create a function that will display Choose option button on product by ID.
Here is my starting code.
add_filter( 'woocommerce_loop_add_to_cart_link', 'change_product_button' );
function change_product_button() {
global $product;
$id = $product->id;
if ($id == 91){
echo '' . __('View Product', 'woocommerce') . '';
} else {
// display usual add to cart button
}
}
Or maybe we can force product by id as non purchasable to simulate a variable product.
This is a working solution
add_filter( 'woocommerce_loop_add_to_cart_link', 'change_product_button', 10, 2 );
function change_product_button($html, $product) {
$values = array(190, 91);
$id = $product->id;
if(in_array($id, $values)){
$html= '' . __('Choose an option', 'woocommerce') . '';
} else {
$html = '<form action="' . esc_url( $product->add_to_cart_url() ) . '" class="cart" method="post" enctype="multipart/form-data">';
$html .= woocommerce_quantity_input( array(), $product, false );
$html .= '<button type="submit" class="button alt">' . esc_html( $product->add_to_cart_text() ) . '</button>';
$html .= '</form>';
}
return $html;
}
Im trying to get the following information on a woocommerce single product page in order to replace the default price style of woocommerce.
When Item is on sale, I want to be able to get the original price and discounted price and echo it inside a dive for further styling. Im trying to achive something like this.
<div id="orig-price">Original Price: <?php echo $price; ?></div>
<div id="sale-price">Sale Price: <?php echo $sale-price; ?></div>
<div id="saved">You saved: <?php $saved=$price-$saleprice; echo $saved; ?></div>
I tried opening price.php but did not find what I am looking for. here is what I get.
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
<p class="price"><?php echo $product->get_price_html(); ?></p>
<meta itemprop="price" content="<?php echo $product->get_price(); ?>" />
<meta itemprop="priceCurrency" content="<?php echo get_woocommerce_currency(); ?>" />
<link itemprop="availability" href="http://schema.org/<?php echo $product->is_in_stock() ? 'InStock' : 'OutOfStock'; ?>" />
<div><?php echo $sale_price_in_percent; ?></div>
</div>
Am I on the right place? Anyone know how can I access these attributes?
Thanks
Main function for displaying prices is get_price_html() in /woocommerce/includes/abstracts/abstract-wc-product.php file, and there are some filters to allow users to customize the html for prices:
woocommerce_sale_price_html
woocommerce_price_html
woocommerce_empty_price_html
woocommerce_free_sale_price_html
woocommerce_free_price_html
woocommerce_get_price_html
This function performs a complete job for showing prices including taxes and on sale calculations, and since you are completely rewriting the html the example below uses last filter there woocommerce_get_price_html. It extracts the prices from the original HTML and insert them into a new HTML structure.
add_filter( 'woocommerce_get_price_html', function( $price, $product )
{
global $woocommerce_loop;
// check if we are in single product page, in main section, and if product has price and is on sale
if ( is_product() && !isset( $woocommerce_loop ) && $product->get_price() && $product->is_on_sale() ) {
// collect prices from $price html string
$prices = array_map( function( $item ) {
return array( $item, (float) preg_replace( "/[^0-9.]/", "", html_entity_decode( $item, ENT_QUOTES, 'UTF-8' ) ) );
}, explode( ' ', strip_tags( $price ) ) );
$price = isset( $prices[0][0] ) ? '<span class="orig-price">Original Price: ' . $prices[0][0] . '</span>' : '';
$price .= isset( $prices[1][0] ) ? '<span class="sale-price">Sale Price: ' . $prices[1][0] . '</span>' : '';
if ( $product->get_regular_price() ) {
// set saved amount with currency symbol placed as defined in options
$price .= '<span class="saved">You saved: ' . sprintf( get_woocommerce_price_format(), get_woocommerce_currency_symbol(), $prices[0][1] - $prices[1][1] ) . '</span>';
}
}
return $price;
}, 10, 2 );
I'm using span tags here instead of divs used in question because the output is still wrapped in a paragraph. For further customization override the price.php template by placing him inside /themes/yourtheme/woocommerce/single-product/ folder.
This can be achieved by overriding woocommerce template. Create a new PHP file, write your div structure in that file.
Now refer this article on How to override template in WooCommerce
Hope this will move you in right direction