Using WC_Tax::get_tax_classes() to get all WooCommerce tax-classes - php

I try to get the active tax-classes in Woocommerce in my custom plugin. When I use the WC_Tax::get_tax_classes(), I get a empty array.
How does WC_tax class work without order details and run by itself?

WC_Tax::get_tax_classes() returns an empty array when there is only the default tax class set in WooCommerce > Tax (tab) settings.
It's used for example in wc_get_product_tax_class_options() function that displays the available tax classes in admin product pages settings:
/**
* Get product tax class options.
*
* #since 3.0.0
* #return array
*/
function wc_get_product_tax_class_options() {
$tax_classes = WC_Tax::get_tax_classes();
$tax_class_options = array();
$tax_class_options[''] = __( 'Standard', 'woocommerce' );
if ( ! empty( $tax_classes ) ) {
foreach ( $tax_classes as $class ) {
$tax_class_options[ sanitize_title( $class ) ] = $class;
}
}
return $tax_class_options;
}
So the default tax class (active tax class) has no entry when using WC_Tax::get_tax_classes().
Then you can use wc_get_product_tax_class_options() function to get all WooCommerce tax classes or the code from this function if you want something more custom.
Related: How to get the available tax rates in WooCommerce

Related

Show shipping class on product page (variable products) Woocommerce

I'm struggling to show the different shipping classes on the product page in Woocommerce. I have found several codes that show the shipping class of simple products. But not codes that show the classes of the different variations on a variable product.
The code should get the shipping class of simple products to show (cause I gave several simple products). But when the product is a variable product it needs to show the shipping classes of the variations instead of the parent shipping class.
I am not capable of coding this, hoping there is someone who is skilled enough and willing to help.
It would be nice if the front end looks like this:
Front end shipping class
One way is to use the variation stock filter woocommerce_get_stock_html() which takes 2 arguments:
$html for displaying the content
$product Product object
You need to set the shipping class to each variation and add this to your functions.php:
/**
* Add shipping class for Product variations.
*
* #param mixed $html Displays stock html content.
* #param WC_Product $product Product Object.
*
* #return mixed $html Updated stock html content.
*/
add_filter( 'woocommerce_get_stock_html', 'amp_woocommerce_get_stock_html', 10, 2 );
function amp_woocommerce_get_stock_html( $html, $product ) {
$shipping_slug = $product->get_shipping_class();
if ( ! empty( $shipping_slug ) ) {
$shipping_name = get_term_by( 'slug', $shipping_slug, 'product_shipping_class' );
$html .= sprintf( '<p class="shipping-class"><strong>%s</strong> %s</p>', __( 'Shipping:', 'text-domain' ), $shipping_name );
}
return $html;
}

Custom Woocommerce product weight calculation from dimensions only for specific shipping methods

I am trying to set up a dimensional weight counting method when the dimensional weight (width x height x length) of the product is greater than the weight (actual weight).
I found Custom Woocommerce product weight calculation from dimensions answer code that works perfectly.
However I would like to make it works only for specific shipping method(s).
Any advice or help?
add_filter( 'woocommerce_product_get_weight', 'custom_get_weight_from_dimensions', 10, 2 );
function custom_get_weight_from_dimensions( $weight, $product ) {
$chosen_shipping = WC()->session->get('chosen_shipping_methods')[0];
// How to restrict to specific shipping methods?
$dim_weight = $product->get_length() * $product->get_width() * $product->get_height() / 5000;
return $dim_weight > $weight ? $dim_weight : $weight;
}
You can use the following targeting specific shipping methods only (see at the end, how to get your shipping method rate ids):
add_filter( 'woocommerce_product_get_weight', 'custom_get_weight_from_dimensions', 10, 2 );
function custom_get_weight_from_dimensions( $weight, $product ) {
if ( ! is_admin() ) {
// Here set your targeted shipping method rate Ids
$targetted_shipping_ids = array( 'flat_rate:12', 'flat_rate:14' );
// Get chosen shipping method(s)
$chosen_shipping_methods = (array) WC()->session->get('chosen_shipping_methods');
$matched_shipping_methods = array_intersect( $chosen_shipping_methods, $targetted_shipping_ids );
if( ! empty($matched_shipping_methods) ) {
$dim_weight = $product->get_length() * $product->get_width() * $product->get_height() / 5000;
}
}
return isset($dim_weight) && $dim_weight > $weight ? $dim_weight : $weight;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
How to get the shipping method rate ID:
To get the related shipping methods rate IDs, something like flat_rate:12, inspect with your browser code inspector each related radio button attribute value like:

About update product stock status function in WooCommerce 3

The deal is, I have to fix an error in a custom WooCommerce import plugin, which appeared after updating WC from 2.6 to 3.4.
It uses the 'wc_update_product_stock_status' function, and used to pass post (product) id and it's stock status as it is represented in DB ('instock' and 'outofstock', as a string). But nowadays, as I can see in the WooCommerce docs (https://docs.woocommerce.com/wc-apidocs/function-wc_update_product_stock_status.html) it accepts integer instead of string.
So, the question is - what are those integers for in/out of stock values (1/0 did not fit).
If you look to the source code in wc_update_product_stock_status() function:
/**
* Update a product's stock status.
*
* #param int $product_id
* #param int $status
*/
function wc_update_product_stock_status( $product_id, $status ) {
$product = wc_get_product( $product_id );
if ( $product ) {
$product->set_stock_status( $status );
$product->save();
}
}
It uses the WC_Product set_stock_status() Woocommerce 3 CRUD method which uses strings But not integers values:
/**
* Set stock status.
*
* #param string $status New status.
*/
public function set_stock_status( $status = 'instock' ) {
$valid_statuses = wc_get_product_stock_status_options();
if ( isset( $valid_statuses[ $status ] ) ) {
$this->set_prop( 'stock_status', $status );
} else {
$this->set_prop( 'stock_status', 'instock' );
}
}
So it's an error in the comment usage in wc_update_product_stock_status() function.
It still uses: 'instock' and 'outofstock' status strings. the default value is 'instock'…
The main difference is also that stock status is now handled as outofstock term for the custom taxonomy product_visibility
Before Woocommerce 3, stock status was handled as product meta data.

Change WooCommerce variable product title based on variations

I've coded in a custom select box to a group of my products that changes the price based on the user's selection. It works well, but now I need to change the product title too based on their selection.
Basically if option 1 is chosen, the product name stays the same. But is option 2 is chosen, I need to add "-RZ" to the end of the product title.
I'm not sure if I can do this in the 'woocommerce_before_calculate_totals' hook where I altered the prices, but if anyone knows the hook I should use and the code to access the current product's title via PHP that would be great.
Here is the code that alters the price if it's helpful:
function calculate_core_fee( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" )) {
/* core price */
//echo $additionalPrice;
//$additionalPrice = 100;
foreach ( $cart_object->cart_contents as $key => $value ) {
$product_id = $value['product_id'];
if( isset( $value["addOn"] ) && $value["addOn"] == $product_id) {
$additionalPrice = $value['core'];
/* Woocommerce 3.0 + */
$orgPrice = floatval( $value['data']->get_price() );
//echo $additionalPrice;
//echo $orgPrice;
$value['data']->set_price( $orgPrice + $additionalPrice );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_core_fee', 99 );
I know may have to get the name and store it in a SESSION variable to use later if the hook to do this is on the cart, checkout, or order page rather than the single-product page.
Yes this is possible in the same hook. You can manipulate the product title with class WC_Product get_name() and set_name() methods. But as for the price, you should set and get a custom cart field value to make it (just as $additionalPrice = $value['core'];).
See here a simple related answer: Changing WooCommerce cart item names
So you could have something like (just a fake example):
// Get your custom field cart value for the user selection
$userSelection = $value['user_selection'];
// Get original title
$originalTitle = $value['data']->get_name();
// Conditionally set the new item title
if($userSelection == 'option2')
$value['data']->set_name( $originalTitle . '-RZ' );

WooCommerce - How to get shipping class of cart items in calculate_shipping function?

I have created a WooCommerce plugin that enables free shipping for subscribers. It seems to have broken following a recent WooCommerce upgrade.
Specifically, the problem seems that the shipping class of the cart items may not be being retrieved correctly.
Here is my calculate_shipping code - can anyone advise what is wrong?
/**
* Add free shipping option for customers in base country with an active subscription,
* but only if the cart doesn't contain an item with the 'heavy-item-shipping-class'.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping($package) {
global $woocommerce;
// Check country and subscription status
if (is_user_in_base_country() && does_user_have_active_subscription()) {
// This flag will be set to TRUE if cart contains heavy items
$disable_free_shipping = FALSE;
// Get cart items
$cart_items = $package['contents'];
// Check all cart items
foreach ($cart_items as $cart_item) {
// Get shipping class
$shipping_class = $cart_item['data']->shipping_class; // *** IS THIS THE RIGHT WAY TO GET THE SHIPPING CLASS ??? ***
// If heavy item, set flag so free shipping option is not made available
if ($shipping_class === 'heavy-item-shipping-class') {
// Set flag
$disable_free_shipping = TRUE;
// Enough
break;
}
}
// If appropriate, add the free shipping option
if ($disable_free_shipping === FALSE) {
// Create the new rate
$rate = array(
'id' => $this->id,
'label' => "Free Shipping",
'cost' => '0',
'taxes' => '',
'calc_tax' => 'per_order'
);
// Register the rate
$this->add_rate($rate);
}
else {
// Doesn't qualify for free shipping, so do nothing
}
}
}
UPDATE
I've looked at the %package array and noticed that it now contains the shipping class under [shipping_class:protected]. (Previously, this must have been [shipping_class].) Is it possible to extract this data? If not, what is the correct way of doing it?
I found the solution. Now, it seems the only way to get the shipping class of a product/item is to call get_shipping_class() on it.
So, in my code snippet, above, I changed...
$shipping_class = $cart_item['data']->shipping_class;
...to...
$shipping_class = $cart_item['data']->get_shipping_class();
Hopefully, this will help someone else. :)

Categories