I've got a client who needs a checkbox for "accepting the terms and conditions etc." The tricky thing is that he will be adding in-person purchases on the admin panel and needs the checkbox there as well. I got the checkbox on both the front and back-end but I'm having some trouble getting them to talk to each other. When placing an order on the front-end, it shows as admin-panel-pic
But when you click into edit the order, the checkbox in not checked and if you update the order at all the value will disappear. I'm sure I'm missing something obvious but this is the first time I've had to modify Woocommerce fields like this.
Here's the code pertaining to the checkbox I have currently in my functions.php:
<?php
add_action('woocommerce_before_order_notes', 'wps_add_select_checkout_field');
function wps_add_select_checkout_field( $checkout ) {
woocommerce_form_field( 'rem_terms', array(
'type' => 'checkbox',
'class' => array('form-row mycheckbox'),
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox
checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-
checkbox'),
'required' => true,
'label' => 'I agree with the terms and conditions described in the Privacy Policy and the <a
target="_blank" rel="noopener" href="/liability-release-and-express-assumption-of-risk">
Liability Release </a>',) // Label and Link
);
$checkout->get_value( 'rem_terms' );
}
add_action('woocommerce_checkout_update_order_meta',
'wps_select_checkout_field_update_order_meta');
add_action( 'woocommerce_checkout_process', 'bt_add_checkout_checkbox_warning' );
/**
* Alert if checkbox not checked
*/
function bt_add_checkout_checkbox_warning() {
if ( ! (int) isset( $_POST['rem_terms'] ) ) {
wc_add_notice( __( 'Please agree to our terms and conditions before placing your order' ),
'error' );
}
}
function wps_select_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['rem_terms'] ) ) {
update_post_meta( $order_id, 'rem_terms', sanitize_text_field( $_POST['rem_terms'] ) );
}
}
add_action( 'woocommerce_admin_order_data_after_order_details',
'misha_editable_order_meta_general' );
function misha_editable_order_meta_general( $order ){ ?>
<br class="clear" />
<h4>Checkbox</h4>
<?php
/*
* get all the meta data values we need
*/
$rem_terms = get_post_meta( $order->get_id(), 'rem_terms', true );
?>
<div class="address">
<p><strong>Customer accepts REM's terms and conditions described in the
privacy policy</strong><?php echo $rem_terms?></p>
</div>
<div class="edit_address"><?php
woocommerce_wp_checkbox( array(
'id' => 'rem_terms',
'label' => 'Customer Agrees to terms and conditions',
'value' => $rem_terms,
'wrapper_class' => 'form-field-wide'
) );
?></div>
<?php }
add_action( 'woocommerce_process_shop_order_meta', 'save_new_fields' );
function save_new_fields( $ord_id ){
update_post_meta( $ord_id, 'rem_terms', wc_clean( $_POST[ 'rem_terms' ] ) );
}
function example_custom_order_fields( $fields, $order ) {
$new_fields = array();
if( get_post_meta( $order->id, 'rem_terms', true ) ) {
$new_fields['rem_terms'] = array(
'label' => 'Cust Accepts Terms',
'value' => get_post_meta( $order->id, 'rem_terms', true )
);
}
return array_merge( $fields, $new_fields );
}
add_filter( 'wcdn_order_info_fields', 'example_custom_order_fields', 10, 2 );
I was able to sort this out. Simply reassigning the value of the checkbox from 1 to "yes" as needed.
Related
Am using the snippet below to show a custom checkbox for all products but would like to hide/not show it if product with ID 32 is in cart. How do i modify this code to achieve that? Thanks in advance.
add_action( 'woocommerce_review_order_before_submit', 'bbloomer_add_checkout_privacy_policy', 9 );
function bbloomer_add_checkout_privacy_policy() {
woocommerce_form_field( 'privacy_policy', array(
'type' => 'checkbox',
'class' => array('form-row privacy'),
'label_class' => array('woocommerce-form__label woocommerce-form__label-for-checkbox checkbox'),
'input_class' => array('woocommerce-form__input woocommerce-form__input-checkbox input-checkbox'),
'required' => true,
'label' => 'I\'ve read and accept the Privacy Policy',
));
}
// Show notice if customer does not tick
add_action( 'woocommerce_checkout_process', 'bbloomer_not_approved_privacy' );
function bbloomer_not_approved_privacy() {
if ( ! (int) isset( $_POST['privacy_policy'] ) ) {
wc_add_notice( __( 'Please acknowledge the Privacy Policy' ), 'error' );
}
}
Before you actually show the checkbox field, you will first have to go through the cart to see if the productID is NOT present.
Same for the validation, as it is a required field and would otherwise still be a required field, even though it is not present.
So you get:
// Function to check if a certain product ID is in cart
function is_product_in_cart() {
// Check if product in cart
// Multiple product IDs can be entered, separated by a comma
$targeted_ids = array( 32, 1234, 5678 );
// Flag no product in cart
$flag = false;
// WC Cart NOT null
if ( ! is_null( WC()->cart ) ) {
// Loop through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
// Check cart item for defined product Ids
if ( in_array( $cart_item['product_id'], $targeted_ids ) ) {
// Product is in cart
$flag = true;
// Break loop
break;
}
}
}
return $flag;
}
// Add field
function action_woocommerce_review_order_before_submit() {
// NOT true
if ( ! is_product_in_cart() ) {
// Add checkbox
woocommerce_form_field( 'privacy_policy', array(
'type' => 'checkbox',
'class' => array( 'form-row privacy' ),
'label_class' => array( 'woocommerce-form__label woocommerce-form__label-for-checkbox checkbox' ),
'input_class' => array( 'woocommerce-form__input woocommerce-form__input-checkbox input-checkbox' ),
'required' => true,
'label' => 'I\'ve read and accept the Privacy Policy',
));
}
}
add_action( 'woocommerce_review_order_before_submit', 'action_woocommerce_review_order_before_submit', 9 );
// Validate
function action_woocommerce_checkout_process() {
// NOT true
if ( ! is_product_in_cart() ) {
// NOT isset
if ( ! isset( $_POST['privacy_policy'] ) ) {
wc_add_notice( __( 'Please acknowledge the Privacy Policy', 'woocommerce' ), 'error' );
}
}
}
add_action( 'woocommerce_checkout_process', 'action_woocommerce_checkout_process', 10, 0 );
// Save field
function action_woocommerce_checkout_create_order( $order, $data ) {
// Isset
if ( isset( $_POST['privacy_policy'] ) ) {
$order->update_meta_data( 'privacy_policy', sanitize_text_field( $_POST['privacy_policy'] ) );
}
}
add_action( 'woocommerce_checkout_create_order', 'action_woocommerce_checkout_create_order', 10, 2 );
I read a few articles on the optgroup which is what i need, i manage to display it on the checkout page, but i need the selected option to be visible on email and the admin area where we view the order details.
Code comes from: "WooCommerce Select Dropdown With Optgroup On Checkout"
What I need: I'm creating a website where I need to add manually a few areas on the checkout page so the user can select his area so I can use it as validation and a way to limit the shipping, once the select area I need to be able to see this on the email order as well on the order that on Woocommerce zones doesn't fit in my case:
<?php
add_action('woocommerce_before_order_notes', 'custom_checkout_select_field_with_optgroup', 10, 1 );
function custom_checkout_select_field_with_optgroup( $checkout ) {
$domain = 'woocommerce';
$title = __("zona", $domain);
$slug = zone_limit;
$default = __("Selecione su Zona", $domain);
$value = $checkout->get_value($slug);
// Region option data array with optgroup
$options = array(
__("North zone", $domain) => array(
'region1' => __("Region 1", $domain),
'region2' => __("Region 2", $domain),
),
__("South zone", $domain) => array(
'region3' => __("Region 3", $domain),
'region4' => __("Region 4", $domain),
)
__("Middle zone", $domain) => array(
'region3' => __("Region 5", $domain),
'region4' => __("Region 6", $domain),
)
);
// The field
echo '<p class="form-row form-row-wide '.$slug.'-dropdown" id="'.$slug.'_field" data-priority="">
<label for="'.$slug.'" class="">'.$title.'</label>
<span class="woocommerce-input-wrapper">
<select name="'.$slug.'" id="'.$slug.'" class="select " data-placeholder="" autocomplete="'.$slug.'">
<option value="">'.$default.'</option>';
// Loop through "optgroup"
foreach( $options as $optgroup_label => $optgroup_options ) {
echo '<optgroup label="'.$optgroup_label.'">';
// Loop through "options" in the "optgroup"
foreach( $optgroup_options as $key => $label ) {
$selected = $value === $key ? ' selected="selected"': '';
echo '<option value="'.$key.'"'.$selected.'>'.$label.'</option>';
}
echo '</optgroup>';
}
echo '</select></span></p>';
}
I've tried this but not lucky
add_filter( 'woocommerce_email_order_meta_fields', 'custom_woocommerce_email_order_meta_fields', 10, 3 );
function custom_woocommerce_email_order_meta_fields( $fields, $sent_to_admin, $order ) {
$fields['meta_key'] = array(
'label' => __( 'Label' ),
'value' => get_post_meta( $order->id, 'meta_key', true ),
);
return $fields;
}
add_filter('woocommerce_email_order_meta_keys', 'my_custom_order_meta_keys');
function my_custom_order_meta_keys( $keys ) {
$keys[] = $value ; // This will look for a custom field called 'Tracking Code' and add it to emails
return $keys;
}
add_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST[$value ] ) ) {
update_post_meta( $order_id, 'region', sanitize_text_field( $_POST[$value ] ) );
}
}
I hope i don't be penalized for this, my initial question was adding the selected value to the email order and use the optgroup collapse effect, however i was told the question was to broad, so i removed the jquery tag and effect and limit my self just the the php and getting it on the email order.
the php was fine i just couln'd get it on the email plus i needed the optgroup.
I did something else, i just used jquery instead of full php only, i created text type field and get it to send answer to email, then i created a modal manually(not wanted to use bootstrap) then a regular html for the optgroup and use jquery get the selected value and insert into the text field. here is my code.
The html is a basic that you can find here
And the css you can use this as example then bot css and html will need to be modify as you need
The php
add_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );
function my_custom_checkout_field( $checkout ) {
echo '<div id="myZoneLimit"><h2>' . __('valida tu zona') . '</h2>';
woocommerce_form_field( 'my_field_limit', array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('Fill in this field'),
'placeholder' => __('Enter something'),
), $checkout->get_value( 'my_field_limit' ));
echo '</div>';
}
add_action('woocommerce_checkout_process', 'my_custom_checkout_field_process');
function my_custom_checkout_field_process() {
// Check if set, if its not set add an error.
if ( ! $_POST['my_field_limit'] )
wc_add_notice( __( 'Por favor seleccione su zona de envio.' ), 'error' );
}
add_filter('woocommerce_email_order_meta_keys', 'my_custom_order_meta_keys');
function my_custom_order_meta_keys( $keys ) {
$keys[] = 'valida tu zona'; // This will look for a custom field called 'Tracking Code' and add it to emails
return $keys;
}
add_action( 'woocommerce_checkout_update_order_meta',
'my_custom_checkout_field_update_order_meta' );
function my_custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['my_field_limit'] ) ) {
update_post_meta( $order_id, 'valida tu zona', sanitize_text_field( $_POST['my_field_limit'] ) );
}
}
add_action( 'woocommerce_admin_order_data_after_billing_address','my_custom_checkout_field_display_admin_order_meta', 10, 1 );
function my_custom_checkout_field_display_admin_order_meta($order){
echo '<p><strong>'.__('valida tu zona').':</strong> ' . get_post_meta( $order->id, 'valida tu zona', true ) . '</p>';
My jquery
/// button that opens the modal that was created the html
$("#my_field_limit").click(function(){
$("#myModalarea").show();
});
//// get the value from the selected option and place in into the the text field
$('#coveredareas').change(function(){
var areazone = $(this).val();
$("#my_field_limit").val(areazone);
I made a custom field for a WooCommerce product but when I am trying to save it, Its value is not saving in the database
function product_certification_number() {
$args = array(
'id' => 'product_certification_number',
'label' => sanitize_text_field( 'Product Certification Number' ),
);
woocommerce_wp_text_input( $args );
}
add_action('woocommerce_product_options_general_product_data','product_certification_number' );
function product_certification_number_save( $post_id ) {
if ( ! ( isset( $_POST['woocommerce_meta_nonce'], $_POST[ 'product_certification_number' ] ) || wp_verify_nonce( sanitize_key( $_POST['woocommerce_meta_nonce'] ), 'woocommerce_save_data' ) ) ) {
return false;
}
$product_teaser = sanitize_text_field(
wp_unslash( $_POST[ 'product_certification_number' ] )
);
update_post_meta(
$post_id,
'product_certification_number',
esc_attr( $product_teaser )
);
}
add_action('woocommerce_process_product_meta','product_certification_number_save');
EDIT: used woocommerce_admin_process_product_object to save instead of outdated woocommerce_process_product_meta. Thnx to: #LoicTheAztec
// Add field
function product_certification_number() {
$args = array(
'id' => '_product_certification_number',
'label' => __( 'Product Certification Number', 'woocommerce' ),
'class' => 'custom-field',
'desc_tip' => true,
'description' => __( 'My description', 'woocommerce' ),
);
woocommerce_wp_text_input( $args );
}
add_action('woocommerce_product_options_general_product_data','product_certification_number', 10, 0 );
// Save
function product_certification_number_save( $product ){
if( isset($_POST['_product_certification_number']) ) {
$product->update_meta_data( '_product_certification_number', sanitize_text_field( $_POST['_product_certification_number'] ) );
}
}
add_action( 'woocommerce_admin_process_product_object', 'product_certification_number_save', 10, 1 );
I've wasted my two hours in this problem.
I finally found out that you need to call save_meta_data after update_meta_data:
/** #var WC_Product */
$product->update_meta_data($key, $value);
$product->save_meta_data();
I added a custom field on the woocommerce checkout page that is populated by URL but I am struggling to find a way to make this field not editable.
I added the following code to function.php:
//Add custom field
function custom_woocommerce_checkout_fields( $checkout_fields = array() ) {
$checkout_fields['order']['imei'] = array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('IMEI'),
'placeholder' => __('imei'),
'default' => $_GET['imei'],
);
return $checkout_fields;
}
add_filter( 'woocommerce_checkout_fields', 'custom_woocommerce_checkout_fields' );
What should I change in my code to accomplish this ?
Try this code. It work for me. Just need to add custom attribute parameter to the fields array.
//Display custom field
function custom_woocommerce_checkout_fields( $checkout_fields = array() ) {
$checkout_fields['order']['imei'] = array(
'type' => 'text',
'class' => array('my-field-class form-row-wide'),
'label' => __('IMEI'),
'placeholder' => __('imei'),
'default' => $_GET['imei'],
'custom_attributes' => array( 'disabled' => true)
);
return $checkout_fields;
}
add_filter( 'woocommerce_checkout_fields', 'custom_woocommerce_checkout_fields' );
// Save custom field
add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta' );
function custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['imei'] ) ) {
update_post_meta( $order_id, '_imei', sanitize_text_field( $_POST['imei'] ) );
}
}
You should try this text <imput> field with the readonly property (meaning not editable).
You should need to have your 'emei' set in the checkout url like:
http://www.example.com/checkout/?imei=3545454653 to make the field appear with the value as I have this condition: if( empty($_GET['imei'])) return;set in the function.
The code:
// Display
add_action( 'woocommerce_after_order_notes', 'custom_woocommerce_checkout_fields' );
function custom_woocommerce_checkout_fields( $checkout ) {
// Only display field if the 'emei' is set in the checkout url
if( empty($_GET['imei'])) return;
echo '<p class="form-row my-field-class form-row-wide woocommerce-validated" id="imei_field">
<label for="imei" class="">'.__('IMEI').'</label>
<input type="text" class="input-text " name="imei" id="imei" placeholder="'.__('IMEI').'" value="'.$_GET['imei'].'" readonly>
</p>';
}
// Save
add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_field_update_order_meta' );
function custom_checkout_field_update_order_meta( $order_id ) {
if ( ! empty( $_POST['imei'] ) ) {
update_post_meta( $order_id, '_imei', sanitize_text_field( $_POST['imei'] ) );
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and work on WooCommerce versions 3+
To get the value (for a defined $order_id):
$imei = get_post_meta( $order_id, '_imei', true );
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?