WooCommerce : Add custom Metabox to admin order page WooCommerce : Add custom Metabox to admin order page wordpress wordpress

WooCommerce : Add custom Metabox to admin order page


UPDATE 2017/11/02 (Works perfectly in Woocommerce 3+)

First I have get everything working has expected, except getting the value for my_field_name in back end "Custom fields" Metabox within Order pages.

Then after a real nightmare, I have found a pretty nice working solution, better than before. In back end you have now a Custom metabox with the custom field my_field_name displaying the right value, like in this screenshot:

screenshot


My code is divided In 2 parts.

1) The backend Metabox in Order pages, with an editable field showing the correct value coming from a custom field on the product pages (in front end):

// Adding Meta container admin shop_order pagesadd_action( 'add_meta_boxes', 'mv_add_meta_boxes' );if ( ! function_exists( 'mv_add_meta_boxes' ) ){    function mv_add_meta_boxes()    {        add_meta_box( 'mv_other_fields', __('My Field','woocommerce'), 'mv_add_other_fields_for_packaging', 'shop_order', 'side', 'core' );    }}// Adding Meta field in the meta container admin shop_order pagesif ( ! function_exists( 'mv_add_other_fields_for_packaging' ) ){    function mv_add_other_fields_for_packaging()    {        global $post;        $meta_field_data = get_post_meta( $post->ID, '_my_field_slug', true ) ? get_post_meta( $post->ID, '_my_field_slug', true ) : '';        echo '<input type="hidden" name="mv_other_meta_field_nonce" value="' . wp_create_nonce() . '">        <p style="border-bottom:solid 1px #eee;padding-bottom:13px;">            <input type="text" style="width:250px;";" name="my_field_name" placeholder="' . $meta_field_data . '" value="' . $meta_field_data . '"></p>';    }}// Save the data of the Meta fieldadd_action( 'save_post', 'mv_save_wc_order_other_fields', 10, 1 );if ( ! function_exists( 'mv_save_wc_order_other_fields' ) ){    function mv_save_wc_order_other_fields( $post_id ) {        // We need to verify this with the proper authorization (security stuff).        // Check if our nonce is set.        if ( ! isset( $_POST[ 'mv_other_meta_field_nonce' ] ) ) {            return $post_id;        }        $nonce = $_REQUEST[ 'mv_other_meta_field_nonce' ];        //Verify that the nonce is valid.        if ( ! wp_verify_nonce( $nonce ) ) {            return $post_id;        }        // If this is an autosave, our form has not been submitted, so we don't want to do anything.        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {            return $post_id;        }        // Check the user's permissions.        if ( 'page' == $_POST[ 'post_type' ] ) {            if ( ! current_user_can( 'edit_page', $post_id ) ) {                return $post_id;            }        } else {            if ( ! current_user_can( 'edit_post', $post_id ) ) {                return $post_id;            }        }        // --- Its safe for us to save the data ! --- //        // Sanitize user input  and update the meta field in the database.        update_post_meta( $post_id, '_my_field_slug', $_POST[ 'my_field_name' ] );    }}

2) Front end / Back end:

• The product page custom field (front end).
• Displaying this data on cart, checkout pages and thank you order (front end).
• Displaying data on order page (back end)

// Add the field to the productadd_action('woocommerce_before_add_to_cart_button', 'my_custom_product_field');function my_custom_product_field() {    echo '<div id="my_custom_field">        <label>' . __( 'My Field') . ' </label>        <input type="text" name="my_field_name" value="">    </div><br>';}// Store custom fieldadd_filter( 'woocommerce_add_cart_item_data', 'save_my_custom_product_field', 10, 2 );function save_my_custom_product_field( $cart_item_data, $product_id ) {    if( isset( $_REQUEST['my_field_name'] ) ) {        $cart_item_data[ 'my_field_name' ] = $_REQUEST['my_field_name'];        // below statement make sure every add to cart action as unique line item        $cart_item_data['unique_key'] = md5( microtime().rand() );        WC()->session->set( 'my_order_data', $_REQUEST['my_field_name'] );    }    return $cart_item_data;}// Add a hidden field with the correct value to the checkoutadd_action( 'woocommerce_after_order_notes', 'my_custom_checkout_field' );function my_custom_checkout_field( $checkout ) {    $value = WC()->session->get( 'my_order_data' );    echo '<div id="my_custom_checkout_field">            <input type="hidden" class="input-hidden" name="my_field_name" id="my_field_name" value="' . $value . '">    </div>';}// Save the order meta with hidden field valueadd_action( 'woocommerce_checkout_update_order_meta', 'my_custom_checkout_field_update_order_meta' );function my_custom_checkout_field_update_order_meta( $order_id ) {    if ( ! empty( $_POST['my_field_name'] ) ) {        update_post_meta( $order_id, '_my_field_slug', $_POST['my_field_name'] );    }}// Display field value on the order edit page (not in custom fields metabox)add_action( 'woocommerce_admin_order_data_after_billing_address', 'my_custom_checkout_field_display_admin_order_meta', 10, 1 );function my_custom_checkout_field_display_admin_order_meta($order){    $my_custom_field = get_post_meta( $order->id, '_my_field_slug', true );    if ( ! empty( $my_custom_field ) ) {        echo '<p><strong>'. __("My Field", "woocommerce").':</strong> ' . get_post_meta( $order->id, '_my_field_slug', true ) . '</p>';    }}// Render meta on cart and checkoutadd_filter( 'woocommerce_get_item_data', 'render_meta_on_cart_and_checkout', 10, 2 );function render_meta_on_cart_and_checkout( $cart_data, $cart_item = null ) {    $custom_items = array();    if( !empty( $cart_data ) ) $custom_items = $cart_data;    if( isset( $cart_item['my_field_name'] ) )        $custom_items[] = array( "name" => 'My Field', "value" => $cart_item['my_field_name'] );    return $custom_items;}// Add the information as meta data so that it can be seen as part of the orderadd_action('woocommerce_add_order_item_meta','add_values_to_order_item_meta', 10, 3 );function add_values_to_order_item_meta( $item_id, $cart_item, $cart_item_key ) {    // lets add the meta data to the order (with a label as key slug)    if( ! empty( $cart_item['my_field_name'] ) )        wc_add_order_item_meta($item_id, __('My field label name'), $cart_item['my_field_name'], true);}

Everything is working as expected now.