In woocommerce I am trying to change the user role depending on customer purchased products. I saw the various code and tried them all without being able to make them work.
I have several products to check for different user roles change.
This is my code attempt:
add_action('woocommerce_order_status_completed', 'change_role_on_purchase' );
$products_to_check = array( '5345, 5344,5342' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Change role
$user->remove_role( 'Subscriber' );
$user->add_role( 'Student-Group' );
// Exit the loop
break;
}
}
$products_to_check = array( '5353, 5352,5351,12119' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Change role
$user->remove_role( 'Subscriber' );
$user->add_role( 'Student-11free2' );
// Exit the loop
break;
}
}
$products_to_check = array( '5360, 5359,5358' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Change role
$user->remove_role( 'Subscriber' );
$user->add_role( 'Student-11free3' );
// Exit the loop
break;
}
}
$products_to_check = array( '5363, 5362,5361' );
foreach ( $items as $item ) {
if ( $order->user_id > 0 && in_array( $item['product_id'], $products_to_check ) ) {
$user = new WP_User( $order->user_id );
// Change role
$user->remove_role( 'Subscriber' );
$user->add_role( 'Student-11regular2' );
// Exit the loop
break;
}
}
But it doesn't work. Any help will be appreciated.
Since Woocommerce 3 your code is outdated and full of mistakes… Instead use the following:
add_action('woocommerce_order_status_completed', 'change_user_role_on_order_status_completed', 10, 2 );
function change_user_role_on_order_status_completed( $order_id, $order ){
if ( $order->get_user_id() > 0 ) {
// Here your settings in this multi dimensional array
$user_roles_for_products = array(
'Student-Group' => array( 5345, 5344, 5342 ),
'Student-11free3' => array( 5353, 5352, 5351, 12119 ),
'Student-11free3' => array( 5360, 5359, 5358 ),
'Student-11regular2' => array( 5363, 5362, 5361 ),
);
$user = $order->get_user();
// Loop through order items
foreach ( $order->get_items() as $item ) {
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Loop through all products to check
foreach ( $user_roles_for_products as $role => $products_to_check ) {
if ( array_intersect( $product_ids, $products_to_check ) && in_array( 'Subscriber', $user->roles ) ) {
$user->remove_role( 'Subscriber' );
$user->add_role( $role );
$break = true;
break; // Stop the loop
}
}
if( isset($break) && $break )
break; // Stop the loop
}
}
}
Code goes in function.php file of your active child theme (or active theme). It should better works.
Related
I'd like to add a custom message below the available shipping methods in the cart, but only if ALL products in the cart have a tag named 'express'.
Therefore I use this snippet:
add_action( 'woocommerce_after_shipping_rate', 'action_after_shipping_rate', 20, 2 );
function action_after_shipping_rate ( $method, $index ) {
if( 'flat_rate:1' === $method->id ) {
echo __("<p>Arriving on your chosen date between 9am - 1pm Perfect for business addresses & special occasions</p>");
}
if( 'flat_rate:2' === $method->id ) {
echo __("<p>Arriving on your chosen date between 9am - 7pm Perfect for residential addresses</p>");
}
}
add_filter( 'woocommerce_shipping_details', 'hide_shipping_details', 10, 2 );
function hide_shipping_details( $rates, $package ) {
$terms = array( 'express' );
$taxonomy = 'product_tag';
$found = false;
foreach( $package['contents'] as $cart_item ) {
if ( !has_term( $terms, $taxonomy, $cart_item['product_id'] ) ){
$found = true;
break;
}
}
if ( $found === false ) {
remove_action( 'woocommerce_after_shipping_rate', 'action_after_shipping_rate', 20, 2 );
}
}
But right now, the custom message remains if 1 or 2 products have the tag 'express' but not ALL products. Can someone help me solve this problem?
No need to call from one hook to another, while you can just loop through all the products in cart in the woocommerce_after_shipping_rate hook
So you get:
function action_woocommerce_after_shipping_rate( $method, $index ) {
// Settings
$terms = array( 'express', 'tag-1' );
$taxonomy = 'product_tag';
// Initialize
$flag = false;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
// Checks if the current product has NOT any of given terms
if ( ! has_term( $terms, $taxonomy, $cart_item['product_id'] ) ) {
$flag = true;
break;
}
}
// When false
if ( ! $flag ) {
// Compare
if ( $method->get_id() === 'flat_rate:1' ) {
$text = 'My text 1';
} elseif ( $method->get_id() === 'flat_rate:3' ) {
$text = 'My text 2';
} elseif ( $method->get_id() === 'local_pickup:1' ) {
$text = 'My text 3';
}
// When isset
if ( isset( $text ) ) {
// Output
echo '<p>' . sprintf( __( '%s', 'woocommerce' ), $text ) . '</p>';
}
}
}
add_action( 'woocommerce_after_shipping_rate', 'action_woocommerce_after_shipping_rate', 10, 2 );
I'm using Awesome Support and I want to add a filter to manually assign the agent to answer the tickets.
This is the funcition:
function wpas_find_agent( $ticket_id = false ) {
if ( defined( 'WPAS_DISABLE_AUTO_ASSIGN' ) && true === WPAS_DISABLE_AUTO_ASSIGN ) {
return apply_filters( 'wpas_find_available_agent', wpas_get_option( 'assignee_default' ), $ticket_id );
}
$users = shuffle_assoc( wpas_get_users( apply_filters( 'wpas_find_agent_get_users_args', array( 'cap' => 'edit_ticket' ) ) ) );
$agent = array();
foreach ( $users->members as $user ) {
$wpas_agent = new WPAS_Member_Agent( $user );
/**
* Make sure the user really is an agent and that he can currently be assigned
*/
if ( true !== $wpas_agent->is_agent() || false === $wpas_agent->can_be_assigned() ) {
continue;
}
$count = $wpas_agent->open_tickets(); // Total number of open tickets for this agent
if ( empty( $agent ) ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
} else {
if ( $count < $agent['tickets'] ) {
$agent = array(
'tickets' => $count,
'user_id' => $user->ID,
);
}
}
}
if ( is_array( $agent ) && isset( $agent['user_id'] ) ) {
$agent_id = $agent['user_id'];
} else {
$default_id = wpas_get_option( 'assignee_default', 1 );
if ( empty( $default_id ) ) {
$default_id = 1;
}
$agent_id = $default_id;
}
return apply_filters( 'wpas_find_available_agent', (int) $agent_id, $ticket_id );
}
And this is the filter I want to add:
add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2);
function asignar_agente($agent_id){
$term_list = wp_get_post_terms( $ticket_id, 'department', array( 'fields' => 'ids' ) );
if($term_list[0] == 34){
$agent_id = 2;
}else{
$agent_id = 3;
}
return $agent_id;
}
How can I pass the $ticket_id variable to the filter to use it?
I need this variable because I need to know the term (department taxonomy) of the ticket is being submitted.
Thank you.
Since you pass $ticket_id when you call apply_filters('wpas_find_available_agent'....); you will be able to get the $ticket_id if you change your filter function to.
function asignar_agente($agent_id, $ticket_id){ <--- just add this parameter here
...
}
this is possible since you pass the parameter in apply_filters and you say add_filter('wpas_find_available_agent', 'asignar_agente', 10, 2); with emphasis on the last parameter with the value 2, that means your filter function will be able to receive 2 parameters.
I want to unset the payment method 'bacs' for the product ID 6197.
I have tried the code below, but this does not have the desired result.
add_filter( 'woocommerce_available_payment_gateways', 'wp_unset_gateway_by_id', 10, 2 );`
function wp_unset_gateway_by_id( $available_gateways, $products) {
global $woocommerce;
$unset = false;
$product_ids = array('6197');
if( in_array( $product->get_id(), $product_ids ) || ( $product->is_type('variation') && in_array( $product->get_parent_id(), $product_ids ) ) ){
unset( $available_gateways['bacs'] );
return $available_gateways;
}
}
I believe I am doing something wrong, but I am relatively new to this. Any advice would be appreciated.
$products is not passed as argument to the woocommerce_available_payment_gateways filter hook
Apply it in the following way:
function filter_woocommerce_available_payment_gateways( $payment_gateways ) {
// Not on admin
if ( is_admin() ) return $payment_gateways;
// The targeted product ids (several can be added, separated by a comma)
$targeted_ids = array( 6197 );
// Flag
$found = false;
// WC Cart
if ( WC()->cart ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
}
// True
if ( $found ) {
// Bacs
if ( isset( $payment_gateways['bacs'] ) ) {
unset( $payment_gateways['bacs'] );
}
}
return $payment_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
I actually want to create an easy function but it doesn't seem to work.
I want that when a user logs to his account on Wordpress to change his role (subscriber -> directory_1) on some condition (easy in this case to test, it should change everytime, but still not working).
Here is my code :
add_action('wp_login', 'update_roles');
function update_roles()
{
global $wpdb;
$author = wp_get_current_user();
if(current_user_can('subscriber'))
{
$author->remove_role( 'subscriber' );
$author->add_role( 'directory_1' );
}
}
Thanks for the help!
You should be using wp_update_user() to update a user's role. After you have added a role using add_role(), you can do something like this:
function custom_update_roles( $user_login, $user ) {
if ( ! empty( $user->roles ) && is_array( $user->roles ) ) {
if ( in_array( "subscriber", $user->roles ) ) {
$user_id = wp_update_user( array( 'ID' => $user->ID, 'role' => 'directory_1' ) );
if ( is_wp_error( $user_id ) ) {
// Error.
} else {
// Success.
}
} else {
// This user is not a subscriber.
}
}
}
add_action( 'wp_login', 'custom_update_roles', 10, 2 );
Refs:
http://codex.wordpress.org/Function_Reference/wp_update_user
http://codex.wordpress.org/Function_Reference/add_role
I found this sweet plugin that will automatically add a menu item to your custom menu for pages. All I need to do is tweak it to work for a hierarchal Custom Post Type. I'm thinking it will be easy for some of you... hopefully :) Thanks in advance.
Here it the code:
class AutoSubmenu {
/**
* Constructor
*/
function __construct() {
add_action( 'publish_page', array( &$this, 'on_publish_page' ) );
}
/**
* When publishing a new child page, add it to the appropriate custom menu.
*/
function on_publish_page( $post_id ) {
// Theme supports custom menus?
if ( ! current_theme_supports( 'menus' ) ) {
return;
}
// Published page has parent?
$post = get_post( $post_id );
if ( ! $post->post_parent ) {
return;
}
// Get menus with auto_add enabled
$auto_add = get_option( 'nav_menu_options' );
if ( empty( $auto_add ) || ! is_array( $auto_add ) || ! isset( $auto_add['auto_add'] ) ) {
return;
}
$auto_add = $auto_add['auto_add'];
if ( empty( $auto_add ) || ! is_array( $auto_add ) ) {
return;
}
// Loop through the menus to find page parent
foreach ( $auto_add as $menu_id ) {
$menu_parent = NULL;
$menu_items = wp_get_nav_menu_items( $menu_id, array( 'post_status' => 'publish,draft') );
if ( ! is_array( $menu_items ) ) {
continue;
}
foreach ( $menu_items as $menu_item ) {
// Item already in menu?
if ( $menu_item->object_id == $post->ID ) {
continue 2;
}
if ( $menu_item->object_id == $post->post_parent ) {
$menu_parent = $menu_item;
}
}
// Add new item
if ( $menu_parent ) {
wp_update_nav_menu_item( $menu_id, 0, array(
'menu-item-object-id' => $post->ID,
'menu-item-object' => $post->post_type,
'menu-item-parent-id' => $menu_parent->ID,
'menu-item-type' => 'post_type', /*array( 'post_type' => 'bio_diversity')*/
'menu-item-status' => 'publish'
) );
}
}
}
}
$auto_submenu = new AutoSubmenu();