Im trying to clean up some default database entries that WooCommerce adds to the postmeta table. The two primary entries that I do not need are _customers_ip_address & _customer_user_agent.
I found _customers_ip_address in create_order() function in file class-wc-checkout.php
do_action( 'woocommerce_checkout_create_order', $order, $data ); seems to be what is setting the data. Although I also found it was being set in wc-core-functions.php # function wc_create_order()
Im not 100% sure how to edit this. Im thinking a simple do_filter, but unset seems to not work inside the do_filter, but obviously I am doing it all wrong. Im not that familiar with do_filter but seems like something simple like the code below.
function cleanup_woocommerce_checkout_create_order($order, $data) {
unset($order->set_customer_ip_address());
return $order;
}
add_filter('woocommerce_checkout_create_order', 'cleanup_woocommerce_checkout_create_order');
The code above gives a WordPress Error of :
Fatal error: Can't use method return value in write context
First woocommerce_checkout_create_order is an action hook (but not a filter hook). Also you can not unset any method applied to an object as you are doing.
What you can do is to try setting an empty value, like:
add_action('woocommerce_checkout_create_order', 'cleanup_specific_order_metadata', 10, 2 );
function cleanup_specific_order_metadata( $order, $data ) {
$order->set_customer_ip_address('');
$order->set_customer_user_agent('');
}
It should work.
If it doesn't work, you can try to use woocommerce_checkout_update_order_meta action hook to remove this meta data afterwards once order data has been saved to database, this way:
add_action('woocommerce_checkout_update_order_meta', 'cleanup_specific_order_metadata', 10, 2 );
function cleanup_specific_order_metadata( $order_id, $data ) {
delete_post_meta( $order_id, '_customer_ip_address' );
delete_post_meta( $order_id, '_customer_user_agent' );
}
This last one should work anyways.
As I can see in this article, https://docs.woocommerce.com/wc-apidocs/source-class-WC_Checkout.html#397
do_action( 'woocommerce_checkout_create_order', $order, $data );
so you should use add_action function
add_action('woocommerce_checkout_create_order', 'cleanup_woocommerce_checkout_create_order', 10, 2 );
function cleanup_woocommerce_checkout_create_order( $order, $data ) {
$order->set_customer_ip_address(0);
}
Or updating the post meta
update_post_meta($order_id, '_customer_ip_address', 0);
or
delete_post_meta($order_id, '_customer_ip_address');
Related
I am having trouble with checking order status of woocommerce order.
I have a plugin that I am creating and I need to know, when the order become "pending" and then "completed". But all hooks are working only if I set the order status manually in wordpress admin.
function order_status_changed_clbk( $order_id ){
...some code...
}
add_action( 'woocommerce_order_status_pending', 'order_status_changed_clbk' );
UPDATE
I've found out that there is a little problem. If the user cancels the payment for example at PayPal, he maybe get's redirected to the checkout again. Now let's expect that he repeats the checkout again. In this case the hook get's called a second time which could be problematic. So I've implemented myself a payment_counter:
add_action( 'woocommerce_checkout_order_processed', 'order_status_changed_clbk' );
function order_status_changed_clbk( $order_id ) {
$payment_counter = (int) get_post_meta( $order_id, 'payment_counter', true );
if ( empty( $payment_counter ) ) {
update_post_meta( $order_id, 'payment_counter', 1 );
error_log( 'Function works!' ); //Get's called only once
} else {
update_post_meta( $order_id, 'payment_counter', ++ $payment_counter ); //Cool thing for statistics maybe, but not really needed
}
}
Maybe this hook works for you:
function order_status_changed_clbk( $order_id ){
error_log( 'Function works!' );
}
add_action( 'woocommerce_checkout_order_processed', 'order_status_changed_clbk' );
I'm using it within my plugin. If the order is processed, it's also "pending" so maybe this is the solution your'e looking for.
Try it out and check your debug.log for Function works!.
I want to write a custom plugin that does some action after woocommerce order is completed, but I can't get this hook to work. I can see this question asked many times.
Like here: https://wordpress.stackexchange.com/questions/134463/woocommerce-order-status-completed-action-hook-not-working
Here: https://wordpress.org/support/topic/woocommerce_order_status_completed-is-not-working
And here: https://wordpress.org/support/topic/woocommerce_order_status_completed-action-hook-not-working
But I cannot help myself with answers that these guys received.
I tried to add the action a few different ways:
add_action( 'woocommerce_order_status_completed', 'ikwoocommerceorderstatuscompleted_func');
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
add_action( 'woocommerce_order_status_completed', array(&$this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
Also tried with a class:
class IKHooks {
function __construct() {
add_action( 'woocommerce_order_status_completed', array($this,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
}
public function ikwoocommerceorderstatuscompleted_func( $order_id ) {
}
}
I even tried to put the action outside of the class:
add_action( 'woocommerce_order_status_completed', array(IKHooks,'ikwoocommerceorderstatuscompleted_func'), 10, 1);
None of these examples work. :(
Check the following steps before calling your hook.
Check if order completion email is sent.
Hook is properly registered in plugin file or theme functions.php
add_action( 'woocommerce_order_status_completed','callback_function_name' );
function callback_function_name(){
global $wp_filter;
print_r($wp_filter);
exit;
}
Check if the name of your callback function is in the hook array:
[woocommerce_order_status_completed] => Array
(
[10] => Array
(
[wc_paying_customer] => Array
(
[function] => wc_paying_customer
[accepted_args] => 1
)
[wc_downloadable_product_permissions] => Array
(
[function] => wc_downloadable_product_permissions
[accepted_args] => 1
)
[callback_function_name] => Array
(
[function] => callback_function_name
[accepted_args] => 3
)
)
)
If you find it then everything is ok, it means that probably there's an issue with your theme or functions.php file. Check for the hook or callback function in your files and then look for remove_action or remove_all_actions that's probably what's preventing your hook from being called.
You can also check in this way
add_action( 'woocommerce_order_status_completed', 'callback_function_name', 1);
Change the priority of your hook from 10 to 1 so it is called first than any other action or hook.
You can use this hook
add_action( 'woocommerce_order_status_changed', 'your_function', 99, 4 );
And the function will look like
function your_function( $order_id, $old_status, $new_status, $order ){
if( $new_status == "completed" ) {
//your code here
}
}
Hope this will be helpful.
I faced the similar issue earlier and solved it as:
Following code update the order status as completed
add_action( 'woocommerce_thankyou', 'your_wc_autocomplete_order' );
function your_wc_autocomplete_order( $order_id ) {
if ( ! $order_id ) {
return;
}
$order = wc_get_order( $order_id );
$order->update_status( 'completed' );
}
Once order is completed, if you want to do something, see the following code:
add_action('woocommerce_order_status_completed','payment_complete');
function payment_complete($order_id)
{
//global $items;
//$order = new WC_Order($order_id);
// do something ...
}
Hopefully, it will work :)
woocommerce_order_status_changed and woocommerce_order_status_completed actually work for me. After struggling for 2 days i realized that you just can't var_dump or var_export or print_r or whatever in the admin panel, it just won't work.
So if you are a newbie like me and thought those actions weren't working, just try triggering another action like sending a mail for example.
This code works:
function your_function( $order_id ){
$order = new WC_Order( $order_id );
$to_email = 'testing_mail#sample.com';
$payment = $order->get_payment_method_title();
$headers = 'From: Your Name <Your_site_mail#address.com>' . "\r\n";
wp_mail($to_email, 'subject', $payment, $headers );
}
add_action( 'woocommerce_order_status_completed', 'your_function');
Try using action hook woocommerce_order_status_changed.
It takes 4 parameters. order id, old status new status and order. Further code reference HERE
This may not be exactly suitable to your requirement, but seems to be worth of an alternative. Hope this helps.
I think you might be after this guy. woocommerce_payment_complete
function mysite_woocommerce_payment_complete( $order_id ) {
error_log( "Payment has been received for order $order_id", 0 );
}
add_action( 'woocommerce_payment_complete', 'mysite_woocommerce_payment_complete' );
Need to add custom meta to order items. Googled it and most articles says to use "woocommerce_add_order_item_meta" hook. This hook is deprecated in the newest version 2.3.7. Someone, please tell me which hook to use instead.
http://docs.woothemes.com/wc-apidocs/function-woocommerce_add_order_item_meta.html
2017/2018 THE RIGHT WAY (Using new CRUD setters and Getters methods)
Related: Replace woocommerce_add_order_item_meta hook in Woocommerce 3.4
Since woocommerce 3 that has improved many things making drastic changes, the action hook woocommerce_add_order_item_meta still work perfectly even in woocommerce version 3.3+.
This hook is enabled by WC_Checkout class methods and related functions in the checkout process and not in WC_Order Class where cart data is not anymore available.
Now as Woocommmerce 3 has introduced new CRUD setters and getters methods, the similar replacement hook to be used is woocommerce_checkout_create_order_line_item that has similar useful arguments as cart data.
The woocommerce_new_order_item is really NOT convenient as cart data is not accessible.
Let see how to work with woocommerce_checkout_create_order_line_item. It has 4 available arguments:
$item is an instance of WC_Order_Item_Product new introduced Class
$cart_item_key is the cart item unique hash key
$values is the cart item
$order an instance of the WC_Order object (This is a very useful additional argument in some specific cases)
In this hook we will replace the old working functions wc_add_order_item_meta() by the new WC_Data update_meta_data() method to be used with $item argument.
Example:
## --- New way --- ##
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_checkout_create_order_line_item', 20, 4 );
function custom_checkout_create_order_line_item( $item, $cart_item_key, $values, $order ) {
// Get a product custom field value
$custom_field_value = get_post_meta( $item->get_product_id(), '_meta_key', true );
// Update order item meta
if ( ! empty( $custom_field_value ) ){
$item->update_meta_data( 'meta_key1', $custom_field_value );
}
// … … Or … …
// Get cart item custom data and update order item meta
if( isset( $values['custom_data'] ) ) {
$item->update_meta_data( 'meta_key2', $values['custom_data'] );
}
}
Finally we can do the same with old way using woocommerce_add_order_item_meta hook as it has nearly the same useful arguments:
## --- Old way --- ##
add_action( 'woocommerce_add_order_item_meta', 'custom_add_order_item_meta', 20, 3 );
function custom_add_order_item_meta( $item_id, $values, $cart_item_key ) {
// Get a product custom field value
$custom_field_value = get_post_meta( $values['data']->get_id(), '_meta_key', true );
// Update order item meta
if ( ! empty( $custom_field_value ) ){
wc_add_order_item_meta( $item_id, 'meta_key1', $custom_field_value );
}
// … … Or … …
// Get cart item custom data and update order item meta
if( isset( $values['custom_data'] ) ) {
wc_add_order_item_meta( $item_id, 'meta_key2', $values['custom_data'] );
}
}
Conclusion: woocommerce_checkout_create_order_line_item is the right replacement hook to be used with WooCommerce 3+ and that new CRUD setters and getters methods.
If you look at wc-deprecated-functions.php you will see
/**
* #deprecated
*/
function woocommerce_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique );
}
Basically, the function was renamed to wc_add_order_item_meta(), so if you need the function then use that. The action hook was not renamed and remains in class-wc-checkout.php as:
// Allow plugins to add order item meta
do_action( 'woocommerce_add_order_item_meta', $item_id, $values, $cart_item_key );
It seems that the hook is now also deprecated as of version 3.0.4.
I'm getting this notification:
The The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.0.4. Replace with woocommerce_new_order_item.
I have replaced the action name 'woocommerce_add_order_item_meta' with 'woocommerce_new_order_item' in an add_action statement in an offending plugin, and the deprecation notification disappears, The problem is that some parameters now appear inside a legacy_values array. I use the plugin YITH WooCommerce Product Add Ons, and the product meta data that should be attached to an order is not picked up by the plugin and therefore not stored with the order. So until this is fixed in the plugin you have to live with the deprecation notification.
I know this has been answered and there is an accepted reply already. I just wanted to give another way to handle this without actually getting a deprecated message (see reference);
add_action('woocommerce_new_order_item', 'saveMetaData', 10, 3); // or use just 2 instead of 3; if you don't need order id
/**
* Add meta to order item
*
* #param int $itemId
* #param WC_Order_Item_Product|WC_Order_Item_Shipping $item
* #param int #orderId
*/
function saveMetaData($itemId, $item, $orderId)
{
if (!isItemValid($item))
{
return;
}
wc_add_order_item_meta($itemId, 'my_custom_data', $item->legacy_values['my_custom_data']);
}
/**
* #param WC_Order_Item_Product|WC_Order_Item_Shipping $item
*
* #return bool
*/
function isItemValid($item)
{
return (
$item instanceof WC_Order_Item_Product &&
isset($item->legacy_values) &&
isset($item->legacy_values['my_custom_data']) &&
!empty($item->legacy_values['my_custom_data'])
);
}
Your specific use case isn't very clear (you didn't specify when or where you need to add this meta info), but you can use woocommerce_checkout_update_order_meta during checkout.
Read more in customizing checkout fields.
No it seems like the hook is also deprecated:
PHP Error:
The "woocommerce_add_order_item_meta" hook uses out of date data structures and function is deprecated since version 3.1.2. Replace with woocommerce_new_order_item.
I also cannot find it here:
https://docs.woocommerce.com/wc-apidocs/hook-docs.html
I wanted to add on to Ilgıt Yıldırım's answer: in my case, my custom values did not exist in the item->legacy_values array. To fix this, I used the woocommerce_checkout_create_order_line_item hook to add the custom values to the item prior to calling the woocommerce_new_order_item hook. Here is an example of that:
add_action( 'woocommerce_checkout_create_order_line_item', 'save_values_in_item', PHP_INT_MAX, 4 );
function save_values_in_item( $item, $cart_item_key, $values, $order ) {
$item->myCustomValues = $values;
}
//THEN call the new hook:
add_action( 'woocommerce_new_order_item', 'add_product_input_fields_to_order_item_meta_wc3', PHP_INT_MAX, 3 );
function add_product_input_fields_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
if ( isset( $item->myCustomValues ) )
{
//iterate through array and place desired values into the meta data using the wc_add_order_item_meta function
}
}
Just to make things clear, this function was deprecated, but the hook is still ok
During the add_to_cart function, there is a filter to add "cart item data". The filter is woocommerce_add_cart_item_data. I expected to store my custom plugin data in this, so that the data is stored relative to the item and multiple products can be added with different data.
This all seemed to work, but I am not able to retrieve the data. I can't figure it out. The data is there, I can see it in a serialized string, but I can't pull it out.
echo '<pre>';
var_dump( WC() );
foreach( WC()->cart->get_cart() as $cart_item ) {
var_dump( $cart_item );
var_dump( WC()->cart->get_item_data( $cart_item ) );
}
echo '</pre>';
The first dump of WC() has a property: session->_data->cart->(serialized data). The _data property is protected, though, but I can see my custom field inside the serialized data.
The $cart_item is an array with product_id and some other data, but it does not include my custom data :(
Finally, using the get_item_data() method I thought I had it all figured out. I passed in the cart item object, and... an empty string. Same if I pass the key, rather than the cart item itself.
How am I supposed to access the cart item data?
Here is the "Add cart item data" function, which works (or at least seems to work):
function save_class_menu_selection( $cart_item_data, $product_id, $variation_id ) {
if ( !product_is_class( $product_id ) ) return $cart_item_data;
// Save the date, or give a fatal warning. Date is required.
if ( !empty($_REQUEST['class-date']) ) {
$cart_item_data['class-date'] = stripslashes($_REQUEST['class-date']);
return $cart_item_data;
}else{
wp_die('<h2>Invalid Class Date Selected</h2><p>You tried to add a class to your cart, but the date selected was invalid. Please try again.</p>');
exit;
}
}
add_filter( 'woocommerce_add_cart_item_data', 'save_class_menu_selection', 10, 3 );
I was in the same situation today and stumbled over this question after some research.
After some reverse engineering I found the problem and want to provide a solution for other which may also stumble over this question.
The problem is that the data gets sanitized when the cart items get restored from the session. So the extra cart item data IS stored into the session but on the next request it does not get restored.
There is a filter "woocommerce_get_cart_item_from_session". As first parameter you get the sanitized cart item (without extra data) and as second all data which got stored into the session (including extra data).
The solution is to hook in there and also restore your custom cart item data.
Example Code:
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$cartItemData['myCustomData'] = 'someCustomValue';
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
To also show the data at the cart/checkout page you can use the following code:
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'My custom data',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
The final thing now is to save the data when the order is made:
add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
if ( isset( $values['myCustomData'] ) ) {
wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
}
}, 10, 3 );
You dont have to do anything else the show the data inside the backend, all order item meta data gets display automatically.
I could not get the default cart item data to work, unfortunately. I feel it may not be properly implemented, or may even be deprecated, as there is a lack of support and documentation.
Instead, I used a cart session variable to accomplish the same thing. It's simply an array where each key is the cart_item_key. The value of each array is yet another array, containing a key-value pair of custom fields. So it's essentially the same thing as the built-in cart item data, except stored as cart session data instead.
Here is a Gist containing some utility functions to make it easy:
https://gist.github.com/RadGH/e3444fc661554a0f8c6f
Or if you want to build it yourself, the magic is in WC()->session. Here are the two key functions for this to work:
WC()->session->get('_my_cart_item_data');
WC()->session->set('_my_cart_item_data', $cart_item_data_array);
These are the action hooks you will need:
<<<EXAMPLES
action: woocommerce_add_to_cart
desc: When an item is added to the cart.
args: $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data
action: woocommerce_add_order_item_meta
desc: When a cart item is converted to an order item, save metadata to the order item
using the function "wc_add_order_item_meta( $item_id, $key, $value )"
args: item_id, $values, $cart_item_key
I have created a plugin mainly following this guide, which simply adds a small bit of data to a given product.
I know Woocommerce have made some changes outlined here.
The problem I'm having is that when I add my item to the cart, and access the cart page, I am getting a blank screen. I believe the problem stems from the use of this filter:
add_filter('woocommerce_get_cart_item_from_session'...
If I comment the line with this filter, my checkout page works (but without the extra details added to my product). I can't work out why this filter is not working, or what problem it is having??
The woocommerce changes said:
WooCommerce 2.0 no longer uses the PHP session_start function, instead it makes use of WordPress’ transients, which is great, unless your code happens to rely on $_SESSION.
I'm not starting any new sessions as far as I can see (my code is 90% the same as the first link). Maybe this is a problem with my server? Any ideas?
i was browsing a lot and i recommend that you read the following:
The solution is to hook in there and also restore your custom cart item data.
Example Code:
add_filter( 'woocommerce_add_cart_item_data', function ( $cartItemData, $productId, $variationId ) {
$cartItemData['myCustomData'] = 'someCustomValue';
return $cartItemData;
}, 10, 3 );
add_filter( 'woocommerce_get_cart_item_from_session', function ( $cartItemData, $cartItemSessionData, $cartItemKey ) {
if ( isset( $cartItemSessionData['myCustomData'] ) ) {
$cartItemData['myCustomData'] = $cartItemSessionData['myCustomData'];
}
return $cartItemData;
}, 10, 3 );
To also show the data at the cart/checkout page you can use the following code:
add_filter( 'woocommerce_get_item_data', function ( $data, $cartItem ) {
if ( isset( $cartItem['myCustomData'] ) ) {
$data[] = array(
'name' => 'My custom data',
'value' => $cartItem['myCustomData']
);
}
return $data;
}, 10, 2 );
The final thing now is to save the data when the order is made:
add_action( 'woocommerce_add_order_item_meta', function ( $itemId, $values, $key ) {
if ( isset( $values['myCustomData'] ) ) {
wc_add_order_item_meta( $itemId, 'myCustomData', $values['myCustomData'] );
}
}, 10, 3 );
You dont have to do anything else the show the data inside the backend, all order item meta data gets display automatically.
this is from
How to retrieve cart_item_data with WooCommerce?
you have to add this stuff to the functions.php file of your theme for example.