phpwoocommercemetadataadminorders

Add non-existing order metadata to extend WooCommerce admin orders search


I have a question following my previous questions: Allow search using billing email in WooCommerce Admin Orders list

Here are my codes to display email and email as md5, phone number and payment gateway name:

add_filter( 'manage_edit-shop_order_columns', 'add_custom_columns_to_admin_orders', 20);
function add_custom_columns_to_admin_orders( $columns ) {
    $new_columns = array();
    foreach ( $columns as $column_name => $column_info ) {
        $new_columns[ $column_name ] = $column_info;

        if ( 'order_total' === $column_name ) {
            $new_columns['order_md5_email'] = __( 'MD5 Email Address', 'my-textdomain' );
            $new_columns['order_email'] = __( 'Email Address', 'my-textdomain' );
            $new_columns['order_customers_phone'] = __( 'Customers Phone', 'my-textdomain' );
            $new_columns['order_payment'] = __( 'Payment Method', 'my-textdomain' );
        }
    }
    return $new_columns;
}


add_action( 'manage_shop_order_posts_custom_column', 'custom_columns_content_in_admin_orders' );
function custom_columns_content_in_admin_orders( $column ) {
    global $post, $the_order;
    if ( 'order_md5_email' === $column ) {
        if ( $the_order->has_status( array('completed') ) ) {
            $email_address = $the_order->get_billing_email();
            $email_address = md5($email_address);
            echo '<span class="order_complete"> '.$email_address.' </span>';
        } else {
            echo '<span class="order_not_complete">This Order is Not Completed!</span>';
        }
    }
    
    if ( 'order_email' === $column ) {
        if ( $the_order->has_status( array('completed') ) ) {
            $email_address = $the_order->get_billing_email();
            echo '<span class="order_complete"> '.$email_address.' </span>';
        } else {
            echo '<span class="order_not_complete">This Order is Not Completed!</span>';
        }
    }
    
    if ( 'order_customers_phone' === $column ) {
        echo '<label for="billing_phone" class="label-billing-email">Customer Phone Number:  </label>';
        echo '<input type="text" name="billing_phone" value="' . $the_order->get_billing_phone() . '" readonly />';
    }
    
    if ( 'order_payment' === $column ) {
        echo $the_order->get_payment_method_title();
    }
}

This code is also for filtering the search on the admin order page:

add_filter( 'woocommerce_shop_order_search_fields', 'extending_admin_orders_search_field', 10, 1 );
function extending_admin_orders_search_field( $meta_keys ){
    $meta_keys[] = '_billing_email';
    $meta_keys[] = '_billing_phone';
    $meta_keys[] = '_payment_method_title';

    return $meta_keys;
}

Now the problem I have is that when I search for values in the admin order page, if I search the MD5 of the email, it will be displayed in the results, just like the simple phone number and email and the name of the payment gateway, which is displayed without any problem.

I think the following 2 methods are applicable:

  1. Using email and generating md5 or my desired changes before creating the search filter (for example, this part $meta_keys[] = '_billing_email'; should be changed to this value ==> $meta_keys[] = md5('_billing_email');).
  2. Saving custom metadata and then calling this custom metadata in the search filter, exactly like the phone number, email address, and the title of the payment gateway that dear Jack gave in the answer to my question.

I would be grateful if you could guide me in both cases and give an example.


Solution

  • First, you need to save as custom metadata the email md5 when the order is created after checkout:

    add_action( 'woocommerce_checkout_create_order', 'save_billing_email_md5', 20, 2 );
    function save_billing_email_md5( $order, $data ) {
        if( $billing_email = $order->get_billing_email() ) {
            $order->add_meta_data('_billing_email_md5', md5($billing_email));
        }
    }
    

    Then also when an order is manually created/updated in admin, add the following:

    add_action( 'woocommerce_process_shop_order_meta', 'admin_save_billing_email_md5' );
    function admin_save_billing_email_md5( $order_id ) {
    
        if( $billing_email = get_post_meta($order_id, '_billing_email', true) ) {
            update_post_meta($order_id, '_billing_email_md5', md5($billing_email));
        }
    }
    

    Then replace function extending_admin_orders_search_field() with:

    add_filter( 'woocommerce_shop_order_search_fields', 'extending_admin_orders_search_field', 10, 1 );
    function extending_admin_orders_search_field( $meta_keys ){
        $meta_keys[] = '_billing_email';
        $meta_keys[] = '_billing_phone';
        $meta_keys[] = '_payment_method_title';
        $meta_keys[] = '_billing_email_md5'; // <=== HERE
    
        return $meta_keys;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.

    This will only work for orders that have the billing email md5 set as custom metadata.