admin管理员组

文章数量:1318564

I'm trying to restrict the user to only being able to add items to the cart from one grouped product at a time.

I've tried writing the code in two different approaches but neither work.

These are my 2 attempts.

Attempt One:

function limit_cart_items_to_one_group ( $passed, $product_id, $quantity ) {
    if (current_user_can('stallholder') ) {

        if( WC()->cart->is_empty() ) return $passed;

        $product_type = array('terms' => array('grouped'));
        $products = wc_get_products( $args );
        $found = $current = false;

        foreach ( $products as $product ) {
           $children = array();
           foreach ( $product->get_children() as $child_id ) {
              $children[] = $child_id;
           }
        }

        if( has_term( $children, 'product_cat', $product_id ) ){
            $current = true;
        }

            foreach ( WC()->cart->get_cart() as $cart_item ){
            if( has_term( $children, 'product_cat', $cart_item['product_id'] ) ) {
                $found = true;
                $current = true;
                break; // stop the loop.
            }
        }

        if( $found && $current ){
            $passed = false;
            $cats_str = implode('" and "', $children );
            wc_add_notice( sprintf( __('Only one Market date is allowed to be booked at a time. Thank you.', 'woocommerce' ), $cats_str ), 'error' );
        }
        return $passed;
    }
}
add_filter( 'woocommerce_add_to_cart_validation', 'limit_cart_items_to_one_group', 10, 3 );

Attempt 2:

function is_product_the_same_group($valid, $product_id, $quantity) {
    if (current_user_can('stallholder') ) {
    
        $product_type = array('terms' => array('grouped'));
        $products = wc_get_products( $args );

        foreach ( $products as $product ) {
           $children = array();
           foreach ( $product->get_children() as $child_id ) {
              $children[] = $child_id;
           }
        }

        global $woocommerce;
        if($woocommerce->cart->cart_contents_count == 0){
             return true;
        }
        foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
            $_product = $values['data'];
            $terms = get_the_terms( $_product->id, $children );
            $target_terms = get_the_terms( $product_id, $children );
            foreach ($terms as $term) {
                $group_ids[] = $term->term_id;  
            }
            foreach ($target_terms as $term) {
                $target_group_ids[] = $term->term_id; 
            }           
        }
        $same_group = array_intersect($group_ids, $target_group_ids);
        if(count($same_group) > 0) return $valid;
        else {
            wc_add_notice( 'This product is in another group!', 'error' );
            return false;
        }
    }
}
add_filter( 'woocommerce_add_to_cart_validation', 'is_product_the_same_group',10,3);

Basically I'm trying to restrict what this specific user role to only being able to book from one group of products at a time.

I'm trying to restrict the user to only being able to add items to the cart from one grouped product at a time.

I've tried writing the code in two different approaches but neither work.

These are my 2 attempts.

Attempt One:

function limit_cart_items_to_one_group ( $passed, $product_id, $quantity ) {
    if (current_user_can('stallholder') ) {

        if( WC()->cart->is_empty() ) return $passed;

        $product_type = array('terms' => array('grouped'));
        $products = wc_get_products( $args );
        $found = $current = false;

        foreach ( $products as $product ) {
           $children = array();
           foreach ( $product->get_children() as $child_id ) {
              $children[] = $child_id;
           }
        }

        if( has_term( $children, 'product_cat', $product_id ) ){
            $current = true;
        }

            foreach ( WC()->cart->get_cart() as $cart_item ){
            if( has_term( $children, 'product_cat', $cart_item['product_id'] ) ) {
                $found = true;
                $current = true;
                break; // stop the loop.
            }
        }

        if( $found && $current ){
            $passed = false;
            $cats_str = implode('" and "', $children );
            wc_add_notice( sprintf( __('Only one Market date is allowed to be booked at a time. Thank you.', 'woocommerce' ), $cats_str ), 'error' );
        }
        return $passed;
    }
}
add_filter( 'woocommerce_add_to_cart_validation', 'limit_cart_items_to_one_group', 10, 3 );

Attempt 2:

function is_product_the_same_group($valid, $product_id, $quantity) {
    if (current_user_can('stallholder') ) {
    
        $product_type = array('terms' => array('grouped'));
        $products = wc_get_products( $args );

        foreach ( $products as $product ) {
           $children = array();
           foreach ( $product->get_children() as $child_id ) {
              $children[] = $child_id;
           }
        }

        global $woocommerce;
        if($woocommerce->cart->cart_contents_count == 0){
             return true;
        }
        foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
            $_product = $values['data'];
            $terms = get_the_terms( $_product->id, $children );
            $target_terms = get_the_terms( $product_id, $children );
            foreach ($terms as $term) {
                $group_ids[] = $term->term_id;  
            }
            foreach ($target_terms as $term) {
                $target_group_ids[] = $term->term_id; 
            }           
        }
        $same_group = array_intersect($group_ids, $target_group_ids);
        if(count($same_group) > 0) return $valid;
        else {
            wc_add_notice( 'This product is in another group!', 'error' );
            return false;
        }
    }
}
add_filter( 'woocommerce_add_to_cart_validation', 'is_product_the_same_group',10,3);

Basically I'm trying to restrict what this specific user role to only being able to book from one group of products at a time.

Share Improve this question asked Jan 21 at 10:32 JWCreativeJWCreative 797 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

In Woocommerce a product can belong to multiple categories, so let's suppose that product1 belongs to category1 and category2.

Now, if you attempt to add product2 which belongs to category2, but not to category1, yet product2 also belongs to category3 to which product1 does not belong to, then while in your first step the term set was (category1, category2) due to product1 belonging to both, after the first step, in the second step you add product2 which belongs to category2 and category3, so your intersection of (category1, category2) and (category2, category3) will be the nonempty set of (category2) and hence product2 is successfully added and now your category set will be (category1, category2, category3) and the set of categories you accept will be ever-increasing as you add products.

So, how can you solve your task?

An approach would be to check whether the category set of the new product is the exact same set as the category set of the old product. While this makes sense technically, it's unlikely that this matches your goal. Example: someone buys a shoe that belongs to the categories of (shoes, sports), but then wants to add some fashionable shoes that belong to (shoes, fashion). If this is the approach, then the second product will not be added to the cart after the first one, because even though it's also a shoe, it's not a sport item.

A second possible approach would be to only check for the categories of the first item and see whether the new item matches any of them. So, if we go back to the example of sports shoes, then due to the fact that the first product is both a shoe and a sports item, you accept any product that is either a shoe or a sports item, but in subsequent product adding you ignore products that do not share at least a category with the first item, ignoring the categories of subsequent items.

Finally, a very strict approach would be to choose what the main category of the first item is, in our example it would likely be mainly a shoe, as it is more specific than sports, but in such cases you may need to prioritize a category of the first product over another category of the first product without having a clear difference in specificity. Assuming you choose this approach, basically you will be able to determine which is the main category of the first product and seek for that category in the case of any subsequently products that are to be added to the cart.

本文标签: phpOnly allow purchases from one group product at a time WooCommerceStack Overflow