Reputation: 45
I am trying to build a WooCommerce cart rule functionality. It should work like this:
When the user's role is "Wholesaler", they must add to the cart at least 2 or 3 items (depending on the category) of the same product category. Once that condition is met, they could add any product to the cart no matter the rules set before.
E.g:
Scenarios:
Based on Prevent WooCommerce checkout if minimum quantity for a category is not reached unless another category is added answer code, this is my code attempt:
function action_woocommerce_check_cart_items() {
// Only run on the cart or checkout pages
if ( is_cart() || is_checkout() ) {
// Minimum
$minimum = 3;
// Category
$category1 = 'socks';
$category2 = 'hats';
// Initialize
$total_socks = 0;
$total_hats = 0;
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $category1, 'product_cat', $product_id ) ) {
// Add to total
$total_socks += $cart_item['quantity'];
}
elseif ( has_term( $category2, 'product_cat', $product_id ) ) {
// Add to total
$total_hats += $cart_item['quantity'];
}
}
// When total is greater than 0 but less than the minimum
if ( ($total_socks > 0 && $total_socks < $minimum) && ( $total_hats > 0 && $total_hats < $minimum ) ) {
// Notice
wc_add_notice( sprintf( __( 'A minimum of %s products are required from the %s category before checking out.', 'woocommerce' ), $minimum, $category1 ), 'error' );
// Optional: remove proceed to checkout button
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );
But I couldn’t add a user role check and mixed with the other categories missing on the script (socks and shirts), any advice?
Upvotes: 1
Views: 655
Reputation: 29614
First of all, you can use the wp_get_current_user()
function to check if the current user has the specified capability.
Then you better use a $settings
array that you will loop through against multiple if/else conditions because this is more effective and much shorter to use.
Via the $settings
array you can set the "category" and the "minimun", "total" should not be adjusted!
Generating the error message can be done in different ways, but a loop is used again to automatically create the message.
So you get:
function action_woocommerce_check_cart_items() {
// Logged in
if ( is_user_logged_in() ) {
// Get user role(s)
$user = wp_get_current_user();
$roles = ( array ) $user->roles;
// Compare, set the desired user role(s)
$compare = array_diff( $roles, array( 'wholesaler', 'wholesale_customer', 'administrator' ) );
// When empty
if ( empty ( $compare ) ) {
// Settings (multiple settings arrays can be added/removed if desired)
$settings = array(
array(
'category' => 'socks',
'minimum' => 3,
'total' => 0
),
array(
'category' => 'hats',
'minimum' => 3,
'total' => 0
),
array(
'category' => 'shirts',
'minimum' => 2,
'total' => 0
)
);
// Initialize
$flag = false;
// Collect data - loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// Get product ID
$product_id = $cart_item['product_id'];
// Get quantity
$product_quantity = $cart_item['quantity'];
// Loop trough settings array
foreach ( $settings as $key => $setting ) {
// Checks if the current product has any of given terms
if ( has_term( $setting['category'], 'product_cat', $product_id ) ) {
// Add to the total
$settings[$key]['total'] += $product_quantity;
}
// Checks if the current total is equal to or greater than the minimum
if ( $setting['total'] >= $setting['minimum'] ) {
// Make true, break loop
$flag = true;
break;
}
}
}
// NOT true
if ( ! $flag ) {
// Initialize
$message = '';
$first_letter = __( 'A ', 'woocommerce' );
// Generate error messages - loop trough settings array
foreach ( $settings as $key => $setting ) {
// NOT the first iteration in a foreach loop, convert to capital letter
if ( $key !== array_key_first( $settings ) ) {
// Make a string lowercase
$first_letter = strtolower( $first_letter );
}
// Generate message, append
$message .= sprintf( __( '%s minimum of %s products are required from the "%s" category', 'woocommerce' ), $first_letter, $setting['minimum'], $setting['category'] );
// NOT the last iteration in a foreach loop, append 'OR'
if ( $key !== array_key_last( $settings ) ) {
$message .= '<strong>' . __( ' OR ', 'woocommerce' ) . '</strong>';
}
}
// Append to message
$message .= __( ' before checking out.', 'woocommerce' );
// Notice
wc_add_notice( $message, 'error' );
// Removing the proceed button, until the condition is met
remove_action( 'woocommerce_proceed_to_checkout','woocommerce_button_proceed_to_checkout', 20 );
}
}
}
}
add_action( 'woocommerce_check_cart_items', 'action_woocommerce_check_cart_items', 10 );
Upvotes: 1