I need to automatically add a product to the cart after user registration (which worked) but to decide which product to add by the user meta (which doesn't work).
The first action was just to add a product after registration and it worked perfectly:
add_action( 'user_register', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 115;
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
Now I need to add a specific product according to lists I have of users promoID I got, but it doesn't add anything to the cart.
example of the code:
add_action( 'user_register', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
$group1iid1 = array("1", "2", "3", "4");
$group1iid2 = array("5", "6", "7", "8");
if (in_array("2", $group1iid1)) {
$product_id = 115;
WC()->cart->add_to_cart( $product_id );
} elseif (in_array("0", $group1iid2)) {
$product_id = 219;
WC()->cart->add_to_cart( $product_id );
} else {
$product_id = 231;
WC()->cart->add_to_cart( $product_id );
}
}
}
If I take the code to a template file and just echo something instead of adding a product - it works ok, but when it's like this in the function.php > nothing happens.
What am I missing?
There are missing things in your code:
In your first condition you need also to add is_user_logged_in() condition, as I suppose that this code is for new registrated users only.
You need to get for the current user, HIS Promo ID value. I suppose that this value is set in user metadata, so to get this Promo ID value with get_user_meta() function, you have to define the correct meta_key.
In your code you have to replace in your conditions '2' and '0' values by the current user Promo ID… (Also elseif (in_array("0", $group1iid2)) { condition is going to be always false as "0" value doesn't exist in $group1iid2)
As I can't test for real all this, Here is some kind of work around, based on your code (without any guaranty):
add_action( 'user_register', 'add_product_to_cart' );
function add_product_to_cart( $user_id ) {
if ( ! is_admin() && $user_id > 0 ) {
// DEFINE BELOW THE META KEY TO GET THE VALUE FOR YOUR GROUP OF CURRENT USER
$meta_key = 'your_group_meta_key';
// Getting the current user group ID
$user_promo_id = get_user_meta( $user_id, $meta_key, true );
$group1_id1 = array('1', '2', '3', '4');
$group1_id2 = array('5', '6', '7', '8');
if (in_array( $user_promo_id, $group1_id1 ) ) {
$product_id = 115;
} elseif (in_array( $user_promo_id, $group1_id2 ) ) {
$product_id = 219;
} else {
$product_id = 231;
}
WC()->cart->add_to_cart( $product_id );
}
}
Related
For Woocommerce, I need a PHP snippet that will hide few products ID's I will select for guests and customers.
My code attempt:
function dma_restrict_product() {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
global $product;
if( in_array( 'customer', (array) $user_roles ) && ( is_single('3759') ) ) {
return true;
add_filter('woocommerce_is_purchasable', 'woocommerce_cloudways_purchasable');
function woocommerce_cloudways_purchasable($cloudways_purchasable, $product) {
return ($product->id == 3759 ? false : $cloudways_purchasable);
}
} else if( in_array('administrator', (array) $user_roles) ) {
return true;
} else {
return false;
}
}
But it doesn't work as I would like.
If you want to hide the product completly:
You can hide products by using the ID of the product and exclude it from the product query:
function hide_my_product( $q ) {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
if ( !in_array( 'administrator', $user_roles ) ) {
// id of product to hide
$product_id = 3759;
// exclude the id from query
$q->set( 'post__not_in', $product_id );
}
}
add_action( 'woocommerce_product_query', 'hide_my_product' );
If you want to hide the add to cart button of product:
If you want to list the product with price, but only hide the "Add to Cart" button, you can do this with the woocommerce_is_purchasable hook, that will return false for your product ids and therefore will show the price, but in the place of "Add to Cart" button the notice "Product cannot be purchased" appears.
add_filter( 'woocommerce_is_purchasable', 'hide_add_to_cart_button', 10, 2 );
function hide_add_to_cart_button( $purchasable = true, $product ) {
$user = wp_get_current_user();
$user_meta = get_userdata($user->ID);
$user_roles = $user_meta->roles;
if ( !in_array( 'administrator', $user_roles ) && $product->get_id() == 3759 ) {
$purchasable = false;
}
return $purchasable;
}
There are 2 different request on your question (one in the title and another a bit different in the body):
1). To avoid guests and customers to purchase some defined products (hiding or disabling add to cart button), use the following:
add_filter( 'woocommerce_is_purchasable', 'restrict_purchases_on_defined_product', 10, 2 );
function restrict_purchases_on_defined_product( $is_purchasable, $product ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
// HERE define your product ID(s) that will noot be purchassable
$restricted_product_ids = array(37, 53, 70);
if ( array_intersect( array( $product->get_id(), $product->get_parent_id() ), $restricted_product_ids ) ) {
return false;
}
}
return $is_purchasable;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
2). To hide completely some defined products from guests and customers, use the following:
// Settings: HERE define your product ID(s) that will not be purchasable
function my_hidden_product_ids() {
return array(37, 53, 70);
}
// Hide some products from product loops
add_action( 'woocommerce_product_query', 'hide_defined_product' );
function hide_defined_product( $query ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
$query->set( 'post__not_in', $hidden_product_ids );
}
}
// Redirect some product pages to main shop page (for security)
add_action( 'template_redirect', 'redirect_defined_product_single_pages' );
function redirect_defined_product_single_pages( $query ) {
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
if ( in_array( get_queried_object_id(), $hidden_product_ids ) ) {
wp_redirect( wc_get_page_permalink( 'shop' ) );
exit();
}
}
}
// Check and remove related cart items silently (for security)
add_action('woocommerce_before_calculate_totals', 'remove_specific_products_from_cart', 10, 1 );
function remove_specific_products_from_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// For guest users or "customer" user role
if ( ! is_user_logged_in() || current_user_can( 'customer' ) ) {
$hidden_product_ids = my_hidden_product_ids();
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) {
if ( array_intersect( array( $cart_item['product_id'], $cart_item['variation_id'] ), $hidden_product_ids ) ) {
$cart->remove_cart_item( $cart_item_key );
}
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related: Hide a specific Woocommerce products from loop if they are in cart
So I can use this snippet from the woocommerce docs and it works to add a free product when a cart total is reached. However, our customers need to be able to remove the product from the cart if they don't want it (repeat customers that don't want the same gift every time). With this snippet, the remove from cart button doesn't work for the free product.
/**
* Add another product depending on the cart total
*/
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 2831; //replace with your product id
$found = false;
$cart_total = 30; //replace with your cart total needed to add above item
if( $woocommerce->cart->total >= $cart_total ) {
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_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 );
}
}
}
}
``
code above is from here: https://docs.woocommerce.com/document/automatically-add-product-to-cart-on-visit/
Removing the product from the cart will actually work, but the problem is that the code will also automatically re-add the product again.
One way to solve this would be to remember that the product has already been added once, and to not re-add the product if the product would be added another time (after it has been removed from the cart for example).
A simple way to do that would be to save that data inside of the WooCommerce session, using WC()->session. Modified code below:
add_action( 'template_redirect', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 2831; //replace with your product id
$found = false;
$cart_total = 10; //replace with your cart total needed to add above item
if( $woocommerce->cart->total >= $cart_total && ! WC()->session->get( 'free_item_given', false ) ) { // <--- ADDED CHECK FOR free_item_given HERE
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found ) {
$woocommerce->cart->add_to_cart( $product_id );
WC()->session->set( 'free_item_given', true ); // <--- REMEMBER free_item_given HERE
}
} else {
// if no products in cart, add it
$woocommerce->cart->add_to_cart( $product_id );
WC()->session->set( 'free_item_given', true ); // <--- REMEMBER free_item_given HERE
}
}
}
}
I hope that it solves your problem!
I am trying to implement a function that will check if a customer has ever bought ANY product from my shop before, and if not - provide them with a free "sign-up gift" on first purchase.
I am able to automatically add the product to the cart fine enough, but the issue occurs afterwards - the product keeps getting added to the cart even after a customer has made a purchase.
Code below - can't figure what the issue might be.
function has_bought( $user_id = 0 ) {
global $wpdb;
$customer_id = $user_id == 0 ? get_current_user_id() : $user_id;
$paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );
$results = $wpdb->get_col( "
SELECT p.ID FROM {$wpdb->prefix}posts AS p
INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
AND p.post_type LIKE 'shop_order'
AND pm.meta_key = '_customer_user'
AND pm.meta_value = $customer_id
" );
// Count number of orders and return a boolean value depending if higher than 0
return count( $results ) > 0 ? true : false;
}
function aaptc_add_product_to_cart() {
if( ! has_bought() && ! is_admin() && is_user_logged_in() ) {
$product_id = 2449; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'aaptc_add_product_to_cart' );
**** EDIT ****
Based on the support provided I have some new code that auto-adds the product to the cart, checks for orders and removes the product if orders exist.
Can someone please confirm whether the code below is correct?
/*
* Automatically add product to cart
*/
function insta_add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 2449; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'insta_add_product_to_cart' );
function remove_shirt_returning_customer() {
$product_id = 2449; // Product Id of the free product which will get added to cart
$user_id = get_current_user_id();
// Get orders by customer.
$args = array(
'customer_id' => $user_id,
);
$orders = wc_get_orders( $args );
if ( !empty($orders) ) {
WC()->cart->remove_cart_item( $product_id );
}
}
add_action( 'init', 'remove_shirt_returning_customer' );
**** EDIT ***
THE SOLUTION
So the previous code still gave me errors. What seems to work effectively (in my localhost environment) is the code below.
/*
* Automatically add product to cart
*/
function insta_add_product_to_cart() {
if ( ! is_admin() ) {
$product_id = 51; // Product Id of the free product which will get added to cart
$found = false;
//check if product already in cart
if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->get_id() == $product_id )
$found = true;
}
// if product not found, add it
if ( ! $found )
WC()->cart->add_to_cart( $product_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $product_id );
}
}
}
add_action( 'init', 'insta_add_product_to_cart' );
/*
* Remove item from cart if previous order exists
*/
function remove_shirt_returning_customer() {
if ( ! is_admin() ) {
$cart_items = WC()->cart->get_cart();
$product_id = 51; // Product Id of the free product which will get added to cart
$user_id = get_current_user_id();
// Get orders by customer.
$args = array(
'customer_id' => $user_id,
);
$orders = wc_get_orders( $args );
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
if ( $cart_item['product_id'] == $product_id && !empty( $orders ) ) {
WC()->cart->remove_cart_item( $cart_item_key );
}
}
}
}
add_action( 'init', 'remove_shirt_returning_customer' );
Instead of using that custom query try using the wc_get_orders function you can retrieve all the orders from a customer using the email address or the user id
// Get orders by customer with ID 12.
$args = array(
'customer_id' => 12,
);
$orders = wc_get_orders( $args );
More info about the wp_get_orders can be found here
You're only going to be able to tell whether the user has ordered from you before or not if they are logged into an account. So if the user is on your site and is logged into the account, you will have to find out which user that is:
$user_id = get_current_user_id();
From there use Enrique's answer to obtain whether that customer has placed an order with you or not.
$user_id = get_current_user_id();
$args = array(
'customer_id' => 12,
);
$orders = wc_get_orders( $args );
From there, test whether $orders is empty or not, if empty leave the item as a default in the cart, if not remove it.
A better approach would be to just automatically have the item in all carts, then conditionally check whether this user is logged in, and has placed an order with you before. If so, remove the item.
I'm creating a WooCommerce add-on to customize the product, based on selected options by the visitor and custom price is calculated and stored into session table also.
I am able to get that value in cart page also.
My problem: I would like to change the default price of the product and replace it with new calculated value in the WooCommerce process as cart, checkout, payment, mail notifications, order...
Any advice please?
Thanks
Ce right hook to get it working is woocommerce_before_calculate_totals. But you will have to complete (replace) the code to get the new price in the hooked function below:
add_action( 'woocommerce_before_calculate_totals', 'custom_cart_items_prices', 10, 1 );
function custom_cart_items_prices( $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 ) {
// Get the product id (or the variation id)
$product_id = $cart_item['data']->get_id();
// GET THE NEW PRICE (code to be replace by yours)
$new_price = 500; // <== Add your code HERE
// Updated cart item price
$cart_item['data']->set_price( $new_price );
}
}
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 on WooCommerce versions 3+. But as you don't give any code I can't test it for real getting the new price from session…
function save_subscription_wrap_data( $cart_item_data, $product_id ) {
$include_as_a_addon_subscription = get_field('include_as_a_addon_subscription',$product_id);
$subscricption_product_data = get_field('subscricption_product',$product_id);
$current_user = is_user_logged_in() ? wp_get_current_user() : null;
$subscriptions = wcs_get_users_subscriptions( $current_user->ID );
if($include_as_a_addon_subscription == "yes")
{
foreach ( $subscriptions as $subscription_id => $subscription ) {
$subscription_status = $subscription->get_status();
}
if($subscription_status == 'active')
{
$cart_item_data[ "subscribe_product" ] = "YES";
}
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'save_subscription_wrap_data', 99, 2 );
function render_meta_on_cart_and_checkout1( $cart_data, $cart_item = null ) {
$meta_items = array();
if( !empty( $cart_data ) ) {
$meta_items = $cart_data;
}
if( isset( $cart_item["subscribe_product"] ) ) {
$meta_items[] = array( "name" => "Product Type", "value" => "Package Addon" );
}
return $meta_items;
}
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout1', 100, 2 );
function calculate_gift_wrap_fee( $cart_object ) {
if( !WC()->session->__isset( "reload_checkout" )) {
$additionalPrice = 100;
foreach ( WC()->cart->get_cart() as $key => $value ) {
if( isset( $value["subscribe_product"] ) ) {
if( method_exists( $value['data'], "set_price" ) ) {
$orgPrice = floatval( $value['data']->get_price() );
//$value['data']->set_price( $orgPrice + $additionalPrice );
$value['data']->set_price(0);
} else {
$orgPrice = floatval( $value['data']->price );
//$value['data']->price = ( $orgPrice + $additionalPrice );
$value['data']->price = (0);
}
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'calculate_gift_wrap_fee', 99 );
I have searched far and wide for a solution to add a free item (that I have hidden with woocommerce) to the cart when someone enters the hiddenproduct coupon I made. This is the code that I am using, it is a modified version of this:http://docs.woothemes.com/document/automatically-add-product-to-cart-on-visit/. The difference is instead of using the cart total to add it, I am trying to use the applied coupon.
Here is my current code and it is not adding the product to the cart:
add_action( 'init', 'add_product_to_cart' );
function add_product_to_cart() {
if ( ! is_admin() ) {
global $woocommerce;
$product_id = 1211;
$found = false;
$coupon_id = 1212;
if( $woocommerce->cart->applied_coupons == $coupon_id ) {
//check if product already in cart
if ( sizeof( $woocommerce->cart->get_cart() ) > 0 ) {
foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
$_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 );
}
}
}
}
I am pretty sure that the error is happening here '( $woocommerce->cart->applied_coupons == $coupon_id )' but I do not know the correct identifiers.
This is in my functions.php
Can anyone help me out? Thank you
I was in a similar situation and used some of your code and made some tweaks.. This worked for me: if(in_array($coupon_id, $woocommerce->cart->applied_coupons)){
Cheers!
I know this is ancient, but I had basically the same need. So I thought I'd go ahead and post my solution. I'm hardly an expert on any of this, so I'm sure there's plenty of room for improvement. I put this in my functions.php (obviously borrowing a lot from the original post here):
function mysite_add_to_cart_shortcode($params) {
// default parameters
extract(shortcode_atts(array(
'prod_id' => '',
'sku' => '',
), $params));
if( $sku && !$prod_id ) $prod_id = wc_get_product_id_by_sku($sku);
if($prod_id) {
$cart_contents = WC()->cart->get_cart_contents();
if ( sizeof( $cart_contents ) > 0 ) {
foreach ( $cart_contents as $values ) {
$cart_prod = $values['product_id'];
if ( $cart_prod == $prod_id ) $found = true;
}
// if product not found, add it
if ( ! $found ) WC()->cart->add_to_cart( $prod_id );
} else {
// if no products in cart, add it
WC()->cart->add_to_cart( $prod_id );
}
}
return '';
}
add_shortcode('mysite_add_to_cart','mysite_add_to_cart_shortcode');
add_action( 'woocommerce_applied_coupon', 'mysite_add_product' );
function mysite_add_product($coupon_code) {
$current_coupon = new WC_Coupon( $coupon_code );
$coupon_description = $current_coupon->get_description();
do_shortcode($coupon_description);
return $coupon_code;
}
This lets me add a shortcode in the coupon description that specifies what product should get added when the coupon is applied. It can be either [mysite_add_to_cart prod_id=1234] or [mysite_add_to_cart sku=3456]. So far it seems to be working fine.