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 );
Related
I want to show a custom checkbox during checkout that will only show for certain SKUs or Product categories. I already have this code that shows the checkbox on all checkout pages
add_action( 'woocommerce_review_order_before_submit', 'bt_add_checkout_checkbox', 10 );
/**
* Add WooCommerce additional Checkbox checkout field
*/
function bt_add_checkout_checkbox() {
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'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, // Mandatory or Optional
'label' => 'Custom label', // Label and Link
));
}
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['checkout_checkbox'] ) ) {
wc_add_notice( __( 'Please acknowledge the Checkbox' ), 'error' );
}
}
I don't know much about PHP but I think I must use $cart_item and $product within a foreach loop and an if statement but I'm quite lost with this part, my logic says it would be something like this:
function bt_add_checkout_checkbox() {
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ){
$product = $cart_item['data'];
$sku = WC()->cart->get_sku($product);
if ($sku == 'SA300ARS'){
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'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, // Mandatory or Optional
'label' => 'I acknowledge that my product can take up to 24 hours to be delivered. (Unless the description says otherwise)', // Label and Link
));
}
}
}
You're going in the right direction. You just need to modify the code like this:
add_action( 'woocommerce_review_order_before_submit', 'bt_add_checkout_checkbox', 10 );
/**
* Add WooCommerce additional Checkbox checkout field
*/
function bt_add_checkout_checkbox() {
//Check if wooCommerce is activated
if ( class_exists( 'WooCommerce' ) ) {
//Define SKUs you want to check for
$checkSKUs = ['sku1', 'sku2', 'sku3'];
//Grab all the SKUs in cart
$skus = array();
foreach( WC()->cart->get_cart() as $cart_item ) {
array_push($skus, $cart_item['data']->get_sku());
}
//Check if anything matches in both
$matchingResult = array_intersect($checkSKUs,$skus);
if (count($matchingResult) > 0) {
//If at least 1 SKU matches then generate checkout field
woocommerce_form_field( 'checkout_checkbox', array( // CSS ID
'type' => 'checkbox',
'class' => array('form-row mycheckbox'), // CSS Class
'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, // Mandatory or Optional
'label' => 'I acknowledge that my product can take up to 24 hours to be delivered. (Unless the description says otherwise)', // Label and Link
));
}
}
}
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['checkout_checkbox'] ) ) {
wc_add_notice( __( 'Please acknowledge the Checkbox' ), 'error' );
}
}
I believe this should work. If not then let me know.
I've added comments for your understanding.
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.
Have a script in my functions.php to show certain custom fields I created to appear at checkout, but some products do not need these fields to appear. So I assigned these as virtual and used this code to make these only appear on standard products:
add_action( 'woocommerce_before_order_notes', 'my_checkout_fields' );
function my_checkout_fields( $checkout ) {
$only_virtual = false;
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( ! $cart_item['data']->is_virtual() ) $only_virtual = true;
}
if( $only_virtual ) {
woocommerce_form_field( 'so_childs_name', array(
'type' => 'text',
'required' => 'true',
'class' => array('cname-class form-row-wide'),
'label' => __('Child's Name'),
), $checkout->get_value( 'so_childs_name' ));
}
It works.... occasionally.
Of course, I need it to work all the time, so why isn't it working or is there is a way instead of using only_virtual, can I just use an array of product ID's?
There are some mistake and a missing closing bracket in your code (if I have well understood). Try:
add_action( 'woocommerce_before_order_notes', 'my_checkout_fields' );
function my_checkout_fields( $checkout ) {
$has_virtual = false; // Initializing
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( $cart_item['data']->is_virtual() ) {
$has_virtual = true; // Stop the loop
break;
}
}
if( ! $has_virtual ) {
woocommerce_form_field( 'so_childs_name', array(
'type' => 'text',
'required' => 'true',
'class' => array('cname-class form-row-wide'),
'label' => __('Child's Name'),
), $checkout->get_value( 'so_childs_name' ) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should work.
I working on a solution in woocommerce registration with custom checkbox.
The plan is when somebody select the custom checkbox an additional textfield opens and have to be required.
The part that works:
// add the special customer role
add_action('admin_init', 'uiwc_new_role');
function uiwc_new_role() {
add_role(
'kundenkarte',
"Kundenkarte",
array(
'read' => true,
'delete_posts' => false
)
);
}
add_action( 'woocommerce_after_order_notes', 'custom_checkout_field_with_wholesale_option' );
function custom_checkout_field_with_wholesale_option( $checkout ) {
if( current_user_can( 'wholesale_customer' ) ) return; // exit if it is "wholesale customer"
echo '<div id="wholesale_checkbox_wrap">';
woocommerce_form_field('wholesale_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Do you have a Customer Card?'),
'placeholder' => __('card'),
'required' => false,
'value' => true
), '');
echo '</div>';
}
// Conditionally change customer user role
add_action( 'woocommerce_checkout_update_order_meta', 'wholesale_option_update_user_meta' );
function wholesale_option_update_user_meta( $order_id ) {
if ( isset($_POST['wholesale_checkbox']) ) {
$user_id = get_post_meta( $order_id, '_customer_user', true ); // Get user ID
if( $user_id > 0 ){
$user = new WP_User($user_id);
$user->remove_role('customer');
$user->add_role('kundenkarte');
}
}
}
My PHP knowledge is very low.
Updated (tested and works)
With the code below, when your checkbox is checked a custom required text field is visible (with validation and save as user meta data and order meta data):
add_action( 'woocommerce_after_order_notes', 'custom_checkout_field_with_wholesale_option' );
function custom_checkout_field_with_wholesale_option( $checkout ) {
if( current_user_can( 'wholesale_customer' ) ) return; // exit if it is "wholesale customer"
echo '<style> #wholesale_card_field.hidden { display:none; }</style>
<div id="wholesale_checkbox_wrap">';
woocommerce_form_field('wholesale_checkbox', array(
'type' => 'checkbox',
'class' => array('input-checkbox'),
'label' => __('Do you have a Customer Card?'),
'placeholder' => __('card'),
'required' => false,
'value' => true
), '');
woocommerce_form_field('wholesale_card', array(
'type' => 'text',
'class' => array('hidden'),
'placeholder' => __('Customer card Id'),
'required' => true,
), '');
echo '</div>';
?>
<script>
jQuery(function($){
$('#wholesale_checkbox_field input').click(function(){
if( $(this).is(':checked')) {
$('#wholesale_card_field').css('display', 'none').removeClass('hidden').show();
} else if ( ! $(this).is(':checked') && $('#wholesale_card_field').css('display') !== 'none' ) {
$('#wholesale_card_field').hide();
}
});
});
</script>
<?php
}
// Validation
add_action( 'woocommerce_checkout_process', 'wholesale_option_validation' );
function wholesale_option_validation() {
if ( isset($_POST['wholesale_checkbox']) && isset($_POST['wholesale_card']) && empty($_POST['wholesale_card']) ) {
wc_add_notice( __("Please fill in your customer card Id"), "error" );
}
}
// Conditionally change customer user role and add customer card as order and user meta
add_action( 'woocommerce_checkout_update_order_meta', 'wholesale_option_update_meta' );
function wholesale_option_update_meta( $order_id ) {
if ( isset($_POST['wholesale_checkbox']) ) {
$user_id = get_post_meta( $order_id, '_customer_user', true ); // Get user ID
if( $user_id > 0 ){
$user = new WP_User($user_id);
$user->remove_role('customer');
$user->add_role('kundenkarte');
}
// Add customer card Id as order metadata
if ( isset($_POST['wholesale_card']) ) {
update_post_meta( $order_id, 'wholesale_card', sanitize_text_field( $_POST['wholesale_card'] ) );
if( $user_id > 0 )
update_user_meta( $user_id, 'wholesale_card', sanitize_text_field( $_POST['wholesale_card'] ) );
}
}
}
// Display customer card on admin order edit page under billing address
add_action( 'woocommerce_admin_order_data_after_billing_address', 'display_wholesale_option_admin_order', 10, 1 );
function display_wholesale_option_admin_order( $order ){
echo '<p><strong>'.__('Card Id').':</strong> ' . $order->get_meta( 'wholesale_card' ) . '</p>';
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
The following code displays a custom checkbox before add to cart button on single product pages:
add_action( 'woocommerce_before_add_to_cart_button', 'output_custom_text_field', 0 );
function output_custom_text_field() {
//Lots of code then:
<input type="checkbox" id="option1" name="option1">
}
Now I would like to trap/capture this checkbox option in Woocommerce session and then make a custom price calculations in the following code:
function final_cart_update( $cart_object ) {
foreach ( $cart_object->get_cart() as $cart_item ) {
// get the custom pricing for this product
if (isset( $_POST['option1'])) {
$pricing_custom = get_post_meta( $cart_item['product_id'], '_number_field_1', true );
}
// get product price
$price = floatval( $cart_item['data']->get_price() );
// set new price
$cart_item['data']->set_price( $price + $pricing_custom );
}
}
add_action( 'woocommerce_before_calculate_totals', 'final_cart_update', 99, 1 );
What is missing is the part that will capture the checkbox option to set it in sessions, like:
if (isset( $_POST['option1'])) {
// Set it in session
}
Any help is appreciated.
Admin Part of the code →
/*-------------------------------------------*/
/* 5. Adding Custom Field */
/*-------------------------------------------*/
// Add custom fields in "product data" settings metabox ("Advanced" tab)
add_action('woocommerce_product_options_advanced','woocious_add_custom_field_product_dashboard');
function woocious_add_custom_field_product_dashboard(){
global $post;
echo '<div class="product_custom_field">';
// Checkbox Field
woocommerce_wp_checkbox( array(
'id' => 'woocious_custom_services_fields',
'description' => __('Select if you want add on services', 'woocious'),
'label' => __('Display custom add on services', 'woocious'),
'desc_tip' => 'true',
) );
// Minimum Letter Text Box
woocommerce_wp_text_input( array(
'id' => 'addon_service_1',
'label' => __('Service 1', 'woocommerce'),
'description' => __('set custom minimum Lettering text field', 'woocommerce'),
'desc_tip' => 'true',
) );
// Number Field
woocommerce_wp_text_input(
array(
'id' => '_number_field_1',
'label' => __( 'Service amount 1', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => false,
'description' => __( "Please enter the service amount", 'woocommerce' ),
'type' => 'number',
'desc_tip' => 'true',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
// Maximum Letter Text Box
woocommerce_wp_text_input( array(
'id' => 'addon_service_2',
'label' => __('Service 2', 'woocommerce'),
'description' => __('set custom maximum Lettering text field', 'woocommerce'),
'desc_tip' => 'true'
) );
// Number Field
woocommerce_wp_text_input(
array(
'id' => '_number_field_2',
'label' => __( 'Service amount 2', 'woocommerce' ),
'placeholder' => '',
'desc_tip' => false,
'description' => __( "Please enter the service amount", 'woocommerce' ),
'type' => 'number',
'desc_tip' => 'true',
'custom_attributes' => array(
'step' => 'any',
'min' => '0'
)
)
);
echo '</div>';
}
// Save Inputted Entries, in the Product Dashboard Text Fields.
add_action('woocommerce_process_product_meta', 'woocommerce_product_custom_fields_save');
function woocommerce_product_custom_fields_save($post_id){
// Checkbox Field
$checkbox = isset( $_POST['woocious_custom_services_fields'] ) ? 'yes' : 'no';
update_post_meta( $post_id, 'woocious_custom_services_fields', $checkbox );
// Save Minimum Letters
if ( isset( $_POST['addon_service_1'] ) )
update_post_meta($post_id, 'addon_service_1', sanitize_text_field( $_POST['addon_service_1'] ) );
// Save Maximum Letters
if ( isset( $_POST['addon_service_2'] ) )
update_post_meta($post_id, 'addon_service_2', sanitize_text_field( $_POST['addon_service_2'] ) );
// Save the services amount
if ( isset( $_POST['_number_field_1'] ) )
update_post_meta($post_id, '_number_field_1', sanitize_text_field( $_POST['_number_field_1'] ) );
}
Outputting HTML on Product Page →
// Output Custom Text Field to Product Page
add_action( 'woocommerce_before_add_to_cart_button', 'output_custom_text_field', 0 );
function output_custom_text_field() {
// Get the checkbox value
$custom_option = get_post_meta( $post->ID, 'woocious_custom_services_fields', true );
// If is single product page and have the "custom text option" enabled we display the field
if ( is_product() && ! empty($custom_option) ) {
?>
<div class="woociousbuy_inner">
<div class="woociousbuy_two">
<h3>Add on Services</h3>
<input type="checkbox" id="option1" name="option1">
<label for="option1"><?php global $post; echo get_post_meta($post->ID,'addon_service_1',true);?>
<svg class="svgcheckbox" width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M13 50.986L37.334 75 88 25" stroke-width="15" stroke="#66bb6a" fill="none" fill-rule="evenodd" stroke-dasharray="150" stroke-dashoffset="150"/></svg>
</label><span class="woocense_price bold">€<?php global $post; echo get_post_meta($post->ID,'_number_field_1',true);?></span>
</div>
<div class="woociousbuy_inner">
<input type="checkbox" id="option2" name="option2"/>
<label for="option2"><?php global $post; echo get_post_meta($post->ID,'addon_service_2',true);?>
<svg class="svgcheckbox" width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><path d="M13 50.986L37.334 75 88 25" stroke-width="15" stroke="#66bb6a" fill="none" fill-rule="evenodd" stroke-dasharray="150" stroke-dashoffset="150"/></svg>
</label><span class="woocense_price bold">€<?php global $post; echo get_post_meta($post->ID,'_number_field_2',true);?></span>
</div>
</div>
<?php
}
}
You don't need to use any session for that. Use woocommerce_add_cart_item_data filter hook like:
add_action( 'woocommerce_before_add_to_cart_button', 'custom_product_option_checkbox_field' );
function custom_product_option_checkbox_field() {
echo '<p><label><input type="checkbox" id="option1" name="option1"> '.__("Option 1").'</label></p>';
}
// Add selected add-on option as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'filter_add_cart_item_data_callback', 10, 3 );
function filter_add_cart_item_data_callback( $cart_item_data, $product_id, $variation_id ) {
if ( isset( $_POST['option1'] ) && $pricing_custom = get_post_meta( $product_id, '_number_field_1', true ) ) {
$cart_item_data['pricing_custom'] = $pricing_custom;
$cart_item_data['unique_key'] = md5( microtime().rand() ); // Make each item unique
}
return $cart_item_data;
}
// Change the product price
add_action( 'woocommerce_before_calculate_totals', 'action_before_calculate_totals_callback', 10, 1 );
function action_before_calculate_totals_callback( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Avoiding hook repetition and price calculation problems
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
if ( isset( $cart_item['pricing_custom'] ) ) {
// Set the calculated price
$cart_item['data']->set_price( $cart_item['data']->get_price() + $cart_item['pricing_custom'] );
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.