WooCommerce add product image in my account order details - wordpress

i want to add a new column called image to myaccount-> orders -> view order
in the orders details table which displays the product image for the corresponding product item in the table like this
expected result
what i have tried
function display_remove_order_item_button( $item_id, $item, $order ){
// Avoiding displaying buttons on email notification
if( ! ( is_wc_endpoint_url( 'view-order' ) || is_wc_endpoint_url( 'order-received' ) ) )
return;
$order_id = 569;
$order = wc_get_order( $order_id );
$product = apply_filters( 'woocommerce_order_item_product', $order->get_product_from_item( $item ), $item );
echo $product->get_image();
}
add_action( 'woocommerce_order_details_before_order_table', 'nolo_custom_field_display_cust_order_meta', 10, 1 );
but the image appears inside the product column
how can i achive the function in the picture ?

For that you will need to edit following templates:
templates/order/order-details.php & templates/order/order-details-item.php
First copy both templates in your active theme folder and add this lines
<th class="woocommerce-table__product-image product-image"><?php _e( 'Image', 'woocommerce' ); ?></th>
in order-details.php and
<td class="woocommerce-table__product-image product-image"><?php echo $product->get_image('thumbnail'); ?></td>
in order-details-item.php. If you need a reference of function get_image check this : https://docs.woocommerce.com/wc-apidocs/class-WC_Product.html
order-details.php
<thead>
<tr>
<th class="woocommerce-table__product-name product-name"><?php _e( 'Product', 'woocommerce' ); ?></th>
<th class="woocommerce-table__product-image product-image"><?php _e( 'Image', 'woocommerce' ); ?></th>
<th class="woocommerce-table__product-table product-total"><?php _e( 'Total', 'woocommerce' ); ?></th>
</tr>
</thead>
order-details-item.php
<td class="woocommerce-table__product-name product-name"></td>
<td class="woocommerce-table__product-image product-image"><?php echo $product->get_image('thumbnail'); ?></td>
<td class="woocommerce-table__product-total product-total">
<?php echo $order->get_formatted_line_subtotal($item); ?>
</td>

Currently there is no such a hooks / filters to achieved your modifications as per your images. But it can be possible by overridden woocommerce follows templates -
Override "order-details.php" template by copying it to yourtheme/woocommerce/order/order-details.php to add your "Image" header.
Override "order-details-item.php" template by copying it to yourtheme/woocommerce/order/order-details-item.php to add your "Image" to display.

Related

Add optional additional fee to checkout

i am using this following code to show the option to add an additional fee (product) to the cart on the "cart" page. It is working great but it is now showing on the cart page, but how do i get it to show on the checkout page additionally:
<?php
/* ADD custom theme functions here */
add_filter( 'woocommerce_price_trim_zeros', 'wc_hide_trailing_zeros', 10, 1 );
function wc_hide_trailing_zeros( $trim ) {
return true;
}
add_action('woocommerce_cart_totals_after_shipping', 'wc_shipping_insurance_note_after_cart');
function wc_shipping_insurance_note_after_cart() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
I have tried different methods, and it should be pretty basic but i am rusty on my Functions.php skills.
You could try copying the function and giving it a new name. Then change the hook depending on where you want it on the checkout page.
Here is a great visual guide to the hooks on the checkout page: https://www.businessbloomer.com/woocommerce-visual-hook-guide-checkout-page/
Try something like this:
Notice how I changed the hook from woocommerce_cart_totals_after_shipping to woocommerce_before_checkout_form here you can experiment using the hooks on the guide I linked to. I also changed the name of the function from wc_shipping_insurance_note_after_cart to wc_shipping_insurance_note_after_checkout to avoid conflicts.
add_action('woocommerce_before_checkout_form', 'wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$product_id = 971;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ):
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php else: ?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php endif;
}
Edit per comment. You could try something like this if you only want to add the table row if a product in the cart has a certain category.
You will have to change "example-category" in $categories = array('example-category'); to your category slug.
add_action('woocommerce_before_checkout_form','wc_shipping_insurance_note_after_checkout');
function wc_shipping_insurance_note_after_checkout() {
global $woocommerce;
$categories = array('example-category');
$found = false;
//loop trough cart items
foreach ( WC()->cart->get_cart_contents() as $cart_item_key => $cart_item ) {
$product_id = $cart_item['product_id'];
//Check if product has category
if ( has_term( $categories, 'product_cat', $product_id ) ) {
$found = true;
}
}
// Do this if product has category
if ( $found ) {
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td><?php _e( 'Add ($3)' ); ?> </td>
</tr>
<?php
} else {
//If product does not have category do this instead
?>
<tr class="shipping">
<th><?php _e( 'Gift wrapper', 'woocommerce' ); ?></th>
<td>$3</td>
</tr>
<?php
}
}

Hide coupon discount on Woocommerce checkout [duplicate]

I'm using a coupon for a calculation in the Woocommerce cart. It automatically adds a discount to the total so the right amount can be sent to payments gateways.
I'd like to hide all infos about this coupons/discount from visitors.
Problem: The only method I've found (see below) hides the coupon field, row (from totals) and messages, but also disable the coupon...
add_filter( 'woocommerce_coupons_enabled', 'hide_coupon_field' );
function hide_coupon_field( $enabled ) {
if ( is_cart() || is_checkout() ) {
$enabled = false;
}
return $enabled;
}
Is there a hook allowing to hide everything related to the discount without canceling the coupon?
EDIT:
Looks like it's impossible to simply remove the discount line in the order-details. So a simple solution, inspired by helgatheviking suggestion, might be to remove all the totals generated by this part
<?php if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) : ?>
<tr>
<th scope="row"><?php echo $total['label']; ?></th>
<td><?php echo $total['value']; ?></td>
</tr>
<?php endforeach; ?>
And then to echo them one by one the way I need it. I'm already able to show the order total with this
<td><?php echo number_format($order->get_total(),2,'.','')."€"; ?></td>
but now I'm trying to retrieve the order subtotal, and this code
<td><?php echo number_format($order->get_item_subtotal(),2,'.','')."€"; ?></td>
gives me a Warning: Missing argument 1 for WC_Order::get_item_subtotal().
I'm not sure if get_item_subtotal() is the right way to get the order subtotal. And if so, what argument is missing? Or should I search around get_line_subtotal or get_subtotal_to_display?
No, there does not seem to be as there is no filter in the get_coupons() method of the cart class. If you went to the WooCommerce git repo and sent a pull request with a filter here and an explanation as to why it should be there, they might consider merging it in. I've done that a few times.
You could also, copy the checkout/review-order.php and cart/cart-totals.php templates into your theme and remove the following two blocks of code:
<?php foreach ( WC()->cart->get_coupons( 'cart' ) as $code => $coupon ) : ?>
<tr class="cart-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
and
<?php foreach ( WC()->cart->get_coupons( 'order' ) as $code => $coupon ) : ?>
<tr class="order-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
Keep in mind that this prevents the display of ALL coupon discounts and will end up looking like the following screenshots:
I'm not a fan of overriding the more complex WC templates... especially not the ones pertaining to the checkout process. I've had to fix many sites that stopped working when their theme template overrides became obsolete as WooCommerce develops.
Edit
I tracked down the Discount row in the order/order-details.php template. It is from the function $order->get_order_item_totals()... this returns an array of rows and can be filtered. So, this removes the row from the order received page:
function so_25714509_get_order_item_totals( $total_rows ){
unset( $total_rows['order_discount'] );
return $total_rows;
}
add_filter( 'woocommerce_get_order_item_totals', 'so_25714509_get_order_item_totals' );

Append a measuring unit to the quantity field in WooCommerce email notifications

I'd like to append a unit to the quantity field in the order confirmation email, more precisely in the order items table of that email (email-order-details.php)
See screenshot:
I've tried to add this line of PHP
`<?php echo '<p>VE</p>'; ?>`
into the HTML table in the template file, now my code looks like this:
<div style="margin-bottom: 40px;">
<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: 'Helvetica Neue', Helvetica, Roboto, Arial, sans-serif;" border="1">
<thead>
<tr>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?> <?php echo '<p>VE</p>'; ?></th>
<th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<tbody>
<?php
echo wc_get_email_order_items( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
$order,
array(
'show_sku' => $sent_to_admin,
'show_image' => false,
'image_size' => array( 32, 32 ),
'plain_text' => $plain_text,
'sent_to_admin' => $sent_to_admin,
)
);
?>
</tbody>
But my adjustment is not showing in the correct location. Can anyone help out with this and hint me in the right direction?
No need to edit/overwrite template files as you can just use the woocommerce_email_order_item_quantity filter hook
So you get:
function filter_woocommerce_email_order_item_quantity( $qty_display, $item ) {
$qty_display = $qty_display . ' VE';
return $qty_display;
}
add_filter( 'woocommerce_email_order_item_quantity', 'filter_woocommerce_email_order_item_quantity', 10, 2 );
Optional: if you don't want to apply this to all e-mail notifications but target specific ones, you can use:
// Setting the email_is as a global variable
function action_woocommerce_email_before_order_table( $order, $sent_to_admin, $plain_text, $email ) {
$GLOBALS['email_id_str'] = $email->id;
}
add_action( 'woocommerce_email_before_order_table', 'action_woocommerce_email_before_order_table', 10, 4 );
function filter_woocommerce_email_order_item_quantity( $qty_display, $item ) {
// Getting the email ID global variable
$refNameGlobalsVar = $GLOBALS;
$email_id = isset( $refNameGlobalsVar['email_id_str'] ) ? $refNameGlobalsVar['email_id_str'] : '';
// Targeting specific email. Multiple statuses can be added, separated by a comma
if ( in_array( $email_id, array( 'new_order' ) ) ) {
$qty_display = $qty_display . ' VE';
}
return $qty_display;
}
add_filter( 'woocommerce_email_order_item_quantity', 'filter_woocommerce_email_order_item_quantity', 10, 2 );
Also see: How to target other WooCommerce order emails
Code goes in functions.php file of the active child theme (or active theme).

Change sorting of WooCommerce customer orders --> orders.php [duplicate]

In WooCommerce, customers can log in to their account and see the order history. By default the orders are displaying with the newest order date first.
I want to turn this around, so the order with the oldest date shows first.
I can't find any place to change ordering from ASC/DESC, looking in the template file woocoommerce/myaccount/orders.php file.
<table class="woocommerce-orders-table woocommerce-MyAccount-orders shop_table shop_table_responsive my_account_orders account-orders-table">
<thead>
<tr>
<?php foreach ( wc_get_account_orders_columns() as $column_id => $column_name ) : ?>
<th class="woocommerce-orders-table__header woocommerce-orders-table__header-<?php echo esc_attr( $column_id ); ?>"><span class="nobr"><?php echo esc_html( $column_name ); ?></span></th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ( $customer_orders->orders as $customer_order ) :
Any way to alter the loop to display orders with the oldest date first?
The filter hook woocommerce_my_account_my_orders_query allows to change the 'order' argument to ASC (ascending), changing the sorting behavior on My account customer orders list:
add_filter( 'woocommerce_my_account_my_orders_query', 'my_account_orders_query_change_sorting' );
function my_account_orders_query_change_sorting( $args ) {
$args['order'] = 'ASC'; // Default is 'DESC'
return $args;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.

Hide discount infos without canceling the coupon in woocommerce

I'm using a coupon for a calculation in the Woocommerce cart. It automatically adds a discount to the total so the right amount can be sent to payments gateways.
I'd like to hide all infos about this coupons/discount from visitors.
Problem: The only method I've found (see below) hides the coupon field, row (from totals) and messages, but also disable the coupon...
add_filter( 'woocommerce_coupons_enabled', 'hide_coupon_field' );
function hide_coupon_field( $enabled ) {
if ( is_cart() || is_checkout() ) {
$enabled = false;
}
return $enabled;
}
Is there a hook allowing to hide everything related to the discount without canceling the coupon?
EDIT:
Looks like it's impossible to simply remove the discount line in the order-details. So a simple solution, inspired by helgatheviking suggestion, might be to remove all the totals generated by this part
<?php if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) : ?>
<tr>
<th scope="row"><?php echo $total['label']; ?></th>
<td><?php echo $total['value']; ?></td>
</tr>
<?php endforeach; ?>
And then to echo them one by one the way I need it. I'm already able to show the order total with this
<td><?php echo number_format($order->get_total(),2,'.','')."€"; ?></td>
but now I'm trying to retrieve the order subtotal, and this code
<td><?php echo number_format($order->get_item_subtotal(),2,'.','')."€"; ?></td>
gives me a Warning: Missing argument 1 for WC_Order::get_item_subtotal().
I'm not sure if get_item_subtotal() is the right way to get the order subtotal. And if so, what argument is missing? Or should I search around get_line_subtotal or get_subtotal_to_display?
No, there does not seem to be as there is no filter in the get_coupons() method of the cart class. If you went to the WooCommerce git repo and sent a pull request with a filter here and an explanation as to why it should be there, they might consider merging it in. I've done that a few times.
You could also, copy the checkout/review-order.php and cart/cart-totals.php templates into your theme and remove the following two blocks of code:
<?php foreach ( WC()->cart->get_coupons( 'cart' ) as $code => $coupon ) : ?>
<tr class="cart-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
and
<?php foreach ( WC()->cart->get_coupons( 'order' ) as $code => $coupon ) : ?>
<tr class="order-discount coupon-<?php echo esc_attr( $code ); ?>">
<th><?php wc_cart_totals_coupon_label( $coupon ); ?></th>
<td><?php wc_cart_totals_coupon_html( $coupon ); ?></td>
</tr>
<?php endforeach; ?>
Keep in mind that this prevents the display of ALL coupon discounts and will end up looking like the following screenshots:
I'm not a fan of overriding the more complex WC templates... especially not the ones pertaining to the checkout process. I've had to fix many sites that stopped working when their theme template overrides became obsolete as WooCommerce develops.
Edit
I tracked down the Discount row in the order/order-details.php template. It is from the function $order->get_order_item_totals()... this returns an array of rows and can be filtered. So, this removes the row from the order received page:
function so_25714509_get_order_item_totals( $total_rows ){
unset( $total_rows['order_discount'] );
return $total_rows;
}
add_filter( 'woocommerce_get_order_item_totals', 'so_25714509_get_order_item_totals' );

Resources