Add extra packaging options through radio buttons in WooCommerce checkout - php

Based on Update fee dynamically based on radio buttons in Woocommerce checkout anser code. I'm trying to make it work with different packaging options on WooCommerce checkout.
The idea is to be able to provide options for gift wrapping, packaging in a bag and so forth.
Problem is, it gives me selectable options but it's all messed up as it is printing out the HTML for the tags and what not.
This is the code I am working with:
add_action( 'woocommerce_form_field_radio', 'gift_bag_none', 20, 4 );
function gift_bag_none( $field, $key, $args, $value ) {
if ( ! empty( $args['options'] ) && is_checkout() ) {
$field = str_replace( '</label><input ', '</label><br><input ', $field );
$field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
}
return $field;
}
add_action( 'woocommerce_cart_calculate_fees', 'gift_bag_none_fee', 20, 1 );
function gift_bag_none_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$packing_fee = WC()->session->get( 'chosen_packing' );
if( $packing_fee === 'box' )
$fee = 29.00;
else if( $packing_fee === 'none' )
$fee = 0.00;
else if( $packing_fee === 'both' )
$fee = 25.00;
else
$fee = 5.00;
$cart->add_fee( __( 'Packaging Cost', 'woocommerce' ), $fee );
}
add_action( 'woocommerce_review_order_after_shipping', 'checkout_packing_addition', 20 );
function checkout_packing_addition() {
$domain = 'woocommerce';
echo '<tr><th>' . __('Packaging Options', $domain) . '</th><td>';
echo '<tr class="packing-select"><th>' . __('In a bag?<br>Boxed and wrapped as gift?<br><span style="color:red;">Boxed, wrapped and in a bag?</span><br>Or just the product?', $domain) . '</th><td>';
$chosen = WC()->session->get('chosen_packing');
$chosen = empty($chosen) ? WC()->checkout->get_value('radio_packing') : $chosen;
$chosen = empty($chosen) ? 'none' : $chosen;
woocommerce_form_field( 'radio_packing', array(
'type' => 'radio',
'class' => array( 'form-row-wide packing' ),
'options' => array(
'bag' => __('Yes, give it to me in a bag for '.wc_price(5.00), $domain),
'box' => __('Giftbox + Wrapping for '.wc_price(29.00), $domain),
'both' => __('Wrapped Giftbox in a Bag for '.wc_price(25.00), $domain),
'none' => __('Just the product at no extra cost '.wc_price(0.00), $domain)
),
'default' => $chosen,
), $chosen );
echo '</td></tr>';
}
add_action( 'wp_footer', 'checkout_packing_script' );
function checkout_packing_script(){ ?>
<script type="text/javascript">
jQuery( function($) {
$('form.checkout').on('change', 'input[name=radio_packing]', function(e){
e.preventDefault();
var p = $(this).val();
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'packing': p,
},
success: function (result) {
$('body').trigger('update_checkout');
},
error: function(error){
}
});
});
});
</script>
<?php
}
add_action('wp_ajax_woo_get_ajax_data', 'packing_ajax_data');
add_action('wp_ajax_nopriv_woo_get_ajax_data', 'packing_ajax_data');
function packing_ajax_data() {
if ( isset($_POST['packing']) ){
$packing = sanitize_key( $_POST['packing'] );
WC()->session->set('chosen_packing', $packing );
echo json_encode( $packing );
}
die();
}

Updated: 10/2021 - tested in WordPress 5.8.1 & WooCommerce 5.7.1
Your code has some minor mistakes
Use add_filter( 'woocommerce_form_field_radio' instead of add_action(..
Use strip_tags( wc_price() ) against wc_price()
So you get:
// Customizing WooCommerce radio form field
function filter_woocommerce_form_field_radio( $field, $key, $args, $value ) {
// Specific key and apply on checkout page
if ( ! empty( $args['options'] ) && $key == 'radio_packing' && is_checkout() ) {
$field = str_replace( '</label><input ', '</label><br><input ', $field );
$field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
}
return $field;
}
add_filter( 'woocommerce_form_field_radio', 'filter_woocommerce_form_field_radio', 20, 4 );
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Dynamic packing fee
$packing_fee = WC()->session->get( 'chosen_packing' );
// Determine packing fee
if ( $packing_fee === 'bag' ) {
$fee = 5.00;
} else if( $packing_fee === 'box' ) {
$fee = 29.00;
} else if( $packing_fee === 'both' ) {
$fee = 25.00;
} else {
$fee = 0.00;
}
// Add fee: name - amount - taxable
$cart->add_fee( __( 'Packaging fee', 'woocommerce' ), $fee, true );
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
// Add a custom radio fields for packaging selection
function action_woocommerce_review_order_after_shipping() {
// Domain
$domain = 'woocommerce';
// Output
echo '<tr class="packing-select"><th>' . __('Packing options', $domain ) . '</th><td>';
$chosen = WC()->session->get( 'chosen_packing' );
$chosen = empty( $chosen ) ? WC()->checkout->get_value( 'radio_packing' ) : $chosen;
$chosen = empty( $chosen ) ? 'none' : $chosen;
// Add a custom checkbox field
woocommerce_form_field( 'radio_packing', array(
'type' => 'radio',
'class' => array( 'form-row-wide packing' ),
'options' => array(
'bag' => sprintf( __( 'Yes, give it to me in a bag for %s', $domain ), strip_tags( wc_price( 5.00 ) ) ),
'box' => sprintf( __( 'Giftbox + Wrapping for %s', $domain ), strip_tags( wc_price( 29.00 ) ) ),
'both' => sprintf( __( 'Wrapped Giftbox in a Bag for %s', $domain ), strip_tags( wc_price( 25.00 ) ) ),
'none' => sprintf( __( 'Just the product at no extra cost %s', $domain ), strip_tags( wc_price( 0.00 ) ) )
),
'default' => $chosen,
), $chosen );
echo '</td></tr>';
}
add_action( 'woocommerce_review_order_after_shipping', 'action_woocommerce_review_order_after_shipping', 10, 0 );
// jQuery - Ajax script
function action_wp_footer() {
if ( ! is_checkout() )
return; // Only checkout page
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'input[name=radio_packing]', function(e){
e.preventDefault();
var p = $(this).val();
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'packing': p,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log('response: '+result); // just for testing | TO BE REMOVED
},
error: function(error){
console.log(error); // just for testing | TO BE REMOVED
}
});
});
});
</script>
<?php
}
add_action( 'wp_footer', 'action_wp_footer', 10, 0 );
// Php Ajax (Receiving request and saving to WC session)
function woo_get_ajax_data() {
if ( isset($_POST['packing']) ){
$packing = sanitize_key( $_POST['packing'] );
WC()->session->set('chosen_packing', $packing );
echo json_encode( $packing );
}
die(); // Always at the end (to avoid server error 500)
}
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );

Related

Woocommerce Checkout Custom Field: Selected option is "forgotten" if I browse another page and return to checkout page

I have created a custom checkout field related to packaging and with different price options.
It works nicely if I complete my order, all options are saved and appearing on thank you page/order email/admin edit order.
But, the issue is that if I select an option from this custom field and then continue browsing to another page, if I then go to checkout page again, the previously selected option is not displayed, somehow forgotten.
Can someone help me with adjustments to my code so that the options are saved and not forgotten?
Code is this (taken from this topic Add a dynamic fee based on a select field in WooCommerce Checkout and adjusted to suit my needs):
//Add a custom select fields for packing option fee
add_action( 'woocommerce_checkout_before_order_review', 'checkout_shipping_form_packing_addition', 40 );
function checkout_shipping_form_packing_addition( ) {
$domain = 'woocommerce';
echo '<tr class="packing-select"><th><h3>' . __('Packaging', $domain) . '</h3></th><td>';
$chosen = WC()->session->get('chosen_packing');
// Add a custom checkbox field
woocommerce_form_field( 'chosen_packing', array(
'type' => 'select',
'label' => __('Choose regular or gift-wrap packaging:', $domain ),
'class' => array( 'form-row-wide packing' ),
'options' => array(
'' => __("Select an option:", $domain),
'bag' => sprintf( __("Regular (free)", $domain), strip_tags( wc_price(0.00) ) ),
'box1' => sprintf( __("Gift-wrap (1): 0,50€", $domain), strip_tags( wc_price(0.50) ) ),
'box2' => sprintf( __("Gift-wrap (2): 1,00€", $domain), strip_tags( wc_price(1.00) ) ),
'box3' => sprintf( __("Gift-wrap (3): 1,50€", $domain), strip_tags( wc_price(1.50) ) ),
'box4' => sprintf( __("Gift-wrap (4): 2,00€", $domain), strip_tags( wc_price(2.00) ) ),
'box5' => sprintf( __("Gift-wrap (5): 2,50€", $domain), strip_tags( wc_price(2.50) ) ),
'box6' => sprintf( __("Gift-wrap (6): 3,00€", $domain), strip_tags( wc_price(3.00) ) ),
'box7' => sprintf( __("Gift-wrap (7): 3,50€", $domain), strip_tags( wc_price(3.50) ) ),
'box8' => sprintf( __("Gift-wrap (8): 4,00€", $domain), strip_tags( wc_price(4.00) ) ),
'box9' => sprintf( __("Gift-wrap (9): 4,50€", $domain), strip_tags( wc_price(4.50) ) ),
'box10' => sprintf( __("Gift-wrap (10+): 5,00€", $domain), strip_tags( wc_price(5.00) ) ),
),
'required' => true,
), $chosen );
echo '</th><td>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_shipping_packing_script' );
function checkout_shipping_packing_script() {
// Only checkout page
if ( is_checkout() && ! is_wc_endpoint_url() ) :
WC()->session->__unset('chosen_packing');
?>
<script type="text/javascript">
jQuery( function($){
$('form.checkout').on('change', 'select#chosen_packing', function(){
var p = $(this).val();
console.log(p);
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'packing': p,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log('response: '+result); // just for testing | TO BE REMOVED
},
error: function(error){
console.log(error); // just for testing | TO BE REMOVED
}
});
});
});
</script>
<?php
endif;
}
// Php Ajax (Receiving request and saving to WC session)
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );
function woo_get_ajax_data() {
if ( isset($_POST['packing']) ){
$packing = sanitize_key( $_POST['packing'] );
WC()->session->set('chosen_packing', $packing );
echo json_encode( $packing );
}
die(); // Alway at the end (to avoid server error 500)
}
// Add a custom dynamic packaging fee
add_action( 'woocommerce_cart_calculate_fees', 'add_packaging_fee', 20, 1 );
function add_packaging_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$domain = "woocommerce";
$packing_fee = WC()->session->get( 'chosen_packing' ); // Dynamic packing fee
if ( $packing_fee === 'bag' ) {
$label = __("Regular (free)", $domain);
$cost = 0.00;
} elseif ( $packing_fee === 'box1' ) {
$label = __("Giftwrap (1)", $domain);
$cost = 0.50;
} elseif ( $packing_fee === 'box2' ) {
$label = __("Giftwrap (2)", $domain);
$cost = 1.00;
} elseif ( $packing_fee === 'box3' ) {
$label = __("Giftwrap (3)", $domain);
$cost = 1.50;
} elseif ( $packing_fee === 'box4' ) {
$label = __("Giftwrap (4)", $domain);
$cost = 2.00;
} elseif ( $packing_fee === 'box5' ) {
$label = __("Giftwrap (5)", $domain);
$cost = 2.50;
} elseif ( $packing_fee === 'box6' ) {
$label = __("Giftwrap (6)", $domain);
$cost = 3.00;
} elseif ( $packing_fee === 'box7' ) {
$label = __("Giftwrap (7)", $domain);
$cost = 3.50;
} elseif ( $packing_fee === 'box8' ) {
$label = __("Giftwrap (8)", $domain);
$cost = 4.00;
} elseif ( $packing_fee === 'box9' ) {
$label = __("Giftwrap (9)", $domain);
$cost = 4.50;
} elseif ( $packing_fee === 'box10' ) {
$label = __("Giftwrap (10+)", $domain);
$cost = 5.00;
}
if ( isset($cost) )
$cart->add_fee( $label, $cost );
}
// Field validation, as this packing field is required
add_action('woocommerce_checkout_process', 'packing_field_checkout_process');
function packing_field_checkout_process() {
// Check if set, if its not set add an error.
if ( isset($_POST['chosen_packing']) && empty($_POST['chosen_packing']) )
wc_add_notice( __( "<strong>Packaging</strong> is a required field.", "woocommerce" ), 'error' );
}
Excuse my linguistic mistakes, english is not my native language.

Hide checkbox (with code) for other Nations

I need help with this code that i found on a blog:
// Display the custom checkbow field in checkout
add_action( 'woocommerce_review_order_before_order_total', 'fee_installment_checkbox_field', 20 );
function fee_installment_checkbox_field(){
echo '<tr class="packing-select"><th>';
woocommerce_form_field( 'installment_fee', array(
'type' => 'checkbox',
'class' => array('installment-fee form-row-wide'),
'label' => __('Consegna su appuntamento'),
'placeholder' => __(''),
), WC()->session->get('installment_fee') ? '1' : '' );
echo '</th><td>';
}
// jQuery - Ajax script
add_action( 'wp_footer', 'checkout_fee_script' );
function checkout_fee_script() {
// Only on Checkout
if( is_checkout() && ! is_wc_endpoint_url() ) :
if( WC()->session->__isset('installment_fee') )
WC()->session->__unset('installment_fee')
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on('change', 'input[name=installment_fee]', function(){
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'installment_fee',
'installment_fee': fee,
},
success: function (result) {
$('body').trigger('update_checkout');
},
});
});
});
</script>
<?php
endif;
}
// Get Ajax request and saving to WC session
add_action( 'wp_ajax_installment_fee', 'get_installment_fee' );
add_action( 'wp_ajax_nopriv_installment_fee', 'get_installment_fee' );
function get_installment_fee() {
if ( isset($_POST['installment_fee']) ) {
WC()->session->set('installment_fee', ($_POST['installment_fee'] ? true : false) );
}
die();
}
// Add a custom calculated fee conditionally
add_action( 'woocommerce_cart_calculate_fees', 'set_installment_fee' );
function set_installment_fee( $cart ){
if ( is_admin() && ! defined('DOING_AJAX') || ! is_checkout() )
return;
if ( did_action('woocommerce_cart_calculate_fees') >= 2 )
return;
if ( 1 == WC()->session->get('installment_fee') ) {
$items_count = WC()->cart->get_cart_contents_count();
$fee_label = sprintf( __( "Consegna su appuntamento" ), '×', $items_count );
$fee_amount = 4;
WC()->cart->add_fee( $fee_label, $fee_amount );
}
}
add_filter( 'woocommerce_form_field' , 'remove_optional_txt_from_installment_checkbox', 10, 4 );
function remove_optional_txt_from_installment_checkbox( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'installment_fee' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
I want to hide this checkbox in checkout page if the customer Nation is not Italy. Thank you!
I've added a checkbox in checkout page, and now i expect to hide this checkbox if the customer nation is not Italy (so this checkbox will be only visible for Italian customers

WooCommerce checkout radio buttons that set a percentage fee based on the original price of a specific product

I am trying to implement warranty option into woocommerce checkout. The below code works really well for setting a percentage fee based on specific items 'subtotal' amount.
// Custom function to get related cart items subtotal for specific defined product Ids
function get_related_items_subtotal( $cart ) {
// HERE below define the related targeted products IDs in the array
$targeted_ids = array(29, 27, 28, 72, 84, 95);
$custom_subtotal = 0; // Initialize
// Loop through cart items
foreach ( $cart->get_cart() as $item ) {
if ( array_intersect($targeted_ids, array($item['product_id'], $item['variation_id']) ) ) {
$custom_subtotal += $item['line_subtotal'] + $item['line_subtotal_tax'];
}
}
return $custom_subtotal;
}
// 1 - Display custom checkout radio buttons fields
add_action( 'woocommerce_review_order_before_payment', 'display_custom_checkout_radio_buttons' );
function display_custom_checkout_radio_buttons() {
$custom_subtotal = get_related_items_subtotal( WC()->cart );
if ( $custom_subtotal > 0 ) {
$value = WC()->session->get( 'warranty' );
$value = empty( $value ) ? WC()->checkout->get_value( 'warranty' ) : $value;
$value = empty( $value ) ? '0' : $value;
echo '<div id="checkout-radio">
<h4>' . __("Choose your Warranty") .'</h4>';
woocommerce_form_field( 'warranty', array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'0' => __( '1 Year Repair or Replace Warranty - Included', 'woocommerce' ),
'10' => __( '2 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 10 * $custom_subtotal / 100 ) ) . ')',
'15' => __( '3 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 15 * $custom_subtotal / 100 ) ) . ')',
),
), $value );
echo '</div>';
}
}
// 2 - Customizing Woocommerce checkout radio form field
add_filter( 'woocommerce_form_field_radio', 'custom_form_field_radio', 20, 4 );
function custom_form_field_radio( $field, $key, $args, $value ) {
if ( ! empty( $args['options'] ) && 'warranty' === $key && is_checkout() ) {
$field = str_replace( '</label><input ', '</label><br><input ', $field );
$field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
}
return $field;
}
// 3 - Add a percentage Fee based on radio buttons for specific defined product Ids
add_action( 'woocommerce_cart_calculate_fees', 'percentage_fee_based_on_radio_buttons', 20 );
function percentage_fee_based_on_radio_buttons( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$percentage = (float) WC()->session->get( 'warranty' );
if ( $percentage ) {
$custom_subtotal = get_related_items_subtotal( $cart );
if ( $custom_subtotal > 0 ) {
$label_text = sprintf( __('Extended Warranty %d years', 'woocommerce'), $percentage == 10 ? 2 : 3 );
$cart->add_fee( $label_text, $custom_subtotal * $percentage / 100 );
}
}
}
// 4 - Set chosen radio button value to a WC Session variable
add_action( 'woocommerce_checkout_update_order_review', 'chosen_input_radio_button_value_to_wc_session' );
function chosen_input_radio_button_value_to_wc_session( $posted_data ) {
parse_str( $posted_data, $fields );
if ( isset( $fields['warranty'] ) ){
WC()->session->set( 'warranty', $fields['warranty'] );
}
}
Is there a way to output the calculated warranty amount options based on the original price of a specific product and NOT on the 'subtotal' amount? I'm thinking to target a price to be the basis of the calculation whose SKU contains some specific words. Is this possible? Please advise.
I added some code to get_related_items_subtotal() to check with SKU. Check the below code.
// Custom function to get related cart items subtotal for specific defined product Ids
function get_related_items_subtotal( $cart ) {
// HERE below define the related targeted products IDs in the array
$targeted_skus = array('BCA', 'ABC', 'MPN', 'A4545A', '5656FGDF', 'FDF4FD');
$custom_subtotal = 0; // Initialize
// Loop through cart items
foreach ( $cart->get_cart() as $item ) {
// Retrieve WC_Product object from the product-id:
$product = wc_get_product( $item["variation_id"] ? $item["variation_id"] : $item["product_id"] );
$sku = $product->get_sku();
if( is_string_contain_word( $sku, $targeted_skus ) ){
$custom_subtotal += $item['line_subtotal'] + $item['line_subtotal_tax'];
}
}
return $custom_subtotal;
}
// 1 - Display custom checkout radio buttons fields
add_action( 'woocommerce_review_order_before_payment', 'display_custom_checkout_radio_buttons' );
function display_custom_checkout_radio_buttons() {
$custom_subtotal = get_related_items_subtotal( WC()->cart );
if ( $custom_subtotal > 0 ) {
$value = WC()->session->get( 'warranty' );
$value = empty( $value ) ? WC()->checkout->get_value( 'warranty' ) : $value;
$value = empty( $value ) ? '0' : $value;
echo '<div id="checkout-radio">
<h4>' . __("Choose your Warranty") .'</h4>';
woocommerce_form_field( 'warranty', array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'0' => __( '1 Year Repair or Replace Warranty - Included', 'woocommerce' ),
'10' => __( '2 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 10 * $custom_subtotal / 100 ) ) . ')',
'15' => __( '3 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 15 * $custom_subtotal / 100 ) ) . ')',
),
), $value );
echo '</div>';
}
}
// 2 - Customizing Woocommerce checkout radio form field
add_filter( 'woocommerce_form_field_radio', 'custom_form_field_radio', 20, 4 );
function custom_form_field_radio( $field, $key, $args, $value ) {
if ( ! empty( $args['options'] ) && 'warranty' === $key && is_checkout() ) {
$field = str_replace( '</label><input ', '</label><br><input ', $field );
$field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
}
return $field;
}
// 3 - Add a percentage Fee based on radio buttons for specific defined product Ids
add_action( 'woocommerce_cart_calculate_fees', 'percentage_fee_based_on_radio_buttons', 20 );
function percentage_fee_based_on_radio_buttons( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$percentage = (float) WC()->session->get( 'warranty' );
if ( $percentage ) {
$custom_subtotal = get_related_items_subtotal( $cart );
if ( $custom_subtotal > 0 ) {
$label_text = sprintf( __('Extended Warranty %d years', 'woocommerce'), $percentage == 10 ? 2 : 3 );
$cart->add_fee( $label_text, $custom_subtotal * $percentage / 100 );
}
}
}
// 4 - Set chosen radio button value to a WC Session variable
add_action( 'woocommerce_checkout_update_order_review', 'chosen_input_radio_button_value_to_wc_session' );
function chosen_input_radio_button_value_to_wc_session( $posted_data ) {
parse_str( $posted_data, $fields );
if ( isset( $fields['warranty'] ) ){
WC()->session->set( 'warranty', $fields['warranty'] );
}
}
function is_string_contain_word( $find, $string, $exact = false ){
if( is_array( $string ) ){
foreach ( $string as $key => $str ) {
if( !$exact ){
$find = strtolower( $find );
$str = strtolower( $str );
}
if ( preg_match( '/\b'.$find.'\b/', $str ) ) {
return true;
}
}
return false;
}else{
if( !$exact ){
$find = strtolower( $find );
$string = strtolower( $string );
}
if ( preg_match( '/\b'.$find.'\b/', $string ) ) {
return true;
}
return false;
}
}

Add Delivery Radio Buttons before order total in WooCommerce checkout

I am writing a WordPress plugin in which I need to add two radio buttons before the order total in the WooCommerce Order review section. I figured out how to add custom radio buttons to the order review section but I am unable to get the idea how to move delivery options just before the order total.
Please check the screenshot to understand what exactly I want to achieve.
Here's my code:
// Part 1 - Display Radio Buttons
add_action( 'woocommerce_review_order_before_payment', 'custom_checkout_radio_choice' );
function custom_checkout_radio_choice() {
$chosen = WC()->session->get( 'radio_chosen' );
$chosen = empty( $chosen ) ? WC()->checkout->get_value( 'radio_choice' ) : $chosen;
$chosen = empty( $chosen ) ? '0' : $chosen;
$args = array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'2.95' => '60 MINUTES: €2.95',
'0' => '24 - 48 HOURS',
),
'default' => $chosen
);
echo '<div id="checkout-radio">';
echo '<h3>Delivery Options</h3>';
woocommerce_form_field( 'radio_choice', $args, $chosen );
echo '</div>';
}
// Part 2 - Add Fee and Calculate Total
add_action( 'woocommerce_cart_calculate_fees', 'custom_checkout_radio_choice_fee', 20, 1 );
function custom_checkout_radio_choice_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$radio = WC()->session->get( 'radio_chosen' );
if ( $radio ) {
$cart->add_fee( 'Delivery Fee', $radio );
}
}
// Part 3 - Add Radio Choice to Session
add_action( 'woocommerce_checkout_update_order_review', 'custom_checkout_radio_choice_set_session' );
function custom_checkout_radio_choice_set_session( $posted_data ) {
parse_str( $posted_data, $output );
if ( isset( $output['radio_choice'] ) ){
WC()->session->set( 'radio_chosen', $output['radio_choice'] );
}
}
Please help me out with this.
To move your radio buttons before order total you will need to use another hook. But you can't have that delivery radio buttons on the fee total line…
I have simplified and revisited the code:
add_action( 'woocommerce_review_order_before_order_total', 'checkout_delivery_radio_buttons' );
function checkout_delivery_radio_buttons() {
echo '<tr class="delivery-radio">
<th>'.__("Delivery Options").'</th><td>';
$chosen = WC()->session->get( 'delivery' );
$chosen = empty( $chosen ) ? WC()->checkout->get_value( 'delivery' ) : $chosen;
$chosen = empty( $chosen ) ? '0' : $chosen;
woocommerce_form_field( 'delivery', array(
'type' => 'radio',
'class' => array( 'form-row-wide', 'update_totals_on_change' ),
'options' => array(
'2.95' => '60 MINUTES: €2.95',
'0' => '24 - 48 HOURS',
),
), $chosen );
echo '</td></tr>';
}
add_action( 'woocommerce_cart_calculate_fees', 'checkout_delivery_fee', 20, 1 );
function checkout_delivery_fee( $cart ) {
if ( $radio = WC()->session->get( 'delivery' ) ) {
$cart->add_fee( 'Delivery Fee', $radio );
}
}
add_action( 'woocommerce_checkout_update_order_review', 'checkout_delivery_choice_to_session' );
function checkout_delivery_choice_to_session( $posted_data ) {
parse_str( $posted_data, $output );
if ( isset( $output['delivery'] ) ){
WC()->session->set( 'delivery', $output['delivery'] );
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Calculate and show the new price after choosing the weight of the product in WooCommerce

In WooCommerce, I use a code that shows the steak weight selection form, saves the selection data and displays this data in the cart, on the checkout page, when editing the order and in email notifications.
// Display Custom Checkbox Field
add_action('woocommerce_product_options_general_product_data', 'steak_custom_field_add');
function steak_custom_field_add(){
global $post;
// Checkbox
woocommerce_wp_checkbox(
array(
'id' => '_steak_checkbox',
'label' => __('Steak Weight', 'woocommerce' ),
'description' => __( 'If necessary, enable steak weight selection', 'woocommerce' )
)
);
}
// Save Custom Checkbox Field
add_action('woocommerce_process_product_meta', 'steak_custom_field_save');
function steak_custom_field_save($post_id){
// Custom Product Checkbox Field
$steak_checkbox = isset( $_POST['_steak_checkbox'] ) ? 'yes' : 'no';
update_post_meta($post_id, '_steak_checkbox', esc_attr( $steak_checkbox ));
}
// Display Custom Select Box
add_action( 'woocommerce_before_add_to_cart_button', 'display_steak_custom_field', 0 );
function display_steak_custom_field() {
global $product;
// If is single product page and have the "steak_checkbox" enabled we display the field
if ( $product->get_meta( '_steak_checkbox' ) === 'yes' ) {
echo '<div class="steak_select_box">';
$select = woocommerce_form_field( 'steak_custom_options', array(
'type' => 'select',
'class' => array('my-steak-select-box form-row-wide'),
'label' => __('Steak Weight'),
'required' => false,
'return' => false,
'options' => array(
'' => 'Select...',
'300g' => '300g',
'400g' => '400g',
'500g' => '500g',
'600g' => '600g',
'700g' => '700g',
'800g' => '800g',
'900g' => '900g',
'1000g' => '1000g'
)
), '' );
echo $select;
echo '</div>';
}
}
// Add as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_steak_cart_item_data', 10, 21 );
function add_custom_steak_cart_item_data($cart_item_data, $product_id, $variation_id ){
if( isset( $_POST['steak_custom_options'] ) ) {
$cart_item_data['steak_option'] = wc_clean( $_POST['steak_custom_options'] );
}
return $cart_item_data;
}
// Add custom fields values under cart item name in cart
add_filter( 'woocommerce_cart_item_name', 'steak_custom_field_add_cart', 10, 21 );
function steak_custom_field_add_cart( $item_name, $cart_item, $cart_item_key ) {
if( ! is_cart() )
return $item_name;
if( isset($cart_item['steak_option']) ) {
$item_name .= '<div class="my-steak-class"><strong>' . __("Steak Weight", "woocommerce") . ':</strong> ' . $cart_item['steak_option'] . '</div>';
}
return $item_name;
}
// Display custom fields values under item name in checkout
add_filter( 'woocommerce_checkout_cart_item_quantity', 'steak_custom_checkout_cart_item_name', 10, 21 );
function steak_custom_checkout_cart_item_name( $item_qty, $cart_item, $cart_item_key ) {
if( isset($cart_item['steak_option']) ) {
$item_qty .= '<div class="my-steak-class"><strong>' . __("Steak Weight", "woocommerce") . ':</strong> ' . $cart_item['steak_option'] . 'гр.</div>';
}
return $item_qty;
}
// Save chosen select field value to each order item as custom meta data and display it everywhere
add_action('woocommerce_checkout_create_order_line_item', 'save_order_item_steak_field', 10, 21 );
function save_order_item_steak_field( $item, $cart_item_key, $values, $order ) {
if( isset($values['steak_option']) ) {
$key = __('Steak Weight', 'woocommerce');
$value = $values['steak_option'];
$item->update_meta_data( $key, $value ,$item->get_id());
}
}
add_action('wp_footer','add_footer_steak_script');
function add_footer_steak_script(){
?>
<script>
( function( $ ) {
$( document ).ready( function() {
$(document).on('change', '#steak_custom_options' ,function() {
$('.add_to_cart_button').data('steak_custom_options', this.value)
});
});
}( jQuery ) );
</script>
<?php
}
But unfortunately, I do not know how to solve one problem ...
The price of this product is calculated per 100 grams. The minimum order quantity is 300 grams. And I need that, when choosing the weight of the product, the final cost of this product should be calculated accordingly.
For example:
for 300g - $regular_price * 3 = $new_price
for 500g - $regular_price * 5 = $new_price
for 1000g - $regular_price * 10 = $new_price
etc.
The total cost of this product should be shown next to the main price per 100 grams.
I think this code will be useful to other developers as well. I will be very happy for your help!
To adjust the product price, on the cart page, etc.. based on the weight selected from the dropdown, add the following code
function my_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if( isset( $cart_item['steak_option'] ) ) {
// Remove the last 2 zeros (100g becomes 1, 300g becomes 3, 1000g becomes 10, etc...)
// Remove 'g' from grams
// convert string to integer
$chosen_weight = (int) str_replace( '00', '', str_replace('g', '', $cart_item['steak_option']) );
// Get current price
$current_price = $cart_item['data']->get_price();
// Set new price, price is already known per 100g
$cart_item['data']->set_price( $current_price * $chosen_weight );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'my_before_calculate_totals', 10, 1 );
To change the price on the single product page, based on the dropdown menu, add this
function add_footer_steak_script() {
global $woocommerce, $product;
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
console.log('JS works!');
var price = <?php echo $product->get_price(); ?>, currency = '<?php echo get_woocommerce_currency_symbol(); ?>';
$( '[name=steak_custom_options]' ).change(function(){
if (!(this.value < 1)) {
var dropdown_val = this.value;
var remove_g = dropdown_val.replace( 'g', '' );
var remove_double_zero = remove_g.replace( '00', '' );
var product_total = parseFloat( price * remove_double_zero );
$( '.woocommerce-Price-amount' ).html( currency + product_total.toFixed(2));
}
});
});
</script>
<?php
}
add_action('wp_footer','add_footer_steak_script');

Categories