2
votes

In WooCommerce, I'm working on a plugin that pulls names and addresses from a Custom Post Type (CTP). I would like to loads them in a custom checkout dropdown field, I've got everything working up.

But what I need to do is have the information from the CTP to load into an 'options' array as below:

I've got most of the code working, the only issue I am having now is getting it to load all of my posts in this CPT(there are four). Right now it only loads the "Please select something..." and a single post(the most recent one). My code is as follows:

*Revised Code *

add_filter( 'woocommerce_checkout_fields' , 'add_addressbook_checkout_field', 20, 1 );
function add_addressbook_checkout_field( $fields ) {

    $options = array();

    // First option
    $options[0] = 'Please select something…';

// Get 'addressbook' posts
    // $posts = array();
    $args = array('post_type'=>'addressbook', 'posts_per_page'=>3000,'order'=>'asc');
    $query = New WP_Query($args);
    if($query->have_posts()):while($query->have_posts()):$query->the_post();

        $temp = array();
        $temp['id'] = get_the_id();
        $temp['fname'] = get_field('fname');
        $temp['lname'] = get_field('lname');
        $temp['company'] = get_field('company');
        $posts = $temp;

    endwhile;endif;wp_reset_postdata();

// Loop through 'addressbook' posts (to set all other select options)
foreach( $posts as $post ){
    // Set each complete name as an option (Where key is the post ID)
    // $options[$posts['id']] = $posts['fname','id'] . ' ' . $posts['lname','id'] . ' ' . $posts['company','id'];
            $options[$post->ID] = $posts['fname'] . ' ' . $posts['lname'] . ', ' . $posts['company'];
}
    //, $post->ID

$fields['shipping']['addressbook'] = array(
    'type'          => 'select',
    'label'         => __('Address Book', 'woocommerce'),
    'placeholder'   => _x('Pick an address', 'placeholder', 'woocommerce'),
    'options'       =>  $options, // Here we set the options
    'required'      => false,
    'priority'      => 1,
    'class'         => array('form-row-wide'),
    'clear'         => true
);

return $fields;
}

UPDATE


I have the address list populating the select option, now I just need it to populate the rest of the form with the info using AJAX with the query results. Code Below: // Ad 'addressbook' custom checkout select field

add_filter( 'woocommerce_checkout_fields' , add_addressbook_checkout_field', 20, 1 );

function add_addressbook_checkout_field( $fields ) {

    $options = array();

    // First option
    $options[0] = 'Please select something…';

// Get 'addressbook' posts
    $posts = array();
    $args = array('post_type'=>'addressbook', 'posts_per_page'=>-1,'order'=>'asc');
    $query = New WP_Query($args);
    if($query->have_posts()):while($query->have_posts()):$query->the_post();

        $temp = array();
        $temp['id'] = get_the_id();
        $temp['fname'] = get_field('fname');
        $temp['lname'] = get_field('lname');
        $temp['company'] = get_field('company');
        $temp['addr1'] = get_field('address_line_1');
        $temp['addr2'] = get_field('address_line_2');
        $temp['city'] = get_field('city');
        $temp['state'] = get_field('state');
        $temp['zip'] = get_field('zip');
        $posts = $temp;

        $id             =   $posts['id'];
        $fname      = $posts['fname'];
        $lname      = $posts['lname'];
        $company    = $posts['company'];
        $addr1      = $posts['addr1'];
        $addr2      = $posts['addr2'];
        $city       = $posts['city'];
        $state      = $posts['state'];
        $zip            = $posts['zip'];
        // Loop through 'addressbook' posts (to set all other select options)
    foreach( $posts as $post ){
        // Set each complete name as an option (Where key is the post ID)
        $options[$id] = $company  . ', '. $fname  . ' '. $lname . ', ' . $addr1 . '....';
    }

    endwhile;endif;wp_reset_postdata();
    $fields['shipping']['addressbook'] = array(
    'type'          => 'select',
    'label'         => __('Address Book', 'woocommerce'),
    'placeholder'   => _x('Pick an address', 'placeholder', 'woocommerce'),
    'options'       =>  $options, // Here we set the options
    'required'      => false,
    'priority'      => 1,
    'class'         => array('form-row-wide'),
    'clear'         => true
);

return $fields;

}
// process custom checkout field
add_action('woocommerce_checkout_process', 'check_addressbook_checkout_field', 20 );

function check_addressbook_checkout_field( $order, $data ) {

    if ( isset($_POST['addressbook']) && empty($_POST['addressbook']) )

            wc_add_notice( __("Please pick an address from the Address Book"),

    'error' );

}

// Add custom meta data (or existing change data) to the order before saving 
//it

add_action('woocommerce_checkout_create_order',
'set_meta_data_in_checkout_create_order', 20, 2 );
function set_meta_data_in_checkout_create_order( $order, $data ) {

  if ( isset($_POST['addressbook']) ){
    // Set the meta data in the order

        if( ! empty($fname) )
        $order->update_meta_data( 'ab_fname', esc_attr( $fname ) );

        if( ! empty($lname) )
        $order->update_meta_data( 'ab_lname', esc_attr( $lname ) );

        if( ! empty($company) )
        $order->update_meta_data( 'ab_company', esc_attr( $company ) );

        if( ! empty($addr1) )
        $order->update_meta_data( 'ab_addr1', esc_attr( $addr1 ) );

        if( ! empty($addr2) )
        $order->update_meta_data( 'ab_addr2', esc_attr( $addr2 ) );

        if( ! empty($city) )
        $order->update_meta_data( 'ab_city', esc_attr( $city ) );

        if( ! empty($state) )
        $order->update_meta_data( 'ab_state', esc_attr( $state ) );

        if( ! empty($zip) )
        $order->update_meta_data( 'ab_zip', esc_attr( $zip ) );

  }

}
?>

<script>

</script>
1

1 Answers

0
votes

First, Instead of using ACF function the_field() as this function echo the value, you should use ACF function get_field() instead to set a value in a variable or in some php code.

Also is not possible to load in an <option> all the data as you are doing… You need to choose some and wrap it as a string… So I have choosed the complete name as displayed value related to the post ID option key. Then with that option key (the post ID from your CTP), is easy to retrieve the related data…

Then here is the way to make it:

  1. The first function will add your custom checkout field
  2. The second function will check that the custom field is not empty
  3. The third function will get the related data and add it as custom meta data to the order

The code:

// Ad 'addressbook' custom checkout select field
add_filter( 'woocommerce_checkout_fields' , 'add_address_book_checkout_field', 20, 1 );
function add_address_book_checkout_field( $fields ) {
    if ( ! is_ssl() ) return $fields; // if needed (?)

    // Get 'addressbook' posts
    $addressbook_posts = get_post(array('post_type'=>'addressbook', 'posts_per_page' => -1 ));
    // First option
    $options = array( '' => 'Please select something…');

    // Loop through 'addressbook' posts (to set all other select options)
    foreach( $addressbook_posts as $post ){
        // Set each complete name as an option (Where key is the post ID)
        $options[$post->ID] = get_field( 'fname', $post->ID ) . ' ' . get_field( 'lname', $post->ID );
    }

    $fields['shipping']['address_book'] = array(
        'type'          => 'select',
        'label'         => __('Address Book', 'woocommerce'),
        'placeholder'   => _x('Pick an address', 'placeholder', 'woocommerce'),
        'options'       =>  $options, // Here we set the options
        'required'      => false,
        'priority'      => 1,
        'class'         => array('form-row-wide'),
        'clear'         => true
    );

    return $fields;
}

// process custom checkout field
add_action('woocommerce_checkout_process', 'check_address_book_checkout_field', 20 );
function check_address_book_checkout_field( $order, $data ) {
    if ( isset($_POST['address_book']) && empty($_POST['address_book']) )
        wc_add_notice( __("Please pick an address from the Address Book"), 'error' );
}

// Add custom meta data (or existing change data) to the order before saving it
add_action('woocommerce_checkout_create_order', 'set_meta_data_in_checkout_create_order', 20, 2 );
function set_meta_data_in_checkout_create_order( $order, $data ) {
    if ( isset($_POST['address_book']) ){
        // The selected "Adress book" Post ID
        $post_id = $_POST['address_book'];

        // Get the data for the selected "Adress book" Post ID
        $fname      = get_field( 'fname', $post_id );
        $lname      = get_field( 'lname', $post_id );
        $company    = get_field( 'company', $post_id );
        $addr1      = get_field( 'address_line_1', $post_id );
        $addr2      = get_field( 'address_line_2', $post_id );
        $city       = get_field( 'city', $post_id );
        $state      = get_field( 'state', $post_id );
        $zip        = get_field( 'zip', $post_id );

        // Set the meta data in the order
        if( ! empty($fname) )
            $order->update_meta_data( 'ab_fname', esc_attr( $fname ) );
        if( ! empty($lname) )
            $order->update_meta_data( 'ab_lname', esc_attr( $lname ) );
        if( ! empty($company) )
            $order->update_meta_data( 'ab_company', esc_attr( $company ) );
        if( ! empty($addr1) )
            $order->update_meta_data( 'ab_addr1', esc_attr( $addr1 ) );
        if( ! empty($addr2) )
            $order->update_meta_data( 'ab_addr2', esc_attr( $addr2 ) );
        if( ! empty($city) )
            $order->update_meta_data( 'ab_city', esc_attr( $city ) );
        if( ! empty($state) )
            $order->update_meta_data( 'ab_state', esc_attr( $state ) );
        if( ! empty($zip) )
            $order->update_meta_data( 'ab_zip', esc_attr( $zip ) );
    }
}

Code goes in function.php file of your active child theme (or active theme). It should work.