Update ACF custom fields for new WooCommerce order - wordpress

I'm trying to update 2 ACF custom fields every time an order is created.
We have orders coming from our own website and orders coming from an external marketplace integration. My goal is to differentiate the 2 type of orders using custom fields in the order.
The data for the custom fields is provided by an external marketplace integration. The first field has to be filled with the ordernumber (if it it exists) and the other field is just a simple true/false field.
For website orders we're using "Free shipping". For external orders, the provided shipping details are as follows:
Shipping "Verzending voor bol(xxxxx)"
I'm trying to get the shipping method using the woocomerce_new_order action, and using $order->get_shipping_method()
However, when a new order is created, the custom fields won't update.
This is what I've tried so far:
add_action( 'woocommerce_new_order', 'vliegwerk_bolcom_order_filter', 99, 2);
function vliegwerk_bolcom_order_filter( $order_id, $order ) {
$order = wc_get_order( $order_id );
$verzendmethode = $order->get_shipping_method();
$bol_ordernummer = (int) filter_var($verzendmethode, FILTER_SANITIZE_NUMBER_INT);
if ($bol_ordernummer > 0) {
update_field('field_61fa977c8dff9', $bol_ordernummer, $order_id );
update_field('field_61fa95f594b13', 1, $order_id );
}
}
I already tested the woocommerce_new_order trigger, it works as expected.
I've also tried updating the fields using a foreach loop, and triggering the function with a shortcode. This also works as expected.
However, when combining it all together, the fields won't update. Any help would be appreciated!

Related

Trying to access ACF value in functions.php, in woocommerce_email_order_details action

I have a Wordpress installation with Woocommerce and I added a ACF field to the orders. It's called 'booking_reference'.
Inside my functions.php file, on checkout I update the 'booking_reference' custom field. It gets saved to the database. All is working as it should.
In my next function i'm trying to email this custom field to the customer. I use this code:
$order_id = $order->get_id();
$reference_number_acf_order = get_field('booking_reference', $order_id );
When I echo $reference_number_acf_order, it's empty. The $order_id variable is correct. It contains the order correct order ID.
The rest of the email to the customer is correct, it contains data from the order. Only the ACF value is empty.
Are u using WP_Query() or something like in your new function?
If so. try calling wp_reset_query(); first:
wp_reset_query();
$reference_number_acf_order = get_field('booking_reference', $order_id );

How to get ACF data from WooCommerce customers for order export

On a Wordpress-Shop I use WooCommerce (WC) with Advenced-Custom-Fields (ACF)
and WP-All-Import (WPAI) + WP-All-Export (WPAE).
I added a ACF field CustomerNumber to the WC-Customer (which enhanced the WP-User).
On the WPAI-XML-Import I set the CustomerNumber with a value from a ERP.
So all customers have a unique CustomerNumber.
I now need to export the WC-Orders (to import them in the ERP again).
The Order-XML must include the CustomerNumber from the Customer belongs to the Order.
As I see, the other standard fields from the customer – like name and address – are copied automatically to the order (by WooCommerce itself).
My question is now: How I have to do this for the ACF’s?
Did I have to do this by code on my own? Adding the same AC-fields to the WC-Order and hook into the order checkout and copy the values from the customer to the order?
Or is there some kind of setup which do that and which I did not recognize?
Thx
I did not really found an answer.
My current solution is now as I described it in my question.
I added a new rule for these acf to also make them available on the orders.
Then I added a hook to new created orders, determine the acf from the user and copied the necessary values into the order acf.
function di_woocommerce_new_order( $order_id ) {
$order = new WC_Order( $order_id );
if ( !$order ) return;
$customer_id = $order->get_customer_id();
if ( !$customer_id ) return;
$customer = new WC_Customer($customer_id);
if ( !$customer ) return;
$customer_number = $customer->get_meta('customernumber');
if ( !$customer_number ) return;
// add customer number
$order->add_meta_data('customernumber', $customer_number);
// update order modified timestamp
$order->add_meta_data('order_last_updated', current_time( 'mysql' ));
$order->save_meta_data();
}
add_action( 'woocommerce_checkout_order_processed', 'di_woocommerce_new_order', 10, 1);

How to retrieve the latest categories assigned to a post currently under editing?

I need to limit the post tile length of a post belonging to a specific category while editing. So I need to check what categories have been assigned to the post under editing and decide whether to limit or not its post title.
I use "wp_insert_post_data" to do the job
add_filter( 'wp_insert_post_data' , 'limit_title_length' , '99', 2 );
But what I found is that the categories returned from passed $postarr are existing categories. Not the latest categories. So it would not work for new post or if categories being changed while editing.
$post_category = $postarr['post_category'];
I also checked get_the_category() inside the function, and that also returns existing categories, not the latest categories if category assignment changed.
My codes so far...
function limit_title_length( $data, $postarr ) {
// set up variables like max length, category id to limit
...
// get post id, title and categories from $data and $postarr passed
$title = $data['post_title'];
$id = $postarr['ID'];
$post_category = $postarr['post_category'];
// check if the specified category exists in the categories assigned to this post
...
// process $title, reset $post_title in $data
...
$data['post_title'] = $title;
return $data;
}
add_filter( 'wp_insert_post_data' , 'limit_title_length' , '99', 2 );
wp_insert_post_data fires in the very late stage of post publishing. I expected to get the latest categories from $postarr['post_category'];
but it's not in my case here. Any solutions or alternatives?
So just to be clear - You want to identify the most recent category added to a post?
If this is the case you will be hard pressed to do so as Wordpress does not save meta for added categories. If you are skilled enough you could script such a function and save the data in a custom table. Then retrieve it for use.
If you know the name of the category you are looking for you can use has_category! .

How to get real term_meta using ACF with custom fields on taxonomy terms (instead of wp_options)

Having a simple Woocommerce site, I'm using ACF pro to add some custom fields to the terms of a given taxonomy. Using this, I can, for example, add a "color" field to my "product category" taxonomy terms. Good.
The issue:
Wanting to do some query using get_terms() (codex), I discovered that my meta_query parameters were not working (unexpected results). Why ? My custom fields were not saved (from backend) as term_meta but as wp_option.
It seems that ACF 4 is saving those fields, not as term_meta (as it's designed for), but as wp_option, in the Wordpress options table. So you cannot "query terms by terms_meta" (meta_query) using get_terms() (codex) to get some terms based on some term_meta value.
I could fix this doing the following:
Let's say I have 2 custom fields on my taxonomy terms: color and shape (means I have a color and shape input on my backend terms edit/create page for the given taxonomy).
function acf_update_term_meta( $value, $post_id, $field ) {
$term_id = (int) filter_var( $post_id, FILTER_SANITIZE_NUMBER_INT );
if ( $term_id > 0 ) {
update_term_meta( $term_id, $field['name'], $value );
}
return $value;
}
add_filter( 'acf/update_value/name=color', 'acf_update_term_meta', 10, 3 );
add_filter( 'acf/update_value/name=shape', 'acf_update_term_meta', 10, 3 );
function acf_load_term_meta( $value, $post_id, $field ) {
$term_id = (int) filter_var( $post_id, FILTER_SANITIZE_NUMBER_INT );
if ( $term_id > 0 ) {
$value = get_term_meta( $term_id, $field['name'], true );
}
return $value;
}
add_filter( 'acf/load_value/name=color', 'acf_load_term_meta', 10, 3 );
add_filter( 'acf/load_value/name=shape', 'acf_load_term_meta', 10, 3 );
So we have:
a filter to update the term_meta using update_term_meta() (codex) when updating this ACF fields (hooked 2 times, one for color and one for shape)
a filter to return the term_meta value using get_term_meta() (codex) instead of the wp_option (hooked 2 times, one for color and one for shape)
source
Note 1:
this will trigger for ALL terms (no matter the taxonomy) having the color or shape custom field. You may need to filter by taxonomy if you don't want it to always apply in those fields cases.
Note 2:
ACF5 seems to support out-of-the-box real term_meta, but is still in early access only.
The upgrade process seems to contain a refactor method for this particular case (duplicate data from wp_options to real term_metas):
After updating to ACF 5, you will be prompted to upgrade the Database.
This is a necessary step to migrate across your field and field group
settings from version 4.x. This upgrade will also copy across any
taxonomy term values from the 'wp_options' table to the 'wp_termmeta'
table.
No data is deleted or modified during this upgrade. (source)
Note 3: I believe it would be possible to loop on all ACF terms custom fields to "generate" this code automatically for all custom fields on terms, and prevent having to add 2 filters for each new ACF term field. But as ACF5 should go out soon, it may not be worth the time.

How to check payment method on a WooCommerce order by id?

I want to make some changes if the chosen payment method is COD. On existing WC_Order i have used
($order->payment_method_title == 'Cash On Delivery' ? ... : ... );
to retrieve the title.
But i would like to check against the id (cod) because the title string gets translated to different languages which doesn't make it a good solution.
Is there a way to retrieve the id on a WC_Order in woocommerce?
The post meta key for the payment method ID is simply _payment_method
So if $order->payment_method doesn't have the magic methods in place to get that automatically, you could retrieve the post meta using traditional WordPress
get_post_meta( $order->id, '_payment_method', true );
Update for WooCommerce 3.0
$order->get_payment_method();
If you want the title of the payment method you can do:
$order = new WC_Order( $order_id );
$payment_title = $order->get_payment_method_title();
This returns the string set in the Woocommerce > Payment methods, ex: Paypal.
Here are some very helpful references and documentation that will help you do anything you want with WooCommerce.
WooCommerce Order Class
WooCommerce Reference Docs
Cheers.
If you need the payment gateway object itself you can use the wc_get_payment_gateway_by_order function.
$payment_gateway = wc_get_payment_gateway_by_order( $order );

Resources