Change role after purchasing a specific product on WooCommerce - wordpress

I need to add a function which changes the user’s role after purchasing a specific product (by ID, or category). How can I do so?

You can use this code
add_action( 'woocommerce_order_status_completed', 'misha_change_role_on_purchase' );
function misha_change_role_on_purchase( $order_id ) {
// get order object and items
$order = new WC_Order( $order_id );
$items = $order->get_items();
$product_id = 55; // that's a specific product ID
foreach ( $items as $item ) {
if( $product_id == $item['product_id'] && $order->user_id ) {
$user = new WP_User( $order->user_id );
// Remove role
$user->remove_role( 'customer' );
// Add role
$user->add_role( 'subscriber' );
}
}
}
If you want to check by category, just add a condition with has_term( $category_id, 'product_cat', $item['product_id'] )

Related

How to change user rol after buying in Woocommerce

thank you for any of you guys wanted to help me, I just want to know how to change the user role in WordPress when users buy something. I'm using WooCommerce. Regards
You can use Woocommerce action hooks. check my below code.
add_action( 'woocommerce_thankyou', 'change_user_role_afte_buying' );
function change_user_role_afte_buying( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
$products_to_check = array( '1', '2', '3' ); // your product ids for checking someting buy
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id ); // get user Object
$user->remove_role( 'customer' ); // remove old role
$user->add_role( 'new-role' ); // add new role
break; // Exit the loop
}
}
}

WooCommerce New order email manually trigger for some products

Please i find this code as solution for WooCommerce New order email manually trigger for some products but I don't know where exactly putting this code in functions.php or else thanks.
/**
* Modified from https://www.skyverge.com/blog/add-woocommerce-email-recipients-conditionally/
*
* Add another email recipient for admin New Order emails if a product from a specific category or with a specific tag is ordered
*
* #param string $recipient a comma-separated string of email recipients (will turn into an array after this filter!)
* #param \WC_Order $order the order object for which the email is sent
* #return string $recipient the updated list of email recipients
*/
function sv_conditional_email_recipient( $recipient, $order ) {
// Bail on WC settings pages since the order object isn't yet set yet
// Not sure why this is even a thing, but shikata ga nai
$page = $_GET['page'] = isset( $_GET['page'] ) ? $_GET['page'] : '';
if ( 'wc-settings' === $page ) {
return $recipient;
}
// just in case
if ( ! $order instanceof WC_Order ) {
return $recipient;
}
$items = $order->get_items();
// check if product from category or with tag is in order
foreach ( $items as $item ) {
$product = $order->get_product_from_item( $item );
$args = array('orderby' => 'name', 'order' => 'ASC', 'fields' => 'names');
$product_cats = wp_get_post_terms( $product->get_id, 'product_cat', $args ); // could swap product_cat for product_tag
// add our extra recipient if there's a product from the category with slug "dieta" - commas needed!
// we can bail if we've found one, no need to add the recipient more than once
if ( $product && in_array( "dieta", $product_cats ) ) {
$recipient .= ', notify#example.com';
return $recipient;
}
}
return $recipient;
}
add_filter( 'woocommerce_email_recipient_new_order', 'sv_conditional_email_recipient', 10, 2 );
I code this one and it works on my website, don't forget to replace the_name_of_the_cat by the name of the category and first_email#domain.com,second_email#domain.com by the two emails.
function change_email_recipient_depending_of_cat ( $recipient, $order ) {
global $woocommerce;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( has_term( 'the_name_of_the_cat', 'product_cat', $product_id ) ) {
$recipient = 'first_email#domain.com,second_email#domain.com';
}
return $recipient;
}
}
add_filter( 'woocommerce_email_recipient_new_order', 'change_email_recipient_depending_of_cat', 10, 2 );

Save WooCommerce Order Product Name to User Meta Custom Field

Caveat: I'm a solo freelance designer not a developer ;-)
I've created a custom field in the Wordpress user meta called membership.
I've tried the following code to save the WooCommerce Product Name to the membership custom field on checkout with help from this answer.
Updated attempt:
function wascc_woocommerce_checkout_update_user_meta_membership ( $customer_id, $posted ) {
if (isset($posted['$orderid'])) {
$order = $posted['$orderid'];
}
$theorder = new WC_Order( $order );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
update_user_meta( $customer_id, 'membership', $product_name);
}
}
add_action( 'woocommerce_checkout_update_user_meta', 'wascc_woocommerce_checkout_update_user_meta_membership', 10, 2 );
It produces no error, but does not save the product name to membership.
Help appreciated.
Last question may be related.
as I've commented out, you should use woocommerce_checkout_update_order_meta.
Something like this:
function wascc_woocommerce_checkout_update_user_meta_membership ( $order_id ) {
$theorder = new WC_Order( $order_id );
$items = $theorder->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
}
if (!(empty($product_name))) {
// Gets the customer/user ID associated with the order. Guests are 0.
$customer_id = $theorder->get_user_id();
update_user_meta( $customer_id, 'membership', $product_name );
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'wascc_woocommerce_checkout_update_user_meta_membership' );
I have doubts with your foreach loop though... you are looping just to get the last item?

How do I get the category name or id of a product of a woocommerce order

I have the function below which works to change the role of a user when they buy certain products, but instead of listing out specific product IDs, I'd like to just use the category name or id of those products. That way, if we add a new product in that category, I don't have to remember to add it to this function. This function is specific to a certain category, so it doesn't matter if people have other products from other categories in the order.
function lgbk_add_member( $order_id ) {
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
if ( $order->user_id > 0 && $product_id == '7' ) {
update_user_meta( $order->user_id, 'paying_customer', 1 );
$user = new WP_User( $order->user_id );
// Remove role
$user->remove_role( 'expired' );
// Add role
$user->add_role( 'customer' );
}
}
}
add_action( 'woocommerce_order_status_completed', 'lgbk_add_member' );
You have to use wp_get_post_terms to get category id of any product like this :
$term_list = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'ids'));
I am just fetching id's of categories assigned to this particular product, you can fetch name also.
You can get product category name using this function -
function get_product_category_name_by_id( $category_id ) {
$term = get_term_by( 'id', $category_id, 'product_cat', 'ARRAY_A' );
return $term['name'];
}
$product_category = get_product_category_name_by_id( $your_category_id );
Thanks!

Woocommerce add default shipping class to all products

Is there a way to add a default shipping class to all products? I have one shipping class and need an automated way to add that class to all products when they are created vs. having to constantly add the shipping class.
Many solutions
There is two solutions :
First add the term dynamically before the cart totals (add to your functions.php)
add_action('woocommerce_before_calculate_totals' , 'add_shipping_terms_before_totals' , 10, 1);
function add_shipping_terms_before_totals(WC_Cart $wc_cart){
if( count($wc_cart->get_cart()) == 0 ){
return;
}
// Here you need to edit the slug_to_edit with your custom slug
$shipping_terms = get_term_by( 'slug', 'slug_to_edit', 'product_shipping_class' );
// If can't find the terms, return
if( empty($shipping_terms) ){
return;
}
foreach( $wc_cart->get_cart() as $item){
$product = new WC_Product( $item['product_id'] );
$product_shipping_class = $product->get_shipping_class();
if( !empty($product_shipping_class) ){
continue;
}
wp_set_post_terms( $product->id, array( $shipping_terms->term_id ), 'product_shipping_class' );
}
}
Or, you can add a function that you can manually trigger when you add a products :
if( isset($_GET['update_products']) && is_super_admin() ){
add_action( 'init', 'add_shipping_terms_on_all_products' );
}
function add_shipping_terms_on_all_products(){
global $wpdb;
// Here you need to edit the slug_to_edit with your custom slug
$shipping_terms = get_term_by( 'slug', 'slug_to_edit', 'product_shipping_class' );
// If can't find the terms, return
if( empty($shipping_terms) ){
return;
}
// Request all product
$products = $wpdb->get_results( "
SELECT p.ID as ID
FROM wp_posts AS p
WHERE p.post_status = 'publish'
AND p.post_type = 'product'
" );
foreach($products as $_product){
$product = new WC_Product($_product->ID);
$product_shipping_class = $product->get_shipping_class();
if( !empty($product_shipping_class) ){
continue;
}
wp_set_post_terms( $product->id, array( $shipping_terms->term_id ), 'product_shipping_class' );
}
}
Then you just have to trigger :
http://yoururl?update_products
as admin.
Don't forget to edit slug_to_edit with your shipping class slug

Resources