Woocommerce checkout page depending on product category - wordpress

I am building on a website using woocommerce.
For some products clients need to write the name of their child in the Child name field on the checkout page. (The site sells music lessons)
However for other products like giftcards I dont need this Child name field. I can't find any plugin that can show a different checkout page depending on the catagory of the product that the client is buying.
Anyone an idea for making this possible?
Thnx in advance!

I think I found a website with the answer:
https://wordimpress.com/create-conditional-checkout-fields-woocommerce/
I'm going to try this and place the outcome here.
*** okay couple of hours later!
It did the job, the codes in the website I posted are used for a single product ID. If you want to check for category ID you can change this code:
/**
* Check if Conditional Product is In cart
*
* #param $product_id
*
* #return bool
*/
function wordimpress_is_conditional_product_in_cart( $product_id ) {
//Check to see if user has product in cart
global $woocommerce;
//flag no book in cart
$book_in_cart = false;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id === $product_id ) {
//book is in cart!
$book_in_cart = true;
}
}
return $book_in_cart;
}
for:
/**
* Check if Conditional Product is In cart
*
* #param $product_id
*
* #return bool
*/
function wordimpress_is_conditional_product_in_cart( $product_id ) {
//Check to see if user has product in cart
global $woocommerce;
//flag no book in cart
$book_in_cart = false;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
foreach ($terms as $term) {
$_categoryid = $term->term_id;
}
if ( $_categoryid === 14 ) {
//book is in cart!
$book_in_cart = true;
}
}
return $book_in_cart;
}
If you need to check multiple categorie ID's or product ID's you can copy this excample:
/**
* Check if Conditional Product is In cart
*
* #param $product_id
*
* #return bool
*/
function wordimpress_is_conditional_product_in_cart( $product_id ) {
//Check to see if user has product in cart
global $woocommerce;
//flag no book in cart
$book_in_cart = false;
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
$terms = get_the_terms( $_product->id, 'product_cat' );
foreach ($terms as $term) {
$_categoryid = $term->term_id;
}
if (( $_categoryid === 14 ) || ( $_categoryid === 16 )) {
//book is in cart!
$book_in_cart = true;
}
}
return $book_in_cart;
}
I Hope this post will hopefully save somebody a lot of time searching all the loose bits of information ;)

This worked better for me:
add_filter( 'woocommerce_checkout_fields' , 'custom_override_checkout_fields' );
add_filter( 'woocommerce_default_address_fields' , 'optional_default_address_fields' );
function optional_default_address_fields( $address_fields ) {
$address_fields['postcode']['required'] = false;
$address_fields['city']['required'] = false;
$address_fields['state']['required'] = false;
$address_fields['address_1']['required'] = false;
$address_fields['country']['required'] = false;
$address_fields['billing_company']['required'] = false;
return $address_fields;
}
function custom_override_checkout_fields( $fields ) {
$categories = array('ajakirjad');
$foundAjakiri = false;
$foundOthers = false;
foreach ( WC()->cart->get_cart() as $cart_item ){
if(has_term( $categories, 'product_cat', $cart_item['product_id'] )) {
$foundAjakiri = true;
} else {
$foundOthers = true;
}
}
if($foundAjakiri == true && $foundOthers == false) {
// echo '1';
} elseif($foundAjakiri == false && $foundOthers == true) {
$fields['billing']['billing_address_1']['required'] = false;
$fields['billing']['billing_address_2']['required'] = false;
$fields['billing']['billing_city']['required'] = false;
$fields['billing']['billing_postcode']['required'] = false;
$fields['billing']['billing_state']['required'] = false;
$fields['billing']['billing_country']['required'] = false;
$fields['billing']['billing_country']['class'][] = 'no-need';
$fields['billing']['billing_company']['required'] = false;
unset($fields['billing']['billing_address_1']);
unset($fields['billing']['billing_address_2']);
unset($fields['billing']['billing_city']);
unset($fields['billing']['billing_postcode']);
// unset($fields['billing']['billing_country']);
unset($fields['billing']['billing_state']);
// unset($fields['billing']['billing_phone']);
//unset($fields['order']['order_comments']);
}
//add_filter( 'woocommerce_enable_order_notes_field', '__return_false', 9999 );
add_filter( 'woocommerce_checkout_fields' , 'remove_order_notes' );
return $fields;
}

Related

Hide "ship to a different address" in Woocommerce based on user roles and specific products in cart

I'm trying to hide the "ship to a different address" on WooCommerce checkout page for 2 user roles, if their cart contains any of the specified product ID's.
My code is working for a single product ID:
/** Shipping Address */
function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {
// The targeted products & roles
$targeted_variation_id = 414;
$targeted_user_role = 'team';
$targeted_user_role2 = 'team2';
// Flag
$found = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
// True & user Role is
if ( $found && current_user_can( $targeted_user_role )) {
$needs_shipping = false;
}
// True & only 1 item in cart
if ( $found && current_user_can( $targeted_user_role2 )) {
$needs_shipping = false;
}
return $needs_shipping;
}
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );
But then when I try to create an array of multiple IDs, I can't achieve the desired result, this is my attempt:
**Multiple Variants**
/** Shipping Address */
function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {
// The targeted products & roles
$targeted_variation_id = array(414,617);
$targeted_user_role = 'team';
$targeted_user_role2 = 'team2';
// Flag
$found = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
// True & user Role is
if ( $found && current_user_can( $targeted_user_role )) {
$needs_shipping = false;
}
// True & only 1 item in cart
if ( $found && current_user_can( $targeted_user_role2 )) {
$needs_shipping = false;
}
return $needs_shipping;
}
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );
Anyone able to help figure out how to get it to work with multiple ID's and not just one?
The mistakes in your code is in the following line:
if ( in_array( $targeted_variation_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) )
$targeted_variation_id has been changed to an array,
while the searched value must be a string when using in_array()
It also seems more logical to check the user role first, before iterate all cart items
So you get:
function filter_woocommerce_cart_needs_shipping_address( $needs_shipping ) {
// Retrieve the current user object
$user = wp_get_current_user();
// Add your user roles, several can be entered, separated by a comma
$user_roles = array( 'team1', 'team2', 'administrator' );
// Targeted product IDs, several can be entered, separated by a comma
$targeted_product_ids = array( 30, 813, 414, 617 );
// User role is found
if ( array_intersect( $user_roles, (array) $user->roles ) ) {
// Loop through cart contents
foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
// Get product ID
$product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
// Checks if a value exists in an array
if ( in_array( $product_id, $targeted_product_ids ) ) {
$needs_shipping = false;
break;
}
}
}
return $needs_shipping;
}
add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_woocommerce_cart_needs_shipping_address', 10, 1 );

WooCommerce cart fragments isn't updated after ajax adding items

This is the code that I have on my products page template.
<p>Your total: <span class="r_cart_total"><?= WC()->cart->get_cart_total(); ?></span></p>
So whenever a product is added to cart, I have a filter that works
add_filter( 'woocommerce_add_to_cart_fragments', 'wc_refresh_cart_fragments', 50, 1 );
function wc_refresh_cart_fragments( $fragments ){
$cart_count = WC()->cart->get_cart_contents_count();
$cart_total = WC()->cart->get_cart_total();
// Normal version
$count_normal = '<span class="r_cart_total">' . $cart_total . '</span>';
$fragments['.r_cart_total'] = $count_normal;
return $fragments;
}
According to this function I am updating the span content with class '.r_cart_total'.
This function works fine when an item is removed from the cart, but whenever I add a product to cart the fragments do not get updated.
Here is the add to cart function
/**
* Add to cart product using ajax
**/
add_action('wp_ajax_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_ajax_add_to_cart', 'woocommerce_ajax_add_to_cart');
function woocommerce_ajax_add_to_cart() {
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($_POST['product_id']));
$quantity = empty($_POST['quantity']) ? 1 : wc_stock_amount($_POST['quantity']);
$variation_id = absint($_POST['variation_id']);
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity);
$product_status = get_post_status($product_id);
$is_buy_all = filter_var($_POST['is_buy_all'], FILTER_VALIDATE_BOOLEAN);
//if buy all product then remove all other products in the cart
if($is_buy_all){
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
WC()->cart->remove_cart_item( $cart_item_key );
}
}
if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id) && 'publish' === $product_status) {
do_action('woocommerce_ajax_added_to_cart', $product_id);
//show success message add to cart
if ('yes' === get_option('woocommerce_cart_redirect_after_add')) {
wc_add_to_cart_message(array($product_id => $quantity), true);
}
if($is_buy_all && !empty($_POST['sub_products'])){
$sub_products = json_decode(stripslashes($_POST['sub_products']));
foreach($sub_products as $sub_product){
$sub_product = trim($sub_product);
$sub_product_id = apply_filters('woocommerce_add_to_cart_product_id', absint($sub_product));
$quantity = 1;
$variation_id = absint($variation_id);
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $sub_product_id, $quantity);
$sub_product_status = get_post_status($sub_product_id);
if($passed_validation && WC()->cart->add_to_cart($sub_product_id, $quantity) && 'publish' === $sub_product_status) {
do_action('woocommerce_ajax_added_to_cart', $sub_product_id);
}
}
}
WC_AJAX :: get_refreshed_fragments();
wp_die();
} else {
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink($product_id), $product_id));
echo wp_send_json($data);
wp_die();
}
}

WooCommerce Hide Payment Gateway for Custom Attribute

Just starting in my WordPress/WooCommerce journey.
I found a question on here from a while back asking about restricting payment gateways for a specific attribute selection. I've tried to integrate this into my site and I cannot get it working! I've added the Attribute and Terms, and the slugs are as follows - pay_now_deposit (attr) and pay_now / deposit (terms).
I'm looking to restrict Klarna payments for those paying by deposit, and the code I have is below -
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
// See if there is an attribute called 'pa_size' in the cart
// Replace with whatever attribute you want
if (array_key_exists('pa_pay_now_deposit', (array) $values['data']->get_attributes() ) ) {
foreach ($values['data']->get_attributes() as $attribute => $variation);
// Replace 'small' with your value.
if ($variation == 'deposit') $in_cart = true; //edited
}
}
if ( $in_cart ) {
unset($available_gateways['klarna_payments']);
}
else {
unset($available_gateways['cod']);
}
return $available_gateways;
}
Any advice on where I'm going wrong would be greatly appreciated!
Try to add a break statement.
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( array_key_exists( 'pa_pay_now_deposit', (array) $values['data']->get_attributes() ) ) {
foreach ( $values['data']->get_attributes() as $attribute => $variation ){
if ( $variation == 'deposit' ){
$in_cart = true; //edited
break;
}
}
}
if( $in_cart ){
break;
}
}
if ( $in_cart ) {
unset( $available_gateways['klarna_payments'] );
}else {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}

Woocommerce how to remove coupon code box programmatically

I wonder if you can help? I'm trying to get this to work.
I want to only show the coupon box when the price is more than 19.99 AND its not product id 455821
I can't get this to work. Would you be able to give me any ideas why?
Thanks
Kevin
// START Remove coupon box when price is less than 19.99
add_filter( 'woocommerce_coupons_enabled','hide_coupon_field_on_cart' );
function hide_coupon_field_on_cart( $enabled ) {
global $product;
// $id = $product->get_id();
$product_id = 455821;
$price = "19.95";
$cart = WC()->cart->get_cart();
foreach ( $cart as $id => $cart_item ) {
// $prodid = $cart_item[ 'data' ]->$product->get_id();
if( ($cart_item[ 'data' ]->get_price() <= $price) || ( $cart_item[ 'data' ]->$product->get_id() != $product_id ) ) {
return false; // dont remove it
}
}
return $enabled;
}
// START Remove coupon box when price is less than 19.99
function hide_coupon_field_on_cart( $enabled ) {
// settings
$not_product_id = 455821;
$min_price = 19.99;
// Get cart object
$cart = WC()->cart->get_cart();
foreach ( $cart as $cart_item ) {
// product id
$product_id = $cart_item['product_id'];
// Price
$price = $cart_item['data']->get_price();
if ( $product_id == $not_product_id && $price < $min_price ) {
$enabled = false;
}
}
// Cart total <= 0
if ( WC()->cart->get_total() <= 0 ) {
$enabled = false;
}
return $enabled;
}
add_filter( 'woocommerce_coupons_enabled','hide_coupon_field_on_cart' );

Woocommerce automatic add to cart: product id

So, I found this snippet for automatically adding a product when a user visits a product page:
/*
* Add item to cart on visit
*/
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 64;
$found = false;
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $value
) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
$woocommerce->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
$woocommerce->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'add_product_to_cart' );
Now, it is for only product "id=64." How would I change it so that any products will be added.
Thank you

Resources