Reputation: 155
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
}
add_action( 'woocommerce_before_calculate_totals', 'my_before_calculate_totals', 10, 1 );
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('wp_footer','add_footer_steak_script');
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
}
I also use a code that automatically adds packaging when adding any dish to the cart.
/**
* Calculate the number of lunchboxes and package, based on the number of products in cart.
*/
function add_delivery_charge_to_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
/********** SETTINGS **********/
$lunchbox_id = 5737; // "LunchBox ID" to be added to cart
$pakket_id = 5738; // "Pakket ID" to be added to cart
$exclude_categories = array( 'drink', 'bread' ); // Exclude these categories
$category_qty_total = 0; // Total of category quantity items, Don't edit!!
/********** LOOP THROUGH CART ITEMS **********/
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get product id
$product_id = $cart_item['data']->get_id();
// Get product quantity
$product_qty = $cart_item['quantity'];
// Check if "LunchBox" product is already in cart
if( $product_id == $lunchbox_id ) {
$lunchbox_key = $cart_item_key;
$lunchbox_qty = $product_qty;
}
// Check if "Pakket" product is already in cart
if( $product_id == $pakket_id ) {
$pakket_key = $cart_item_key;
$pakket_qty = $product_qty;
}
// Check if product belongs to a certain category
if( has_term( $exclude_categories, 'product_cat', $product_id ) ) {
$category_qty_total += $product_qty;
}
}
/********** CALCULATE THE TOTALS, SO "LUNCHBOX", "PAKKET" & CATEGORIES ARE NOT USED IN THE TOTALS **********/
// Get total items in cart, counts number of products & quantity per product
$total_items_in_cart = $cart->get_cart_contents_count();
// Total items in cart - category quantity total
$total_items_in_cart -= $category_qty_total;
// Lunchbox total = total_items_in_cart & pakket total = total_items_in_cart
$lunchbox_total = $total_items_in_cart;
$pakket_total = $total_items_in_cart;
// Isset lunchbox qty -> lunchbox total - lunchbox qty & pakket total - lunchbox qty
if ( isset($lunchbox_qty) ) {
$lunchbox_total -= $lunchbox_qty;
$pakket_total -= $lunchbox_qty;
}
// Isset pakket qty -> lunchbox total - pakket qty & pakket total - pakket qty
if ( isset($pakket_qty) ) {
$lunchbox_total -= $pakket_qty;
$pakket_total = $pakket_total - $pakket_qty;
}
/********** APPLY NEW TOTALS TO LUNCHBOX & PAKKET **********/
// If product "LunchBox" is in cart, we check the quantity to update it if needed
if ( isset($lunchbox_key) && $lunchbox_qty != $total_items_in_cart ) {
// Set quantity, lunchbox
$cart->set_quantity( $lunchbox_key, $lunchbox_total );
} elseif ( !isset($lunchbox_key) && $total_items_in_cart > 0 ) {
// Product "LunchBox" is not in cart, we add it
$cart->add_to_cart( $lunchbox_id, $total_items_in_cart );
}
// Total items in cart greater than or equal to 3
if ( $total_items_in_cart >= 3 ) {
// Pakket total = pakket_total / 3 = floor(result)
// Floor = round fractions down, rounding result down
$pakket_total = floor( $pakket_total / 3 );
// If product "Pakket" is in cart
if ( isset($pakket_key) ) {
// Set quantity, pakket
$cart->set_quantity( $pakket_key, $pakket_total );
} elseif ( !isset($pakket_key) ) {
// Product "Pakket" is not in cart, we add it
$cart->add_to_cart( $pakket_id, $pakket_total );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'add_delivery_charge_to_cart', 10, 1 );
Unfortunately, these two codes conflict with each other and I cannot understand what is the reason.
How can this be fixed? I will be happy for your help!
Upvotes: 3
Views: 361
Reputation: 29614
Using the same hook woocommerce_before_calculate_totals
twice will indeed cause problems, so it is a matter of combining both codes into one function.
As the code is written now there are some conditions
NOTE: With this piece of code I also added the lunchbox ID, otherwise you will receive a notification of the weight under the lunchbox product, in some cases.
// Add as custom cart item data function add_custom_steak_cart_item_data( $cart_item_data, $product_id, $variation_id, $quantity ) { if ( !empty( $_POST['steak_custom_options'] ) && $product_id != 5737 ) { ...
So then you get
// Display Custom Checkbox Field
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' )
)
);
}
add_action('woocommerce_product_options_general_product_data', 'steak_custom_field_add', 10, 0 );
// Save Custom Checkbox Field
function steak_custom_field_save( $post_id ) {
$product = wc_get_product( $post_id );
// Custom Product Checkbox Field
$steak_checkbox = isset( $_POST['_steak_checkbox'] ) ? 'yes' : 'no';
// Update product meta
$product->update_meta_data( '_steak_checkbox', $steak_checkbox );
// Save
$product->save();
}
add_action('woocommerce_process_product_meta', 'steak_custom_field_save', 10, 1 );
// Display Custom Select Box
function display_steak_custom_field() {
global $post;
// Get product
$product = wc_get_product( $post->ID );
// 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_action( 'woocommerce_before_add_to_cart_button', 'display_steak_custom_field', 10, 0 );
// Add jQuery script to footer - change price on single product page
function add_footer_steak_script() {
// Returns true on a single product page
if ( is_product() ) {
global $woocommerce, $product;
?>
<script type="text/javascript">
jQuery(document).ready(function ($) {
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', 10, 0 );
// Add as custom cart item data
function add_custom_steak_cart_item_data( $cart_item_data, $product_id, $variation_id, $quantity ) {
if ( !empty( $_POST['steak_custom_options'] ) && $product_id != 5737 ) {
$cart_item_data['steak_option'] = $_POST['steak_custom_options'];
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'add_custom_steak_cart_item_data', 10, 4 );
// Add custom fields values under cart item name in cart
function steak_custom_field_add_cart( $item_name, $cart_item, $cart_item_key ) {
if( is_cart() ) {
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;
}
add_filter( 'woocommerce_cart_item_name', 'steak_custom_field_add_cart', 10, 3 );
/**
* Calculate the number of lunchboxes and package, based on the number of products in cart.
*/
function add_delivery_charge_to_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
/********** SETTINGS **********/
$lunchbox_id = 5737; // "LunchBox ID" to be added to cart
$pakket_id = 5738; // "Pakket ID" to be added to cart
$exclude_categories = array( 'drink', 'bread' ); // Exclude these categories
$category_qty_total = 0; // Total of category quantity items, Don't edit!!
/********** LOOP THROUGH CART ITEMS **********/
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
// Get product id
$product_id = $cart_item['data']->get_id();
// Get product quantity
$product_qty = $cart_item['quantity'];
// Check if "LunchBox" product is already in cart
if( $product_id == $lunchbox_id ) {
$lunchbox_key = $cart_item_key;
$lunchbox_qty = $product_qty;
}
// Check if "Pakket" product is already in cart
if( $product_id == $pakket_id ) {
$pakket_key = $cart_item_key;
$pakket_qty = $product_qty;
}
// Check if product belongs to a certain category
if( has_term( $exclude_categories, 'product_cat', $product_id ) ) {
$category_qty_total += $product_qty;
}
// Check if product, contains steak weight
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 );
}
}
/********** CALCULATE THE TOTALS, SO "LUNCHBOX", "PAKKET" & CATEGORIES ARE NOT USED IN THE TOTALS **********/
// Get total items in cart, counts number of products & quantity per product
$total_items_in_cart = $cart->get_cart_contents_count();
// Total items in cart - category quantity total
$total_items_in_cart -= $category_qty_total;
// Lunchbox total = total_items_in_cart & pakket total = total_items_in_cart
$lunchbox_total = $total_items_in_cart;
$pakket_total = $total_items_in_cart;
// Isset lunchbox qty -> lunchbox total - lunchbox qty & pakket total - lunchbox qty
if ( isset($lunchbox_qty) ) {
$lunchbox_total -= $lunchbox_qty;
$pakket_total -= $lunchbox_qty;
}
// Isset pakket qty -> lunchbox total - pakket qty & pakket total - pakket qty
if ( isset($pakket_qty) ) {
$lunchbox_total -= $pakket_qty;
$pakket_total = $pakket_total - $pakket_qty;
}
/********** APPLY NEW TOTALS TO LUNCHBOX & PAKKET **********/
// If product "LunchBox" is in cart, we check the quantity to update it if needed
if ( isset($lunchbox_key) && $lunchbox_qty != $total_items_in_cart ) {
// Set quantity, lunchbox
$cart->set_quantity( $lunchbox_key, $lunchbox_total );
} elseif ( !isset($lunchbox_key) && $total_items_in_cart > 0 ) {
// Product "LunchBox" is not in cart, we add it
$cart->add_to_cart( $lunchbox_id, $total_items_in_cart );
}
// Total items in cart greater than or equal to 3
if ( $total_items_in_cart >= 3 ) {
// Pakket total = pakket_total / 3 = floor(result)
// Floor = round fractions down, rounding result down
$pakket_total = floor( $pakket_total / 3 );
// If product "Pakket" is in cart
if ( isset($pakket_key) ) {
// Set quantity, pakket
$cart->set_quantity( $pakket_key, $pakket_total );
} elseif ( !isset($pakket_key) ) {
// Product "Pakket" is not in cart, we add it
$cart->add_to_cart( $pakket_id, $pakket_total );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'add_delivery_charge_to_cart', 10, 1 );
// Display custom fields values under item name in checkout
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;
}
add_filter( 'woocommerce_checkout_cart_item_quantity', 'steak_custom_checkout_cart_item_name', 10, 3 );
// Save chosen select field value to each order item as custom meta data and display it everywhere
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('woocommerce_checkout_create_order_line_item', 'save_order_item_steak_field', 10, 4 );
Upvotes: 2