I have some custom code was working perfectly and since I have updated Woocommerce to version 3.5.2 it is not working anymore, not sure if it is because I changed the wordpress theme or because because plugin updates.
My problem is that the value of the custom fields doesn't appear on the order page from woocommerce or even on the order email.
Here is the related code:
// Display Fields using WooCommerce Action Hook
add_action('woocommerce_product_options_general_product_data', 'woocom_general_product_data_custom_field');
function woocom_general_product_data_custom_field()
{
// FieldName1
woocommerce_wp_text_input(array('id' => 'FieldName1', 'label' => __('FieldName1', 'woocommerce'), 'placeholder' => '', 'desc_tip' => 'false', 'description' => __('', 'woocommerce')));
// FieldType1
woocommerce_wp_text_input(array('id' => 'FieldType1', 'label' => __('FieldType1', 'woocommerce'), 'placeholder' => '', 'desc_tip' => 'false', 'description' => __('', 'woocommerce')));
// FieldLenght1
woocommerce_wp_text_input(array('id' => 'FieldLenght1', 'label' => __('FieldLenght1', 'woocommerce'), 'placeholder' => '', 'desc_tip' => 'false', 'description' => __('', 'woocommerce')));
// Dropdown1
woocommerce_wp_text_input(array('id' => 'Dropdown1', 'label' => __('Dropdown1', 'woocommerce'), 'placeholder' => '', 'desc_tip' => 'false', 'description' => __('', 'woocommerce')));
}
// Hook to save the data value from the custom fields
add_action('woocommerce_process_product_meta', 'woocom_save_general_proddata_custom_field');
function woocom_save_general_proddata_custom_field($post_id)
{
// Save Label Option 1
update_post_meta($post_id, 'FieldName1', esc_attr($_POST['FieldName1']));
// Save Label Option 1
update_post_meta($post_id, 'FieldType1', esc_attr($_POST['FieldType1']));
// Save Label Option 1
update_post_meta($post_id, 'FieldLenght1', esc_attr($_POST['FieldLenght1']));
// Save Dropdown1
update_post_meta($post_id, 'Dropdown1', esc_attr($_POST['Dropdown1']));
}
/**
* Register the 'Custom Column' column in the importer.
*
* #param array $options
* #return array $options
*/
function add_column_to_importer($options)
{
// column slug => column name
$options['FieldName1'] = 'FieldName1';
$options['FieldType1'] = 'FieldType1';
$options['FieldLenght1'] = 'FieldLenght1';
$options['Dropdown1'] = 'Dropdown1';
return $options;
}
add_filter('woocommerce_csv_product_import_mapping_options', 'add_column_to_importer');
/**
* Process the data read from the CSV file.
* This just saves the value in meta data, but you can do anything you want here with the data.
*
* #param WC_Product $object - Product being imported or updated.
* #param array $data - CSV data read for the product.
* #return WC_Product $object
*/
function process_import( $object, $data ) {
if ( ! empty( $data['FieldName1'] ) ) {
$object->update_meta_data( 'FieldName1', $data['FieldName1'] );
}
if ( ! empty( $data['FieldType1'] ) ) {
$object->update_meta_data( 'FieldType1', $data['FieldType1'] );
}
if ( ! empty( $data['FieldLenght1'] ) ) {
$object->update_meta_data( 'FieldLenght1', $data['FieldLenght1'] );
}
if ( ! empty( $data['Dropdown1'] ) ) {
$object->update_meta_data( 'Dropdown1', $data['Dropdown1'] );
}
return $object;
}
add_filter( 'woocommerce_product_import_pre_insert_product_object', 'process_import', 10, 2 );
// Add the field to the product
add_action('woocommerce_before_add_to_cart_button', 'my_custom_checkout_field');
function my_custom_checkout_field() {
global $product;
$product_id = $product->get_id();
// Get the field name of InputText1
$FieldType1 = get_post_meta($product_id, 'FieldType1', true);
$FieldName1 = get_post_meta($product_id, 'FieldName1', true);
$FieldLenght1 = get_post_meta($product_id, 'FieldLenght1', true);
$Dropdown1 = get_post_meta($product_id, 'Dropdown1', true);
$Dropdown1Content = explode(", ", $Dropdown1);
echo '<table class="extravariations" cellspacing="0">
<tbody>';
// Field 1
if( ! empty( $FieldType1 ) ){
if( $FieldType1 == "TEXT AREA"){
echo '
<tr>
<td class="label">
<label for="'.$FieldName1.'" id="label1">'.$FieldName1.':</label><br>
</td>
<td class="value">
<textarea id="'.$FieldName1.'" class="inputfield1" name="FieldTypeValue1" maxlength="'.$FieldLenght1.'" rows="2" cols="80" placeholder="" required></textarea>
</td>
</tr>';
}
if( $FieldType1 == "TEXT BOX"){
echo '<tr>
<td class="label">
<label for="'.$FieldName1.'" id="label1">'.$FieldName1.':</label>
</td>
<td class="value">
<input id="'.$FieldName1.'" class="inputfield1" type="text" maxlength="'.$FieldLenght1.'" name="FieldTypeValue1" value="" required>
</td>
</tr>';
}
if( $FieldType1 == "DROP DOWN"){
echo ' <tr>
<td class="label">
<label for="'.$FieldName1.'" id="label1">'.$FieldName1.':</label>
</td>
<td class="value">';
echo'<select id="'.$FieldName1.'" class="inputfield1" name="FieldTypeValue1" >';
foreach ($Dropdown1Content as $Dropdown1IndividualContent) {
echo '<option value="'.$Dropdown1IndividualContent.'">';
echo $Dropdown1IndividualContent;
echo '</option>';
}
echo'</td></tr>';
}
}
echo' </tbody>
</table>';
}
// Store custom field label and value in cart item data
add_action( 'woocommerce_add_cart_item_data','save_my_custom_checkout_field', 20, 2 );
function save_my_custom_checkout_field( $cart_item_data, $product_id ) {
$label1 = get_post_meta( $product_id, 'FieldName1', true );
if( isset( $_REQUEST['FieldTypeValue1'] ) && ! empty( $label1 ) )
$cart_item_data['custom_data']['1'] = array(
'label' => $label1,
'value' => sanitize_text_field( $_REQUEST['FieldTypeValue1'] ),
);
if( count($cart_item_data['custom_data']) > 0 )
$cart_item_data['custom_data']['key'] = md5( microtime().rand() );
return $cart_item_data;
}
// Display items custom fields label and value in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 20, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item ){
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( isset( $cart_item['custom_data'] ) ) {
foreach( $cart_item['custom_data'] as $key => $custom_data ){
if( $key != 'key' ){
$custom_items[] = array(
'name' => $custom_data['label'],
'value' => $custom_data['value'],
);
}
}
}
return $custom_items;
}
// Save item custom fields label and value as order item meta data
add_action('woocommerce_add_order_item_meta','save_in_order_item_meta', 10, 3 );
function save_in_order_item_meta( $item_id, $values, $cart_item_key ) {
if( isset( $values['custom_data'] ) ) {
wc_add_order_item_meta( $item_id, $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
I have been looking for hours and i have no idea how to solve it or what the problem is. Any help or tips will be really helpful. Thanks a lot.
The first main problem is $cart_item_data['custom_data']['1'] = array( that should be instead:
$cart_item_data['custom_data'] = array(
'label' => $label1,
'value' => sanitize_text_field( $_REQUEST['FieldTypeValue1'] ),
);
Then the 2nd main problem is the last function where woocommerce_get_item_data is obsolete and replaced by woocommerce_checkout_create_order_line_item already answered in your last question.
So here below I have revisited your 3 last functions:
// Store custom field label and value in cart item data
add_action( 'woocommerce_add_cart_item_data','add_custom_data_as_custom_cart_item_data', 10, 3 );
function add_custom_data_as_custom_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
if( isset( $_REQUEST['FieldTypeValue1'] ) ) {
// Get an instance of the WC_Product object
$product = wc_get_product( $variation_id > 0 ? $variation_id : $product_id );
if( $label = $product->get_meta('FieldName1') ){
$cart_item_data['custom_data'] = array(
'label' => $product->get_meta('FieldName1'),
'value' => sanitize_text_field( $_REQUEST['FieldTypeValue1'] ),
'unique_key' => md5( microtime().rand() ),
);
}
}
return $cart_item_data;
}
// Display cart item custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_cart_item_custom_on_cart_and_checkout', 10, 2 );
function display_cart_item_custom_on_cart_and_checkout( $cart_item_data, $cart_item ){
if( isset($cart_item['custom_data']['label']) && isset($cart_item['custom_data']['value']) ) {
$cart_item_data[] = array(
'name' => $cart_item['custom_data']['label'],
'value' => $cart_item['custom_data']['value'],
);
}
return $cart_item_data;
}
// Save cart item custom data as order item meta data and display it everywhere in Orders and email notifications
add_action('woocommerce_checkout_create_order_line_item', 'save_custom_order_item_meta_data', 10, 4 );
function save_custom_order_item_meta_data( $item, $cart_item_key, $values, $order ) {
if( isset( $values['custom_data']['label'] ) && isset( $values['custom_data']['value'] ) ) {
$item->update_meta_data( $values['custom_data']['label'], $values['custom_data']['value'] );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
Related
I am trying to combine the two responses from [https://stackoverflow.com/questions/62943477/set-quantity-minimum-maximum-and-step-at-product-level-in-woocommerce ] and Decimal quantity step for specific product categories in WooCommerce but I can't figure out how to edit the first lot of code so that it allows decimal quantity steps.
// Displaying quantity setting fields on admin product pages
add_action( 'woocommerce_product_options_pricing', 'wc_qty_add_product_field' );
function wc_qty_add_product_field() {
global $product_object;
$values = $product_object->get_meta('_qty_args');
woocommerce_wp_text_input( array(
'id' => 'qty_step',
'type' => 'number',
'label' => __( 'Quantity step', 'woocommerce-quantity-step' ),
'placeholder' => '',
'desc_tip' => 'true',
'description' => __( 'Optional. Set quantity step (a number greater than 0)', 'woocommerce' ),
'custom_attributes' => array( 'step' => 'any', 'min' => '1'),
'value' => isset($values['qty_step']) && $values['qty_step'] > 1 ? (int) $values['qty_step'] : 1,
) );
echo '</div>';
}
// Save quantity setting fields values
add_action( 'woocommerce_admin_process_product_object', 'wc_save_product_quantity_settings' );
function wc_save_product_quantity_settings( $product ) {
if ( isset($_POST['qty_args']) ) {
$values = $product->get_meta('_qty_args');
'qty_step' => isset($_POST['qty_step']) && $_POST['qty_step'] > 1 ? (int) wc_clean($_POST['qty_step']) : 1,
) );
} else {
$product->update_meta_data( '_qty_args', array() );
}
}
// The quantity settings in action on front end
add_filter( 'woocommerce_quantity_input_args', 'filter_wc_quantity_input_args', 99, 2 );
function filter_wc_quantity_input_args( $args, $product ) {
if ( $product->is_type('variation') ) {
$parent_product = wc_get_product( $product->get_parent_id() );
$values = $parent_product->get_meta( '_qty_args' );
} else {
$values = $product->get_meta( '_qty_args' );
}
if ( ! empty( $values ) ) {
// Step value
if ( isset( $values['qty_step'] ) && $values['qty_step'] > 1 ) {
$args['step'] = $values['qty_step'];
}
}
return $args;
}
// Ajax add to cart, set "min quantity" as quantity on shop and archives pages
add_filter( 'woocommerce_loop_add_to_cart_args', 'filter_loop_add_to_cart_quantity_arg', 10, 2 );
function filter_loop_add_to_cart_quantity_arg( $args, $product ) {
$values = $product->get_meta( '_qty_args' );
if ( ! empty( $values ) ) {
// Min value
if ( isset( $values['qty_min'] ) && $values['qty_min'] > 1 ) {
$args['quantity'] = $values['qty_min'];
}
}
return $args;
}
I've tried editing the values to a decimal unit but it's not stepping up by that value and it's not saving the value.
I inserted two radio buttons as product add ons by using the following to calculate extra packaging cost. But I have two problems.
First instead of getting the value of my custom field eg 4.35 it gets a value of 4.00.
Second how can I update the sales price in my product page when I choose an option
function add_custom_fees_before_add_to_cart() {
global $product;
$myfee = floatval(get_post_meta(get_the_ID(), '_skrprom', TRUE)) + floatval(0.90);
$args = array(
'type' => 'radio',
'class' => array( 'form-row-wide' ),
'options' => array(
'' => 'Τηλεφωνική Παραγγελία',
$myfee => 'Έξοδα Συσκευασίας '.$myfee.'€',
),
'default' => ''
);
?>
<div class="custom-fees-wrap">
<label for="iconic-engraving"><?php _e( 'Customize Your Order!', 'textdomain' ); ?></label>
<?php woocommerce_form_field( 'custom_fees', $args, '' ); ?>
</div>
<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'add_custom_fees_before_add_to_cart', 99 );
function save_value_add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
$custom_fees = filter_input( INPUT_POST, 'custom_fees' );
if ( empty( $custom_fees ) ) {
return $cart_item_data;
}
$cart_item_data['custom_fees'] = $custom_fees;
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_value_add_cart_item_data', 99, 3 );
function calculate_add_cart_fee() {
global $woocommerce;
$cart_items = $woocommerce->cart->get_cart();
foreach( $cart_items as $key => $item ) {
if( !isset( $item['custom_fees'] ) && empty( $item['custom_fees'] ) ) continue;
$woocommerce->cart->add_fee( __('Έξοδα Συσκευασίας', 'textdomain'), $item['custom_fees'] );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'calculate_add_cart_fee', 99 );
I've added two customer date inputs to the single product page. I need them to be required and validated before adding to the cart, and would also like the dates to be shown on the cart/checkout page and in the order emails.
I found the snippets needed here, however it was only for one custom field so I adjusted to make it for two: https://www.kathyisawesome.com/add-a-custom-field-to-woocommerce-product/
The input fields show up fine, but once you hit the Add to Cart button it doesn't carry throughout the order.
Here is the code used in my functions.php file:
/*
* Display inputs on single product page
*/
function amp_custom_option_1(){
$value = isset( $_POST['_est_delivery'] ) ? sanitize_text_field( $_POST['_est_delivery'] ) : '';
printf( '<div id="dates"><div class="delivery"><label>%s</label><input name="_est_delivery" value="%s" type="date" required /></div>', __( 'Estimated Delivery Date:', 'amp-plugin-textdomain-1' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_form', 'amp_custom_option_1', 9 );
function amp_custom_option_2(){
$value = isset( $_POST['_est_pickup'] ) ? sanitize_text_field( $_POST['_est_pickup'] ) : '';
printf( '<div class="pickup"><label>%s</label><input name="_est_pickup" value="%s" type="date" required /></div></div>', __( 'Estimated Pickup Date:', 'amp-plugin-textdomain-2' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_form', 'amp_custom_option_2', 9 );
/*
* Validate when adding to cart
*/
function amp_add_to_cart_validation_1($passed, $product_id, $qty){
if( isset( $_POST['_est_delivery'] ) && sanitize_text_field( $_POST['_est_delivery'] ) == '' ){
$product = wc_get_product( $product_id );
wc_add_notice( sprintf( __( '%s cannot be added to the cart until you enter a delivery date.', 'amp-plugin-textdomain-1' ), $product->get_title() ), 'error' );
return false;
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'amp_add_to_cart_validation_1', 10, 3 );
function amp_add_to_cart_validation_2($passed, $product_id, $qty){
if( isset( $_POST['_est_pickup'] ) && sanitize_text_field( $_POST['_est_pickup'] ) == '' ){
$product = wc_get_product( $product_id );
wc_add_notice( sprintf( __( '%s cannot be added to the cart until you enter a pickup date.', 'amp-plugin-textdomain-2' ), $product->get_title() ), 'error' );
return false;
}
return $passed;
}
add_filter( 'woocommerce_add_to_cart_validation', 'amp_add_to_cart_validation_2', 10, 3 );
/*
* Add custom data to the cart item
*/
function amp_add_cart_item_data_1( $cart_item, $product_id ){
if( isset( $_POST['_est_delivery'] ) ) {
$cart_item['est_delivery'] = sanitize_text_field( $_POST['_est_delivery'] );
}
return $cart_item;
}
add_filter( 'woocommerce_add_cart_item_data', 'amp_add_cart_item_data_1', 10, 2 );
function amp_add_cart_item_data_2( $cart_item, $product_id ){
if( isset( $_POST['_est_pickup'] ) ) {
$cart_item['est_pickup'] = sanitize_text_field( $_POST['_est_pickup'] );
}
return $cart_item;
}
add_filter( 'woocommerce_add_cart_item_data', 'amp_add_cart_item_data_2', 10, 2 );
/*
* Load cart data from session
*/
function amp_get_cart_item_from_session_1( $cart_item, $values ) {
if ( isset( $values['est_delivery'] ) ){
$cart_item['est_delivery'] = $values['est_delivery'];
}
return $cart_item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'amp_get_cart_item_from_session_1', 20, 2 );
function amp_get_cart_item_from_session_2( $cart_item, $values ) {
if ( isset( $values['est_pickup'] ) ){
$cart_item['est_pickup'] = $values['est_pickup'];
}
return $cart_item;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'amp_get_cart_item_from_session_2', 20, 2 );
/*
* Add meta to order item
*/
function amp_add_order_item_meta_1( $item_id, $values ) {
if ( ! empty( $values['est_delivery'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'est_delivery', $values['est_delivery'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'amp_add_order_item_meta_1', 10, 2 );
function amp_add_order_item_meta_2( $item_id, $values ) {
if ( ! empty( $values['est_pickup'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'est_pickup', $values['est_pickup'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'amp_add_order_item_meta_2', 10, 2 );
/*
* Get item data to display in cart
*/
function amp_get_item_data_1( $other_data, $cart_item ) {
if ( isset( $cart_item['est_delivery'] ) ){
$other_data[] = array(
'name' => __( 'Estimated Delivery Date:', 'amp-plugin-textdomain-1' ),
'value' => sanitize_text_field( $cart_item['est_delivery'] )
);
}
return $other_data;
}
add_filter( 'woocommerce_get_item_data', 'amp_get_item_data_1', 10, 2 );
function amp_get_item_data_2( $other_data, $cart_item ) {
if ( isset( $cart_item['est_pickup'] ) ){
$other_data[] = array(
'name' => __( 'Estimated Pickup Date', 'amp-plugin-textdomain-2' ),
'value' => sanitize_text_field( $cart_item['est_pickup'] )
);
}
return $other_data;
}
add_filter( 'woocommerce_get_item_data', 'amp_get_item_data_2', 10, 2 );
/*
* Show custom field in order overview
*/
function amp_order_item_product_1( $cart_item, $order_item ){
if( isset( $order_item['est_delivery'] ) ){
$cart_item_meta['est_delivery'] = $order_item['est_delivery'];
}
return $cart_item;
}
add_filter( 'woocommerce_order_item_product', 'amp_order_item_product_1', 10, 2 );
function amp_order_item_product_2( $cart_item, $order_item ){
if( isset( $order_item['est_pickup'] ) ){
$cart_item_meta['est_pickup'] = $order_item['est_pickup'];
}
return $cart_item;
}
add_filter( 'woocommerce_order_item_product', 'amp_order_item_product_2', 10, 2 );
/*
* Add the field to order emails
*/
function amp_email_order_meta_fields_1( $fields ) {
$fields['est_delivery'] = __( 'Estimated Delivery Date:', 'amp-plugin-textdomain-1' );
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'amp_email_order_meta_fields_1');
function amp_email_order_meta_fields_2( $fields ) {
$fields['est_delivery'] = __( 'Estimate Pickup Date:', 'amp-plugin-textdomain-2' );
return $fields;
}
add_filter('woocommerce_email_order_meta_fields', 'amp_email_order_meta_fields_2');
I'm not sure what is wrong with my code? Any help is appreciated.
There was some errors and mistakes. I have changed and removed some hooks, remove unnecessary code, merged functions, revisited all your code. As Your 2 dates fields are on single product pages, they will be related to cart items and order items (so order items meta data).
I have set your 2 date fields slugs and labels in the first function, inside an array. Then I call that function everywhere else and I use a foreach loop to process each field. This avoid repetitions, optimize and compact the code.
The code (commented):
// Utility function that contain the 2 field keys and labels pairs used on all other functions
function get_date_label_keys(){
$text_domain = 'woocommerce';
return array( 'est_delivery' => __( 'Estimated Delivery Date', $text_domain ),
'est_pickup' => __( 'Estimated Pickup Date', $text_domain ) );
}
// Display custom fields on single product page (hook replaced)
add_action( 'woocommerce_before_add_to_cart_button', 'amp_display_custom_fields', 20 );
function amp_display_custom_fields(){
echo '<div id="dates">';
// Loop through each custom field
foreach( get_date_label_keys() as $key => $label ){
$class = str_replace('est_', '', $key); // The class
$value = isset($_POST[$key]) ? sanitize_text_field($_POST[$key]) : ''; // Display the value
printf( '<div class="%s"><label>%s:</label> <input type="date" name="%s" value="%s" required /></div>', $class, $label, $key, $value );
}
echo '</div><br clear="all">';
}
// Add to cart fields validation (in case of need)
add_filter( 'woocommerce_add_to_cart_validation', 'amp_add_to_cart_validation', 20, 3 );
function amp_add_to_cart_validation( $passed, $product_id, $qty ){
// Loop through each custom field
foreach( get_date_label_keys() as $key => $label ){
if( isset( $_POST[$key] ) && empty( $_POST[$key] ) ){
wc_add_notice( sprintf( __( '%s cannot be added to the cart until you enter a delivery date.', $domain ), get_the_title() ), 'error' );
$passed = false;
}
}
return $passed;
}
// Add to cart items the custom data
add_filter( 'woocommerce_add_cart_item_data', 'amp_add_cart_item_data', 20, 2 );
function amp_add_cart_item_data( $cart_item, $product_id ){
// Loop through each custom field
foreach( get_date_label_keys() as $key => $label ){
if( isset( $_POST[$key] ) )
$cart_item['dates'][$key] = sanitize_text_field( $_POST[$key] );
}
return $cart_item;
}
// Display the dates in cart items on cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'amp_get_item_data', 20, 2 );
function amp_get_item_data( $item_data, $cart_item = null ) {
// Loop through each custom field
foreach( get_date_label_keys() as $key => $label ){
if ( isset( $cart_item['dates'][$key] ) )
$item_data[] = array(
'name' => $label,
'value' => sanitize_text_field( $cart_item['dates'][$key] )
);
}
return $item_data;
}
// Add order item meta data and Display the data in order items (hook replaced)
add_action( 'woocommerce_checkout_create_order_line_item', 'amp_add_order_item_meta', 20, 4 );
function amp_add_order_item_meta( $item, $cart_item_key, $values, $order ) {
foreach( get_date_label_keys() as $key => $label ){
// Loop through each custom field
if ( ! empty( $values['dates'][$key] ) )
$item->update_meta_data( $label, $values['dates'][$key] );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
On cart page (and checkout too):
Order received and order view pages (in admin order edit pages and email notifications too):
I am using Woocommerce plugin with WPML Multilingual plugin, and I simply can't get to work like I would expect.
My products have serveral Custom Fields that I need to display in the cart, Checkout, Order views and emails notifications.
The Fields are displayed correctly on frontend but when I switch the language the data from sessions are not updated.
How does WPML handle the extra data?
Is there a way to get this to work, that the data update when i switch the language?
Here is my code:
add_filter( 'woocommerce_product_data_tabs', 'mbextra_product_data_tab' , 99 , 1 );
function mbextra_product_data_tab( $product_data_tabs ) {
$product_data_tabs['mbextraproducttab'] = array(
'label' => __( 'EXTRA', 'mbg' ),
'target' => 'mbextraproductdata',
'class' => array();
);
return $product_data_tabs;
}
add_action( 'woocommerce_product_data_panels', 'mbextra_product_data_fields' );
function mbextra_product_data_fields() {
?>
<div id="mbextraproductdata" class="panel woocommerce_options_panel">
<div class="options_group">
<?php
woocommerce_wp_textarea_input(
array(
'id' => 'company',
'label' => __( 'Company', 'mbg' ),
'placeholder' => 'Company Adress here',
'desc_tip' => 'true',
'description' => __( 'Enter Company Adress here', 'mbg' )
)
);
?>
</div>
<div class="options_group">
<?php
woocommerce_wp_textarea_input(
array(
'id' => 'shortdescription',
'label' => __( 'Short-Description', 'mbg' ),
'placeholder' => 'Enter some short info',
'desc_tip' => 'true',
'description' => __( 'Enter Short description here', 'mbg' )
)
);
?>
</div>
</div><!-- #extraproductdata Tab -->
<?php
}
add_action( 'woocommerce_process_product_meta', 'mbprocess_product_meta_fields_save', 99 );
function mbprocess_product_meta_fields_save( $post_id ){
// if set > save the fields
$company = $_POST['company'];
if( isset( $company ) )
update_post_meta( $post_id, 'company', esc_attr( $company ) );
// if set > save data to post_meta
$shortdescription = $_POST['shortdescription'];
if( isset( $shortdescription ) )
update_post_meta( $post_id, 'shortdescription', esc_attr( $shortdescription ) );
}
add_filter( 'woocommerce_add_cart_item_data', 'custom_product_field', 10, 3 );
function custom_product_field( $cart_item_data, $product_id, $variation_id ) {
$shortdesciption = get_post_meta( $product_id , 'shortdesciption' , true );
$company = get_post_meta( $product_id , 'company' , true );
if( !empty( $shortdesciption ) )
{
$cart_item_data['shortdesciption'] = $shortdesciption;
}
if( !empty( $company ) )
{
$cart_item_data['company'] = $company;
}
return $cart_item_data;
}
add_filter( 'woocommerce_get_cart_item_from_session', 'mbget_cart_item_from_session', 10, 3);
function mbget_cart_item_from_session( $cart_item_data, $cart_item_session_data, $cart_item_key ) {
if ( isset( $cart_item_session_data['shortdesciption'] ) ) {
$cart_item_data['shortdesciption'] = $cart_item_session_data['shortdesciption'];
}
if ( isset( $cart_item_session_data['company'] ) ) {
$cart_item_data['company'] = $cart_item_session_data['company'];
}
return $cart_item_data;
}
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
$data = array();
if( !empty( $data ) ) {
$data = $cart_data;
}
if( isset( $cart_item['shortdesciption'] ) ) {
$data[] = array(
'name' => __( 'Stuff', 'mbg' ),
'value' => $cart_item['shortdesciption'] );
}
if( isset( $cart_item['company'] ) ) {
$data[] = array(
'name' => __( 'Company', 'mbg' ),
'value' => $cart_item['company'] );
}
return $data;
}
Thanks
YES you should need to destroy the cart session or to remove all cart items when switching language. But this kind of case never really happen:
As it is NOT really a customer behavior, adding items in cart (for some language) and then switch to another language before checkout for example.
So this should not be really a problem. This is just the behavior of a developer that is testing an e-commmerce in all possible ways, isn't it?
I have a a custom field value for each product. This custom field is inserted with the code below :
<?php
// Insert a Custom Admin Field
add_action( 'woocommerce_product_options_general_product_data', 'woo_add_custom_general_fields' );
function woo_add_custom_general_fields() {
echo '<div class="options_group">';
woocommerce_wp_text_input( array(
'id' => 'days_manufacture',
'label' => __( 'Days for Manufacture', 'woocommerce' ),
'placeholder' => '',
'description' => __( 'Insert here', 'woocommerce' ),
'type' => 'number',
'custom_attributes' => array(
'step' => 'any',
'min' => '1'
),
) );
echo '</div>';
}
// Save the field
add_action( 'woocommerce_process_product_meta', 'woo_add_custom_general_fields_save' );
function woo_add_custom_general_fields_save( $post_id ){
$woocommerce_number_field = $_POST['days_manufacture'];
if( !empty( $woocommerce_number_field ) )
update_post_meta( $post_id, 'days_manufacture', esc_attr( $woocommerce_number_field ) );
}
// Store custom field
add_action( 'woocommerce_add_cart_item_data', 'save_days_field', 10, 2 );
function save_days_field( $cart_item_data, $product_id ) {
$special_item = get_post_meta( $product_id , 'days_manufacture',true );
if(!empty($special_item)) {
$cart_item_data[ 'days_manufacture' ] = $special_item;
// below statement make sure every add to cart action as unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'days_manufacture', $special_item );
}
return $cart_item_data;
}
// Render meta on cart and checkout
add_filter( 'woocommerce_get_item_data', 'rendering_meta_field_on_cart_and_checkout', 10, 2 );
function rendering_meta_field_on_cart_and_checkout( $cart_data, $cart_item ) {
$custom_items = array();
// Woo 2.4.2 updates
if( !empty( $cart_data ) ) {
$custom_items = $cart_data;
}
if( isset( $cart_item['days_manufacture'] ) ) {
$custom_items[] = array( "name" => __( "Days", "woocommerce" ), "value" => $cart_item['days_manufacture'] );
}
return $custom_items;
} ?>
This code works perfectly.
Now I would like on Cart and checkout (before coupon notice) pages to display the highest value of this custom field (days_manufacture) on a custom message, when multiple items are in Cart, like in this screenshot.
How can I achieve this?
Thanks.
Here is a custom function that will display a message on cart and checkout (before coupon notice) pages with the highest number of days of manufacture…
Here is the code:
add_action('woocommerce_before_cart', 'days_of_manufacture');
add_action('woocommerce_before_checkout_form', 'days_of_manufacture', 5);
function days_of_manufacture() {
$day_txt = ' ' . __('day', 'your_theme_domain_slug' );
$days_txt = ' ' . __('days', 'your_theme_domain_slug' );
$text = __('Your Order will be produced in: ', 'your_theme_domain_slug' );
$max_days = 0;
foreach( WC()->cart->get_cart() as $cart_item )
if($cart_item['days_manufacture'] > $max_days)
$max_days = $cart_item['days_manufacture'];
if($max_days != 0) {
if ($max_days == 1)
$days_txt = $day_txt;
$output = $text . $max_days . $days_txt;
echo "<div class='woocommerce-info'>$output</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.
Store the variable in the $_SESSION, then loop thru them and pick the highest, so you can use it later anywhere in your code