WooCommerce CSV Exporter - How to access line items? - php

I use the Customer/Order CSV Export plugin from WooThemes to export orders from my shop. However I want to add additional data to the CSV output per line item (do some calculations etc.) and I found below information on the official WooThemes page.
However I want to access the line item data, how can I achieve this? For example: How can I get the 'item_total' which is not stored in the postmeta database (the postmeta database is listed in the example below) ?
Is the line_item data included in the $order_data? How can I access it?
function wc_csv_export_modify_row_data( $order_data, $order, $csv_generator ) {
$custom_data = array(
'column_1' => get_post_meta( $order->id, 'some_meta_key', true ),
'column_2' => get_post_meta( $order->id, 'some_other_meta_key', true ),
// add other row data here in the format column_key => data
);
$new_order_data = array();
if ( isset( $csv_generator->order_format ) && ( 'default_one_row_per_item' == $csv_generator->order_format || 'legacy_one_row_per_item' == $csv_generator->order_format ) ) {
foreach ( $order_data as $data ) {
$new_order_data[] = array_merge( (array) $data, $custom_data );
}
} else {
$new_order_data = array_merge( $order_data, $custom_data );
}
return $new_order_data;
}
add_filter( 'wc_customer_order_csv_export_order_row', 'wc_csv_export_modify_row_data', 10, 3 );

you can create an object of WC_Order class by passing order id to it. Using get_items() you will get all items array which are present in that order. After getting an array you may use get_item_meta() for getting each items meta values pass order_item_id to it.

Related

Remove particular variation from dropdown in WooCommerce frontend

I am using WooCommerce and WooCommerce Subscriptions and its working as per my expectations.
Now I am creating a variable subscription product having multiple attributes like this.
Now I want to remove/hide particular item from dropdown hence I am trying to use below code / hook which I believe might help me to achieve.
add_filter('woocommerce_dropdown_variation_attribute_options_args', 'hide_variations_for_mindesk_users');
function hide_variations_for_mindesk_users( $args ){
print_r($args);
return $args;
}
Now my question is, how can I remove or hide particular variation product from dropdown? Do I need to remove from variation id or from somewhere?
For example:
Here I want to remove/hide 2nd variation from dropdown which has variation id #4171 having "Monthly- Professional". This should work with single attribute as well.
Can anyone point me in the right direction to achieve this?
In add-to-cart/variable.php template file, we find foreach ( $attributes as $attribute_name => $options ). However, the intention is to hide 1 attribute, so let's see where these are passed to the template file.
In includes/wc-template-functions.php, we can see that the template file is called and an array is passed with some options. One of these options is available_variations' => $get_variations ? $product->get_available_variations()
The get_available_variations() function is then found in includes/class-wc-product-variable.php which in turn $variation_ids = $this->get_children(); contains.
The get_children() function can then be found in includes/class-wc-product-variable.php, which contains apply_filters( 'woocommerce_get_children', $this->children, $this, false );
And that filter hook can be used to remove one or more childIDs (variantions)
So you get:
function filter_woocommerce_get_children( $children, $product, $false ) {
// NOT backend
if ( is_admin() ) return $children;
// Variation ID
$variation_id = 4171;
// Delete by value: Searches the array for a given value and returns the first corresponding key if successful
if ( ( $key = array_search( $variation_id, $children ) ) !== false ) {
unset( $children[$key] );
}
return $children;
}
add_filter( 'woocommerce_get_children', 'filter_woocommerce_get_children', 10, 3 );
If you want to apply it for multiple variantion IDs, use:
function filter_woocommerce_get_children( $children, $product, $false ) {
// NOT backend
if ( is_admin() ) return $children;
// Variation IDs, multiple IDs can be entered, separated by a comma
$variation_ids = array( 4171, 36, 38 );
// Loop through variation IDs
foreach ( $variation_ids as $variation_id ) {
// Delete by value: Searches the array for a given value and returns the first corresponding key if successful
if ( ( $key = array_search( $variation_id, $children ) ) !== false ) {
unset( $children[$key] );
}
}
return $children;
}
add_filter( 'woocommerce_get_children', 'filter_woocommerce_get_children', 10, 3 );
Used in this answer: PHP array delete by value (not key)

Add unique line item meta as order meta data in WooCommerce

I have meta data that is stored below the order line items, many times the data is that same. I am trying to save the unique meta values as order meta data, separated by commas and I if possible to add a text "these are your numbers" before this data.
So far I tried the code below but nothing is happening.
add_action( 'woocommerce_update_order', 'add_unique_order_nummers_to_order', 10, 2 );
function add_unique_order_nummers_to_order( $order_id, $order ) {
$allenummers = array();
$items = $order->get_items();
foreach ( $order->get_items() as $item_id => $item ) {
$allenummers[] = $item->get_meta( '_org_ordernummer', true );
}
$ordernummers_array = array_unique($allenummers);
$ordernummers_unique = implode(',', $ordernummers_array);
update_post_meta( $order_id, '_Unieke_nummers', $ordernummers_unique );
}
I hope someone can help.
Update: Use the following simplified code with a different hook, based on your comment, when order status is changed to "we-fact" custom order status:
add_action('woocommerce_order_status_we-fact', 'add_unique_order_nummers_to_order', 20, 2 );
function add_unique_order_nummers_to_order( $order_id, $order ) {
$allenummers = array(); // Initializing
// Loop through order
foreach ( $order->get_items() as $item ) {
$allenummers[] = $item->get_meta( '_org_ordernummer' );
}
if ( ! empty($allenummers) ) {
$order->update_meta_data('_Unieke_nummers', sprintf( __("These are your numbers: %s"), implode(', ', array_unique($allenummers) ) ) );
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.

Custom meta data added to Woocommerce not displayed in order item meta

I've a single piece of custom metadata to a WooCommerce order and now I want to display this on the thank you page after checkout, however, the data isn't available. The data is saved and available in the admin, I just can't seem to access it.
function custom_order_item_meta( $item_id, $values ) {
if ( ! empty( $values['custom_option'] ) ) {
woocommerce_add_order_item_meta( $item_id, 'custom_option', $values['custom_option'] );
}
}
add_action( 'woocommerce_add_order_item_meta', 'custom_order_item_meta', 10, 2 );
But when I dump out the wc_get_order my meta data isn't there.
I'm using;
woocommerce_add_order_item_meta()
to save the data but dumping out var_dump(wc_get_order( $order->id )); also doesn't show my custom meta field
is there another hook I should be using to access this data?
The data that you are looking for is not order meta data, but order item meta data and is located in wp_woocommerce_order_itemmeta database table (see below how to access this data).
Since woocommerce 3, a much better hook replace old woocommerce_add_order_item_meta hook.
Displayed and readable order item meta data:
To make custom order item meta data displayed everywhere, the meta key should be a readable label name and without starting by an underscore, as this data will be displayed under each order item.
The code:
add_action( 'woocommerce_checkout_create_order_line_item', 'custom_order_item_meta', 20, 4 );
function custom_order_item_meta( $item, $cart_item_key, $values, $order ) {
if ( isset( $values['custom_option'] ) ) {
$item->update_meta_data( __('Custom option', 'woocommerce'), $values['custom_option'] );
}
}
In "Order received" (thankyou) page, you will get something like:
This will be displayed too in backend and email notifications.
To access this order item data you need to get items from the order object in a foreach loop:
foreach( $order->get_items() as $item_id => $item ){
$custom_data = $item->get_meta( 'Custom option' );
}
To Get the first order item (avoiding a foreach loop), you will use:
$items = $order->get_items(); // Order items
$item = reset($items); // The first Order item
$custom_data = $item->get_meta( 'Custom option' ); // Your custom meta data
Related: Replace woocommerce_add_order_item_meta hook in Woocommerce 3.4

Get custom values of variations from order items in WooCommerce

I am trying to get the variation values selected by customer at checkout from an order (by id or otherwise) to map to variables $storage and $tier which are used to build an API url.
I have tried a variety of methods to get the data onto the variables but the API url is failing, which leads me to believe I do not have the indented values on my variables.
My current code is as follows (extract):
add_action( 'woocommerce_order_status_processing', 'my_function' );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $key => $item ) {
$storage = get_post_meta( $key, 'attribute_addon-storage' );
$tier = get_post_meta( $key, 'attribute_subscription-type' );
Does anyone have any idea how I would grab the values of those two variables, addon-storage and subscription-type?
I can see the values I want to get in my database in the woocommerce_order_itemmeta table.
Can I get the values from there?
Edit:
So as per LoicTheAztec's advice, the right way to get the value of the data I see in the woocommerce_order_itemmeta table as $meta_key is:
add_action( 'woocommerce_order_status_processing', 'my_function', 10, 1 );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $key => $item ) {
$storage = wc_get_order_item_meta( $key, 'addon-storage', true );
$tier = wc_get_order_item_meta( $key, 'subscription-type', true );
$anyMetaValue = wc_get_order_item_meta( $key, '$meta_key', true );
// Then I can create the variable I need in the the API url with:
$package = "$tier$storage";
Updated: Your are confusing order post meta data and order item meta data, which are very different things and located in different database tables.
Also your code is incomplete and you will not get anything using get_post_meta() with the $key (which is the item ID)...
The get_post_meta( $order_id, 'meta_key', true ) function will look for Order post meta data (not related to order items) and use Order ID as argument.
The wc_get_order_item_meta( $item_id, 'meta_key', true ) function will look for Order item meta data realated and will use the Item ID as argument (the $key in your code)…
So this function should need to be used in the foreach loop, where you get the order items data, instead.
Then 2 ways:
You should check in your database for the last order ID you have (via phpMyAdmin) in wp_postmeta and wp_woocommerce_order_itemmeta tables, to see where is located the data…
Or you can use the following code (just for testing) that will output the order items raw data where your data is located.
This raw data will be output in the shop, archive and product pages, only visible for logged in admins. You will need to define an order ID in it.
Here is this testing function
add_action( 'woocommerce_before_main_content', 'my_testing_order_function' );
function my_testing_order_function() {
// Define an Order ID
$order_id = 724;
// Only for admin user role
if( ! current_user_can('edit_products')) return;
$order = wc_get_order( $order_id ); // The order object
foreach ( $order->get_items() as $item_id => $item ) {
// Order item meta data Raw output
echo "<pre>ORDER ITEM META DATA - (Item_id $item_id):"; print_r($item->get_data()); echo'</pre>';
echo "<pre>ORDER ITEM META META DATA - (Item_id $item_id):"; print_r($item->get_meta_data()); echo'</pre>';
}
}
Now you have everything needed to locate and get the data. The code below should normally work for you, allowing you to get the data from your variations:
add_action( 'woocommerce_order_status_processing', 'my_function', 10, 1 );
function my_function( $order_id ) {
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $key => $item ) {
// get the data
$storage = wc_get_order_item_meta( $item_id, 'attribute_addon-storage', true );
$tier = wc_get_order_item_meta( $item_id, 'attribute_subscription-type', true );
}
}

Woocommerce Order Again won't copy custom fields

I've managed to code my plugin to add extra custom fields to woocommerce products. This works all the way through from cart to completing an order. Going to my account and viewing past orders, the custom fields are displayed correctly.
However, when I choose to click "order again" on a past order, the new cart doesn't contain the custom fields and their values.
Here is what I currently have to attempt this:
// order again
add_filter( 'woocommerce_order_again_cart_item_data', 'woocommerce_order_again_cart_item_data', 10, 3 );
function woocommerce_order_again_cart_item_data($cart_item_meta, $product, $order){
global $woocommerce;
// Disable validation
remove_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_add_cart_item' ), 10, 3 );
if ( ! array_key_exists( 'item_meta', $cart_item_meta ) || ! is_array( $cart_item_meta['item_meta'] ) )
$cart_item_meta['item_meta'] = array();
foreach ( array( 'jhpc_toppings', 'jhpc_sauce', 'jhpc_toppings_half', 'jhpc_sauce_half', 'jhpc_garnish' ) as $key )
$cart_item_meta['item_meta'][$key] = $product['item_meta'][$key];
return $cart_item_meta;
}
replace
$cart_item_meta['item_meta'][$key] = $product['item_meta'][$key];
by
$cart_item_meta[$key] = $product[$key];
Otherwise, why are you removing the validation ?
Here is the code to add all custom field data for order again. Use the given code in your theme's function.php file and replace the custom field keys of $customfields array with your keys.
<?php
add_filter( 'woocommerce_order_again_cart_item_data', 'wpso2523951_order_again_cart_item_data', 10, 3 );
function wpso2523951_order_again_cart_item_data($cart_item_meta, $product, $order){
//Create an array of all the missing custom field keys that needs to be added in cart item.
$customfields = [
'customfield_key1',
'customfield_key2',
'customfield_key3',
'customfield_key4',
];
global $woocommerce;
remove_all_filters( 'woocommerce_add_to_cart_validation' );
if ( ! array_key_exists( 'item_meta', $cart_item_meta ) || ! is_array( $cart_item_meta['item_meta'] ) )
foreach ( $customfields as $key ){
if(!empty($product[$key])){
$cart_item_meta[$key] = $product[$key];
}
}
return $cart_item_meta;
}
?>
Replace the values of array $customfields with the keys of custom fields that are missing or are not being added automatically.

Categories