4
votes

I need help please... Here is the code, in single product page, it displays inputs for sizes (in back-end this a multi-select in repeater fields) attached to checkboxes for colors (in back-end this a select in repeater fields), they are called by acf repeater fields. Each color can be associated with multiple sizes. The first function works well, it displays what I want. But I can't retrieve results to display them in cart as custom meta product (as product variations), could you tell me where I'm wrong please? thanks a lot, I'm lost... :-( Here is the test product : http://neo2.agencepoint.com/boutique/t-shirt-col-rond-manches-courtes-femme/

add_action( 'woocommerce_before_add_to_cart_button', 'add_custom_fields' );
function add_custom_fields() {
    global $product;
    $product_id = $product->id;
    if( get_field('tailles_et_couleurs', $product_id) ):
        while( has_sub_field('tailles_et_couleurs', $product_id) ):
            $select_couleur = get_sub_field_object('couleurs', $product_id);
            $valeur_couleur = get_sub_field('couleurs', $product_id);
            $select_taille = get_sub_field_object('tailles', $product_id);
            $valeur_taille = get_sub_field('tailles', $product_id);
            foreach( $select_couleur['choices'] as $key_couleur => $nom_couleur ):
                if( $key_couleur == $valeur_couleur ):
                    echo '<div class="conteneur_taille_couleur"><label class="label-couleur label-couleurs-meta-'.$key_couleur.'" for="couleurs-meta-'.$key_couleur.'"> <input id="couleurs-meta-'.$key_couleur.'" name="'.$key_couleur.'" data-type="palettes" type="checkbox" value="'.$nom_couleur.'"><div class="palette-box" id="palette_couleur_'.$key_couleur.'"></div><div class="nom-couleur nom-couleur-couleurs-meta-'.$key_couleur.'">'.$nom_couleur.'</div></label>';
                endif;
            endforeach;
            foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
                if (in_array($key_taille, $valeur_taille)):
                    echo '<div class="conteneur_taille"><label for="'.$key_taille.'">'.$nom_taille.'</label><input class="quantite_prdt" type="text" name="'.$key_taille.'" id="'.$key_taille.'" data-type="text" ></div>';
                endif; 
            endforeach;
            echo '</div>';
        endwhile;
    endif;
}


add_action( 'woocommerce_add_cart_item_data', 'save_my_custom_product_field', 10, 2 );
function save_my_custom_product_field( $cart_item_data, $product_id ) {
    while( has_sub_field('tailles_et_couleurs', $product_id) ):
        $select_couleur = get_sub_field_object('couleurs', $product_id);
        $valeur_couleur = get_sub_field('couleurs', $product_id);
        $select_taille = get_sub_field_object('tailles', $product_id);
        $valeur_taille = get_sub_field('tailles', $product_id);
        foreach( $select_couleur['choices'] as $key_couleur => $nom_couleur ):
            if( $key_couleur == $valeur_couleur ):
                $cart_item_data[$key_couleur] = $valeur_couleur;
                $cart_item_data['unique_key'] = md5( microtime().rand() );
            endif; 
        endforeach;
        foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
            if (in_array($key_taille, $valeur_taille)):
                $cart_item_data[$key_taille] = $valeur_taille;
                $cart_item_data['unique_key'] = md5( microtime().rand() );
            endif; 
        endforeach;
    endwhile;

    return $cart_item_data;
}
add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
    if($cart_item['variation_id'] == 0){
        $item_id = $cart_item['product_id'];
    }
    else
    {
        $item_id = $cart_item['variation_id'];
    }
    $custom_items = array();
    if( !empty( $cart_data ) ):
        $custom_items = $cart_data;
    endif;
    while( has_sub_field('tailles_et_couleurs', $product_id) ):
        $select_couleur = get_sub_field_object('couleurs', $product_id);
        $valeur_couleur = get_sub_field('couleurs', $product_id);
        $select_taille = get_sub_field_object('tailles', $product_id);
        $valeur_taille = get_sub_field('tailles', $product_id);
        foreach( $select_couleur['choices'] as $key_couleur => $nom_couleur ):
            if( $key_couleur == $valeur_couleur ):
                if( isset( $cart_item[$nom_couleur] ) ):
                    $custom_items[] = array( "name" => $nom_couleur, "value" => $cart_item[$valeur_couleur] );
                endif;
            endif; 
        endforeach;
        foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
            if (in_array($key_taille, $valeur_taille)):
                if( isset( $cart_item[$nom_taille] ) ):
                    $custom_items[] = array( "name" => $nom_taille, "value" => $cart_item[$valeur_taille] );
                endif;
            endif;
        endforeach;
    endwhile;

    return $custom_items;
}
2

2 Answers

1
votes

Your main problem in your code is getting the right product ID everywhere.

1) In your first function hooked to get the product ID you have 2 choice:

The first choice is to use this:

add_action( 'woocommerce_before_add_to_cart_button', 'add_custom_fields' );
function add_custom_fields() {
    global $product;
    $product_id = $product->id; // Here you really get the product ID

    if( get_field('tailles_et_couleurs', $product_id) ):

    // . . .  
    // And you will replace everywhere in this function $_product->id by $product_id

}

Or you can use also the WordPress function get_the_id() replacing all your $_product->id occurrences by get_the_id().


2) In your second functions you have:

function save_my_custom_product_field( $cart_item_data, $product_id ) {

So you can use directly the variable $product_id everywhere instead of $_product->id


3) In your third and last function, as you have $cart_item you will use it to get the cart item ID this way:

add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
    if($cart_item['variation_id'] == 0)
        $item_id = $cart_item['product_id'];
    else
        $item_id = $cart_item['variation_id'];

    // Your code goes here replacing everywhere $_product->id by $item_id
1
votes

I've found the answer ! First I add my inputs which come from AC repeaters :

add_action( 'woocommerce_before_add_to_cart_button', 'add_custom_fields' );
function add_custom_fields($key_couleur) {
    global $product;
    $product_id = $product->id;
    if( get_field('tailles_et_couleurs', $product_id) ):
        while( has_sub_field('tailles_et_couleurs', $product_id) ):
            $select_couleur = get_sub_field_object('couleurs', $product_id);
            $valeur_couleur = get_sub_field('couleurs', $product_id);
            $select_taille = get_sub_field_object('tailles', $product_id);
            $valeur_taille = get_sub_field('tailles', $product_id);
            if($valeur_couleur){
            foreach( $select_couleur['choices'] as $key_couleur => $nom_couleur ):
                if( $key_couleur == $valeur_couleur ):
                    $couleuralaligne=str_replace(" (","<br>(",$nom_couleur);
                    echo '<div class="conteneur_taille_couleur"><label class="label-couleur label-couleurs-meta-'.$key_couleur.'" for="couleurs-meta-'.$key_couleur.'"> <input id="couleurs-meta-'.$key_couleur.'" name="'.$key_couleur.'" data-type="palettes" type="checkbox" value="'.$nom_couleur.'"><div class="palette-box" id="palette_couleur_'.$key_couleur.'"></div><div class="nom-couleur nom-couleur-couleurs-meta-'.$key_couleur.'">'.$couleuralaligne.'</div></label>';
                    foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
                        if (in_array($key_taille, $valeur_taille)):
                            $key_couleur_et_taille = $key_couleur.'_'.$key_taille;
                            echo '<div class="conteneur_taille"><label for="'.$key_couleur_et_taille.'">'.$nom_taille.'</label><input class="quantite_prdt" type="text" name="'.$key_couleur_et_taille.'" id="'.$key_couleur_et_taille.'" data-type="text" ></div>';
                            $_SESSION['valeur_couleur']=$key_couleur_et_taille;
                        endif; 
                    endforeach;
                endif;
            endforeach;
            }else{
            foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
                if (in_array($key_taille, $valeur_taille)):
                    $key_couleur_et_taille = $key_couleur.'_'.$key_taille;
                    echo '<div class="conteneur_taille"><label for="'.$key_couleur_et_taille.'">'.$nom_taille.'</label><input class="quantite_prdt" type="text" name="'.$key_couleur_et_taille.'" id="'.$key_couleur_et_taille.'" data-type="text" ></div>';
                    $_SESSION['valeur_couleur']=$key_couleur_et_taille;
                endif; 
            endforeach;
            }  
            echo '</div>';
        endwhile;
    endif;
}

Then, here is the function for saving results when customer adds product to cart :

add_action( 'woocommerce_add_cart_item_data', 'save_my_custom_product_field', 10, 2 );
function save_my_custom_product_field( $cart_item_data, $product_id,$key_couleur,$variation_id) {
    while( has_sub_field('tailles_et_couleurs', $product_id) ):
        $select_couleur = get_sub_field_object('couleurs', $product_id);
        $valeur_couleur = get_sub_field('couleurs', $product_id);
        $select_taille = get_sub_field_object('tailles', $product_id);
        $valeur_taille = get_sub_field('tailles', $product_id);
        // $cart_item_data['couleurs_selectionnees']=array();
        $cart_item_data['tailles_couleurs']=array();
        if(isset($_POST[$valeur_couleur])){
            foreach( $select_couleur['choices'] as $key_couleur => $nom_couleur ):
                if(( $key_couleur == $valeur_couleur ) && (isset($_POST[$valeur_couleur]))):
                    $macouleur=$_REQUEST[$key_couleur];
                       $cart_item_data['couleurs_selectionnees'][$valeur_couleur] = $macouleur;
                endif;
                foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
                    if($key_taille != 'qte'){
                        $key_couleur_et_taille = $key_couleur.'_'.$key_taille;
                        $nom_couleur_et_taille = $nom_couleur.' Taille '.$nom_taille;
                        if ((isset($_POST[$key_couleur_et_taille])) && (!empty($_POST[$key_couleur_et_taille]))):
                                $qty_taille=$_REQUEST[$key_couleur_et_taille];
                                $cart_item_data['tailles_couleurs'][$nom_couleur_et_taille] = $qty_taille;
                        endif;
                    }else{
                        $key_couleur_et_taille = $key_couleur.'_'.$key_taille;
                        $nom_couleur_et_taille = $nom_couleur;
                        if ((isset($_POST[$key_couleur_et_taille])) && (!empty($_POST[$key_couleur_et_taille]))):
                                $qty_taille=$_REQUEST[$key_couleur_et_taille];
                                $cart_item_data['tailles_couleurs'][$nom_couleur_et_taille] = $qty_taille;
                        endif;
                    }
                endforeach;
            endforeach;
        }else{
            foreach( $select_taille['choices'] as $key_taille => $nom_taille ):
                    if($key_taille != 'qte'){
                        $key_couleur_et_taille = $key_couleur.'_'.$key_taille;
                        $nom_couleur_et_taille = $nom_couleur.' Taille '.$nom_taille;
                        if ((isset($_POST[$key_couleur_et_taille])) && (!empty($_POST[$key_couleur_et_taille]))):
                                $qty_taille=$_REQUEST[$key_couleur_et_taille];
                                $cart_item_data['tailles_couleurs'][$nom_couleur_et_taille] = $qty_taille;
                        endif;
                    }
                endforeach;
        }
    endwhile;
    return $cart_item_data;
}

Thirdly, the function to display my variations on cart :

add_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );
function render_meta_on_cart_and_checkout( $cart_data, $cart_item,$product_id,$key_couleur) {
    $custom_items = array();
    if( !empty( $cart_data ) ) {
        $custom_items = $cart_data;
    }                        
    $qty_input_taille = $cart_item['tailles_couleurs'];
    if( (isset( $cart_item['couleurs_selectionnees'] )) && (empty($qty_input_taille))  ) {
        $couleurselect =$cart_item['couleurs_selectionnees'];
        foreach($couleurselect as $key => $value){
            $custom_items[] = array( "name" => 'Couleur', "value" => $value );
        }  
    }else if( !empty($qty_input_taille)  ) {
        $valeurtaille =$cart_item['tailles_couleurs'];
        foreach($valeurtaille as $key => $value){
            $custom_items[] = array( "name" => $key, "value" => $value );
        }
    }
    return $custom_items;
}

And finally, here is the function to display my variation on chackout and thank you pages (and email order confirmation):

function tshirt_order_meta_handler( $item_id, $values, $cart_item_key ) {
    $qty_input_taille = $values['tailles_couleurs'];
    if( (isset( $values['couleurs_selectionnees'] )) && (empty($qty_input_taille))  ) {
        $couleurselect =$values['couleurs_selectionnees'];
        foreach($couleurselect as $key => $value){
            wc_add_order_item_meta( $item_id, 'Couleur ', $value );
        }  
    }else if( !empty($qty_input_taille)  ) {
        $valeurtaille =$values['tailles_couleurs'];
        foreach($valeurtaille as $key => $value){
            wc_add_order_item_meta( $item_id, $key, $value );
        }
    }
}
add_action( 'woocommerce_add_order_item_meta', 'tshirt_order_meta_handler', 1, 3 );