Add shipping class under items in New Order email in WooCommerce? - php

I am trying to add the shipping class under each product to the new order emails for both admin and customers in WooCommerce. This is my first time posting a question so please forgive me if there are formatting issues.
I used the code found here: https://wordpress.stackexchange.com/questions/291637/woocommerce-add-shipping-class-below-each-product-in-shopping-cart-page
That adds the shipping class below each product in the cart but I want to be able to show it on the order emails also.
I am just unsure of which objects to call to grab the data for each product in the new order email.
Here's the code I'm using:
add_action( 'woocommerce_order_item_meta_start', 'ts_order_item_meta_start', 10, 4 );
function ts_order_item_meta_start( $item_id, $item, $order, $plain_text, $item_name ){
$product = $cart_item['data']; // Get the WC_Product object instance
$shipping_class_id = $product->get_shipping_class_id(); // Shipping class ID
$shipping_class_term = get_term( $shipping_class_id, 'product_shipping_class' );
if( empty( $shipping_class_id ) )
return $item_name; // Return default product title (in case of)
$label = __( 'Shipping class', 'woocommerce' );
return $item_name . '<br>
<p class="item-shipping_class" style="margin:12px 0 0;">
<strong>' .$label . ': </strong>' . $shipping_class_term->name . '</p>';
}
I expected the shipping class to be listed below each product in the "New Order" email but currently adding this code returns an internal server error upon checkout.

The following will display The product shipping class name in Woocommerce "New Order" Email notification:
// Setting the email_is as a global variable
add_action('woocommerce_email_before_order_table', 'the_email_id_as_a_global', 1, 4);
function the_email_id_as_a_global($order, $sent_to_admin, $plain_text, $email ){
$GLOBALS['email_id_str'] = $email->id;
}
// Display Items shipping class name in New Order email notification
add_filter( 'woocommerce_order_item_name', 'custom_order_item_name', 10, 3 );
function custom_order_item_name( $item_name, $item, $is_visible ) {
// Targeting email notifications only
if( is_wc_endpoint_url() ) return $item_name;
// Get the WC_Product object (from order item)
$product = $item->get_product();
if( $shipping_class_id = $product->get_shipping_class_id() ){
// Getting the email ID global variable
$refNameGlobalsVar = $GLOBALS;
$email_id = $refNameGlobalsVar['email_id_str'];
// Only for New Order email notification
if( ! empty($email_id) && 'new_order' === $email_id ) {
$shipping_class_name = get_term( $shipping_class_id, 'product_shipping_class' )->name;
$item_name .= '<br><p class="item-shipping_class" style="margin:12px 0 0;">
<strong>' . __( 'Shipping class', 'woocommerce' ) . ': </strong>' . $shipping_class_name . '</p>';
}
}
return $item_name;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Related

Display custom texts based on shipping classes in WooCommerce cart

Here is what I have and it works great for 1 shipping class, but want to have separate messages for different shipping classes:
// Display a custom text under cart item name in cart page
add_filter( 'woocommerce_cart_item_name', 'custom_text_cart_item_name', 10, 3 );
function custom_text_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
// Here below define your shipping class slug
$shipping_class = '5-gallon';
if( is_cart() && $cart_item['data']->get_shipping_class() === $shipping_class ) {
$item_name .= '<br /><div class="item-shipping-class">' . __("Please call confirm shipping rates", "woocommerce") . '</div>';
}
return $item_name; }
For multiple shipping classes with different messages you can use the following:
// Display a custom text under cart item name in cart page
add_filter( 'woocommerce_cart_item_name', 'custom_text_cart_item_name', 10, 3 );
function custom_text_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
// Only on cart page
if( ! is_cart() )
return $item_name;
// Here below define your shipping classes slugs (one by line)
$shipping_class_1 = '5-gallon';
$shipping_class_2 = '10-gallon';
$shipping_class = $cart_item['data']->get_shipping_class();
// First shipping class
if( $shipping_class === $shipping_class_1 ) {
$item_name .= '<br /><div class="item-shipping-class">' . __("Please call confirm shipping rates", "woocommerce") . '</div>';
}
// 2nd shipping class
elseif( $shipping_class === $shipping_class_2 ) {
$item_name .= '<br /><div class="item-shipping-class">' . __("Some different messageā€¦", "woocommerce") . '</div>';
}
return $item_name;
}
Code goes in functions.php file of the active child theme (or active theme). It should works.

ACF custom fields in WooCommerce E-Mail template

I'm wanting to display custom ACF fields in a product within the order complete e-mail, I have this hook which works great for none-variable products:
add_filter( 'woocommerce_order_item_name', 'custom_order_item_name', 10, 2 );
function custom_order_item_name( $item_name, $item ) {
// Targeting email notifications only
if( is_wc_endpoint_url() )
return $item_name;
// Get the WC_Product object (from order item)
$product = $item->get_product();
if( $date = get_field('date', $product->get_id()) ) {
$item_name .= '<br /><strong>' . __( 'Date', 'woocommerce' ) . ': </strong>' . $date;
}
if( $location = get_field('location', $product->get_id()) ) {
$item_name .= '<br /><strong>' . __( 'Location', 'woocommerce' ) . ': </strong>' . $location;
}
return $item_name;
}
However, while it displays my custom fields (date and location) fine for simple products within the e-mail, it does not for variable products.
I can't seem to understand why?
I found the solution.
When it is a simple product, the product ID is the post ID. However when it is a variable product, they then use a variable product ID, not the post ID. Which means the ACF fields are not looking at the post ID of the product, so won't display.
To fix this for variable products you must get the parent ID from the array:
$parent_id=$product->get_parent_id();
// If it is a variable product, get the parent ID
if($parent_id){
$product_id = $parent_id;
// else, it is a simple product, get the product ID
}else{
$product_id = $product->get_id();
}
Full code is:
// Display Items Shipping ACF custom field value in email notification
add_filter( 'woocommerce_order_item_name', 'custom_order_item_name', 10, 2 );
function custom_order_item_name( $item_name, $item ) {
// Targeting email notifications only
if( is_wc_endpoint_url() )
return $item_name;
// Get the WC_Product object (from order item)
$product = $item->get_product();
$parent_id=$product->get_parent_id();
// If it is a variable product, get the parent ID
if($parent_id){
$product_id = $parent_id;
// else, it is a simple product, get the product ID
}else{
$product_id = $product->get_id();
}
if( $date = get_field('date', $product_id) ) {
$item_name .= '<br /><strong>' . __( 'Date', 'woocommerce' ) . ': </strong>' . $date;
}
if( $location = get_field('location', $product_id) ) {
$item_name .= '<br /><strong>' . __( 'Location', 'woocommerce' ) . ': </strong>' . $location;
}
return $item_name;
}

Replace the product name by the Sku in My account view order pages

Using Woocommerce, I would like to add SKU instead of the product name in the order view page of My Account /my-account/view-order/[orderid]/
I am able to add the SKU with a link using the code below.
The SKU is displayed just after the product name on the same line.
add_filter( 'woocommerce_order_item_name', 'display_sku_in_order_item', 20, 3 );
function display_sku_in_order_item( $item_name, $item, $is_visible ) {
if( is_wc_endpoint_url( 'view-order' ) ) {
$product = $item->get_product();
if( $sku = $product->get_sku() )
$item_name .= '' . __( "Product ", "woocommerce") . $sku . '';
}
return $item_name;
}
However, I would like to remove the product name but I don't know the code to write to do this. Any help please?
You just need to replace $item_name .= by $item_name = in your code, like:
add_filter( 'woocommerce_order_item_name', 'display_sku_in_order_item', 20, 3 );
function display_sku_in_order_item( $item_name, $item, $is_visible ) {
if( is_wc_endpoint_url( 'view-order' ) ) {
$product = $item->get_product();
if( $sku = $product->get_sku() )
$item_name = '' . __( "Product ", "woocommerce") . $sku . '';
}
return $item_name;
}
Code goes in function.php file of your active child theme (or active theme). It should work.

Customize order item meta only for WooCommerce admin email notifications

I need to add custom taxonomy to admin new order emails but not to customer emails. My current code displays my custom taxonomy for each item in the order but it is showing up in both admin and customer emails, which I don't want.
Looking thru email-order-items.php I don't see a way to utilize $sent_to_admin in the hook that I am using. Am I missing something?
How do I add my custom taxonomy only to admin emails using just hooks and filters?
add_action( 'woocommerce_order_item_meta_end', 'custom_woocommerce_order_item_meta_end', 10, 3 );
function custom_woocommerce_order_item_meta_end( $item_id, $item, $order ) {
$product = $item->get_product();
$locations = get_the_terms( $product->get_id(), 'my_custom_taxonomy' );
echo '<br/>';
echo '<div style="margin-top: 20px;">';
foreach( $locations as $location ) {
echo 'Location: <b>' . $location->name . '</b>';
echo '<br/>';
}
echo '</div>
}
This can be done using $GLOBAL variable. I have revisited a bit your code too. Try this:
// Setting the "sent_to_admin" as a global variable
add_action('woocommerce_email_before_order_table', 'email_order_id_as_a_global', 1, 4);
function email_order_id_as_a_global($order, $sent_to_admin, $plain_text, $email){
$GLOBALS['email_data'] = array(
'sent_to_admin' => $sent_to_admin, // <== HERE we set "$sent_to_admin" value
'email_id' => $email->id, // The email ID (to target specific email notification)
);
}
// Conditionally customizing footer email text
add_action( 'woocommerce_order_item_meta_end', 'custom_email_order_item_meta_end', 10, 3 );
function custom_email_order_item_meta_end( $item_id, $item, $order ){
// Getting the custom 'email_data' global variable
$refNameGlobalsVar = $GLOBALS;
$email_data = $refNameGlobalsVar['email_data'];
// Only for admin email notifications
if( ! ( is_array( $email_data ) && $email_data['sent_to_admin'] ) ) return;
## -------------------------- Your Code below -------------------------- ##
$taxonomy = 'my_custom_taxonomy'; // <= Your custom taxonomy
echo '<br/><div style="margin-top: 20px;">';
foreach( get_the_terms( $item->get_product_id(), $taxonomy ) as $term )
echo 'Location: <b>' . $term->name . '</b><br/>';
echo '</div>';
}
Code goes in function.php file of the active child theme (or active theme).
Tested and works.

Add the product description to WooCommerce email notifications

How to add product description/content of single product page (not the short description) to WooCommerce new order email notification?
I need to know specific written description of my products as most of them are almost same.
As you are targeting a specific email notification, first we need to get the Email ID to target the "New Order" email notification. The only way is to get it before and to set the value in a global variable.
Then in a custom function hooked in woocommerce_order_item_meta_end action hook, we display the product description exclusively for New Order email notification.
Here is that code:
## Tested on WooCommerce 2.6.x and 3.0+
// Setting the email_is as a global variable
add_action('woocommerce_email_before_order_table', 'the_email_id_as_a_global', 1, 4);
function the_email_id_as_a_global($order, $sent_to_admin, $plain_text, $email ){
$GLOBALS['email_id_str'] = $email->id;
}
// Displaying product description in new email notifications
add_action( 'woocommerce_order_item_meta_end', 'product_description_in_new_email_notification', 10, 4 );
function product_description_in_new_email_notification( $item_id, $item, $order = null, $plain_text = false ){
// Getting the email ID global variable
$refNameGlobalsVar = $GLOBALS;
$email_id = $refNameGlobalsVar['email_id_str'];
// If empty email ID we exit
if(empty($email_id)) return;
// Only for "New Order email notification"
if ( 'new_order' == $email_id ) {
if( version_compare( WC_VERSION, '3.0', '<' ) ) {
$product_id = $item['product_id']; // Get The product ID (for simple products)
$product = wc_get_product($item['product_id']);
} else {
$product = $item->get_product();
if( $product->is_type('variation') ) {
$product = wc_get_product( $item->get_product_id() );
}
}
// Get the Product description (WC version compatibility)
if ( method_exists( $item['product'], 'get_description' ) ) {
$product_description = $product->get_description(); // for WC 3.0+ (new)
} else {
$product_description = $product->post->post_content; // for WC 2.6.x or older
}
// Display the product description
echo '<div class="product-description"><p>' . $product_description . '</p></div>';
}
}
This code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Code Update and Error explanations in woocommerce_order_item_meta_end action hook:
PHP Warning for woocommerce_order_item_meta_end (Mike Joley)

Categories