PPP
PPP

Reputation: 85

Custom checkout fields validation in Woocommerce 3

I've created custom input fields on the checkout page for a bookings website. The amount of input fields is based on the person count. I've managed to get them displayed on the checkout form, getting them sanitized and being displayed in de order admin panel. The input fields are required, so an error (wc_add_notice) should appear if one of more of the fields are empty. How can I achieve to get te wc_add_notice? Here is my code:

//* Add a new checkout field 
function ppp_filter_checkout_fields($fields){
    $fields['extra_fields'] = array(
    'participant_details' => array(
        'type' => 'participant_details',
        'required'      => true,
        'label' => __( 'Participant Details' )
        ),
    );

    return $fields;

}
add_filter( 'woocommerce_checkout_fields', 'ppp_filter_checkout_fields' );

//* Add the field to the checkout
function ppp_filter_checkout_field_group( $field, $key, $args, $value ){
    $op_cart_count = WC()->cart->get_cart_contents_count();

    $items = WC()->cart->get_cart();

    foreach($items as $item) { 
        $person = $item['booking']['_persons'][0];
    }

    if ($person > 1) {

        $html = '';

        $html .= "<h3>Deelnemers</h3>";

        for ( $i = 1; $i < $person; $i++) {
            $counter = $i + 1;

            $html .= "Deelnemer ". $counter . "<br>";

            $html .= woocommerce_form_field( "participant_details[$i][full_name]", array(
                "type" => "text",
                "return" => true,
                "value" => "",
                "required"      => true,
                "label" => __( "Naam" )
                )
            );
            $html .= woocommerce_form_field( "participant_details[$i][email_address]", array(
                "type" => "text",
                "return" => true,
                "value" => "",
                "required"      => true,
                "label" => __( "Emailadres" )
                )
            );

        }
        return $html;

    }
}
add_filter( 'woocommerce_form_field_participant_details', 'ppp_filter_checkout_field_group', 10, 4 );

//* display the extra field on the checkout form
function ppp_extra_checkout_fields(){ 

    $checkout = WC()->checkout();

    foreach ( $checkout->checkout_fields['extra_fields'] as $key => $field ) :

        woocommerce_form_field( $key, $field, $checkout->get_value( $key ) );

    endforeach;


}
add_action( 'woocommerce_checkout_after_customer_details' ,'ppp_extra_checkout_fields' );

//* Sanitize our custom field
function ppp_custom_process_checkout_field_participant_details( $posted ){

    $clean = array();

    foreach( $posted as $participant ){
        $details = ppp_custom_checkout_clean_participant_details( $participant );

        if( ! empty( $details ) ){
            $clean[] = $details;
        }
    }

    return $clean;
}
add_filter( 'woocommerce_process_checkout_participant_details_field', 'ppp_custom_process_checkout_field_participant_details' );

//*
function ppp_custom_checkout_clean_participant_details( $participant = array() ){
    $details = array();
    if( isset( $participant["full_name"] ) ){
        $details['full_name'] = sanitize_text_field( $participant["full_name"] );
    }
    if( isset( $participant["email_address"] ) ){
        $details['email_address'] = sanitize_text_field( $participant["email_address"] );
    }
    return $details;
}

//* Update_post_meta
function ppp_custom_checkout_field_update_order_meta( $order_id, $posted ){

    if( ! empty( $posted["participant_details"] ) ){
        update_post_meta( $order_id, "_participant_details", $posted["participant_details"] );
    } else {
        delete_post_meta( $order_id, "_participant_details" );
    }

}
add_action( 'woocommerce_checkout_update_order_meta', 'ppp_custom_checkout_field_update_order_meta', 10, 2 );

//* Display the extra data in the order admin panel
function ppp_display_order_data_in_admin( $order ){  

    $participant_details = get_post_meta( $order->id, "_participant_details", true ); 

    if( ! empty( $participant_details ) ) { 

        $participant_defaults = array(
                "full_name" => "",
                "email_address" => ""
            );

    ?>
    <div class="participant_data">
        <h4><?php _e( "Deelnemers Lijst", "prespersadprodukties" ); ?></h4>
        <?php 
            $i = 1;

            foreach( $participant_details as $participant ){

                $participant = wp_parse_args( $participant, $participant_defaults );

                echo "<p><strong>" . sprintf( __( "Deelnemer %s", "prespersadprodukties" ), $i+1  ) . "</strong>" . "<br/>";
                echo __( "Naam", "prespersadprodukties" ) . ' : ' . $participant["full_name"] . "<br/>";
                echo __( "Emailadres", "prespersadprodukties" ) . ' : ' . $participant["email_address"] . "<br/>";
                echo "</p>";

                $i++;

            }

         ?>
    </div>
<?php }
}
add_action( 'woocommerce_admin_order_data_after_order_details', 'ppp_display_order_data_in_admin' );

Upvotes: 1

Views: 3326

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 253849

Updated

Note: Your code only works if you have one unique item in cart… If you have 2 different bookings items, it will handle only the last added one.

Now to make the validation work, we need first to add a hidden input field with the number of persons in it. So I have changed a bit your first hooked function:

// Add a new checkout field
add_filter( 'woocommerce_checkout_fields', 'ppp_filter_checkout_fields' );
function ppp_filter_checkout_fields($fields){

    $fields['extra_fields'] = array(
    'participant_details' => array(
        'type' => 'participant_details',
        'required'      => false,
        'label' => __( 'Participant Details' )
        ),
    );

    // Add a "persons" hidden input field
    foreach( WC()->cart->get_cart() as $cart_item ) {
        $persons = $cart_item['booking']['_persons'][0];
    }
    echo '<input type="hidden" name="persons" value="' . $persons . '">';

    return $fields;
}

Then in the code below we can get get easily the number of persons and make the validation of your custom checkout fields:

//* Validate custom checkout fields
add_action( 'woocommerce_after_checkout_validation', 'ppp_checkout_field_participant_details_validation', 20, 2 );
function ppp_checkout_field_participant_details_validation( $data, $errors ){
    if ( isset( $_POST['persons'] ) && $_POST['persons'] > 1 ){

        for ( $i = 1, $j = 2; $i < esc_attr( $_POST['persons'] ); $i++, $j++ ) {
            if ( empty( $_POST['participant_details'][$i]['full_name'] ) )
                $errors->add( 'participant_'.$i.'_full_name',  __( "Please fill in the participant $j full name" ), 'error' );

            if ( empty( $_POST['participant_details'][$i]['email_address'] ) )
                $errors->add( 'participant_'.$i.'_email_address',  __( "Please fill in the participant $j email address" ), 'error' );
        }
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

enter image description here

Upvotes: 1

Related Questions