Save woocommerce ITEM meta data - woocommerce

I the cart i dynamically create some meta data for each item from a function located in functions.php.
IN CHECKOUT, I would like to save each meta data for each item of the current order.
In this way, once order completed, i would need to display these data in woo commerce admin and woocommerce email.
Basically, i need to save $date_start,$duration,$end_date
when the order is completed and receive this data in woocomerce admin and emails.
function get_infos_order ($date_start,$duration){
$end_date = strtotime('+ '.$duration, $date_start);
}
Could someone please give some advices how to do that please ?
Thanks a lot.

Muhammad Muazzam solution is OK, but woocommerce_add_order_item_meta is deprecated, you have to use wc_add_order_item_meta
function add_order_item_meta($item_id, $values) {
$key = ''; // Define your key here
$value = filter_input(INPUT_POST, 'key_name'); // Safer retrieval
wc_add_order_item_meta( $item_id, $meta_key, $meta_value);
}
add_action('woocommerce_add_order_item_meta', 'add_order_item_meta', 10, 2);
Source: https://docs.woocommerce.com/wc-apidocs/source-function-woocommerce_add_order_item_meta.html#428-433

Save them using this function:
function add_order_item_meta($item_id, $values) {
$key = ''; // Define your key here
$value = $_POST['key_name']; // Get your value here
woocommerce_add_order_item_meta($item_id, $key, $value);
}
add_action('woocommerce_add_order_item_meta', 'add_order_item_meta', 10, 2);

Related

Remove specific meta_data from product on woocommerce checkout

so - I have a couple of meta_data which I don't want to get transmitted. Actually with this snippet I am able to do this on woocommerce order view. As I have connected an ERP this won't work there.
add_filter( "woocommerce_order_item_get_formatted_meta_data","unset_specific_order_item_meta_data", 10, 2);
function unset_specific_order_item_meta_data($formatted_meta, $item){
foreach( $formatted_meta as $key => $meta ){
if( in_array( $meta->key, array("length", "surface", "amount") ) )
unset($formatted_meta[$key]);
}
return $formatted_meta;
}
Is there a way to achieve this with woocommerce_checkout_update_order_meta? So that the specific meta_data (like length, surface, amount) isn't in the order in the first place?
The woocommerce_checkout_update_order_meta hook is meant to save custom meta data, unsetting meta data doesn't work here. However you can use delete_meta_data like this:
add_action("woocommerce_checkout_update_order_meta", "custom_woocommerce_checkout_update_order_meta", 10, 2);
function custom_woocommerce_checkout_update_order_meta($order_id, $data) {
$order = wc_get_order($order_id);
if ($order) {
$meta_data_keys = array("length", "surface", "amount");
foreach ($meta_data_keys as $meta_data_key) {
$order->delete_meta_data($meta_data_key);
}
}
}

Woocommerce add to cart with custom price

I've seen many examples of adding an item to the WC cart with a customer price, but none dynamically. I am trying to do in a shortcode function that receives a POST variables....
if (isset($_POST['wmnf_add_donation'])) {
global $woocommerce;
$cart_object = $woocommerce->cart;
$custom_price = ($_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0);
$target_product_id = 65986;
$cart_object->add_to_cart($target_product_id, "1");
foreach ( $cart_object->cart_contents as $key => $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->price = $custom_price;
}
}
}
This adds the item to the cart of course, but the price is zero and I realize I need to somehow save this array back to the WC cart data. Is this method even possible or can it only be done via a filter or action hook? If so, how can I save the changed array back to the cart contents or make it work to add the one item with its posted price? Any guidance greatly appreciated.
Thanks for that answer doublesharp, I was not able to get it to work as described because the form was posting to the page with my shortcode, which has my form, instead of posting directly to the cart. The $_POST was not being seen and the product ended up zero. I did find another approach, but having a problem using wp_redirect. I changed the above shortcode to this:
if (isset($_POST['wmnf_add_donation'])) {
global $woocommerce;
$custom_price = ($_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0);
$target_product_id = 65986;
$_SESSION['donation_amount'] = $custom_price;
$woocommerce->cart->add_to_cart($target_product_id, "1");
wp_redirect( site_url() . '/gifts/swag-bag/');
}
Then I added the following filters to functions.php:
add_filter('woocommerce_get_price','donation_price', 10, 2);
add_filter('woocommerce_get_regular_price','donation_price', 10, 2);
add_filter('woocommerce_get_sale_price','donation_price', 10, 2);
function donation_price($price, $productd){
if($productd->id == '65986'){
$price = $_SESSION['donation_amount'];
}
return $price;
}
This does not work except when wp_redirect is commented out, hence, not redirecting. The above redirects to the cart, but its empty. If I comment out the wp_redirect line and then manually go to the cart, the product is there with my custom price. Actually, I would like to apply a custom price and redirect directly to the checkout page instead of the cart, if possible?
You can use the woocommerce_before_calculate_totals action hook to modify the contents of the cart, including the product prices.
add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals' );
function before_calculate_totals( $_cart ){
// loop through the cart_contents
foreach ( $_cart->cart_contents as $cart_item_key => &$item ) {
// you will need to determine the product id you want to modify, only when the "donation_amount" is passed
if ( $item['id'] == 65986 && isset( $_POST['donation_amount'] ) ){
// custom price from POST
$custom_price = $_POST['donation_amount'] > 0 ? $_POST['donation_amount'] : 0;
// save to the cart data
$item['data']->price = $custom_price;
// new versions of WooCommerce may require (instead of line above)...
// $item['data']->set_price($custom_price);
}
}
}

Adding extra info to order

I am programmatically adding a product to the cart. Besides this, somehow, I want to store some extra info (an array) to the order. When the client finishes the order, I want to access that info through some WordPress actions. I'll have to do this immediately after adding the product to the cart, because the info may change after that, if the user doesn't finish the order right away. Is there any way I can do it, without putting the database to work?
You should probably use the WooCommerce Cart Item Meta API and the WooCommerce Order Item Meta API.
You use them like this:
// Add to cart item
// This is triggered on add to cart
add_filter('woocommerce_add_cart_item_data', 'my_add_cart_item_data', 10, 2);
function my_add_cart_item_data( $cart_item_meta, $product_id ) {
//Here we can easily filter what values should be added to what products using the $product_id
$cart_item_meta['my_meta_key'] = 'meta value';
return $cart_item_meta;
}
// Add to order item when the cart is converted to an order
// This is triggered when the order is created
add_action('woocommerce_add_order_item_meta', 'my_order_item_meta'), 10, 2);
function my_order_item_meta( $item_id, $values, $cart_item_key ) {
// The value stored in cart above is accessable in $values here
woocommerce_add_order_item_meta( $item_id, 'meta_key', $values['my_meta_key'] );
//Or add what ever you want
$meta_value = 'value';
woocommerce_add_order_item_meta( $item_id, 'meta_key', $meta_value );
}
I hope that helps.

Woocommerce remove admin order item item meta

Im adding a custom item meta to every item with woocommerce_add_order_item_meta action.
I dont need to show this custom meta in the Order Detail, because it's an arry stringy that im using to print a pdf.
How can i remove this meta custom item? Is there some action to do it?
Thanks
I understand its a bit old question but I am answering for some other users who will have same issue in future.
If you want your order item meta to not display in admin order details page than you should append underscore (_) at the start of your meta name.
Example:
_custom_order_meta
The underscore trick no longer works. In Woo 3.x there is a hidden meta array:
add_filter('woocommerce_hidden_order_itemmeta',
array($this, 'hidden_order_itemmeta'), 50);
function hidden_order_itemmeta($args) {
$args[] = 'my_hidden_meta';
return $args;
}
It sounds like you need to keep it in order to print the PDF. If you override the order-details.php template you can possibly change:
$item_meta = new WC_Order_Item_Meta( $item['item_meta'], $_product );
to
$array = $item['item_meta'];
if( isset( $array['your_pdf_array_key'] ) ){ unset( $array['your_pdf_array_key'] ); }
$item_meta = new WC_Order_Item_Meta( $array, $_product );
EDIT
The wc_add_order_item_meta() function has 4 parameters as seen in the code:
function wc_add_order_item_meta( $item_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'order_item', $item_id, $meta_key, $meta_value, $unique );
}
If you choose a $meta_key with a preceding underscore, the meta will be automatically hidden from view on the checkout/order-received page, the My Order's list of the My account area, as well as in the admin's order overview page.
Therefore, I would suggest making your woocommerce_add_order_item_meta callback function look something like the following:
add_action( 'woocommerce_add_order_item_meta', '25979024_add_order_item_meta', 10, 3 );
function 25979024_add_order_item_meta( $order_item_id, $cart_item, $cart_item_key ) {
wc_add_order_item_meta( $order_item_id, '_pdf_something', 'hide this stuff' );
}

FeedWordPress - Save string as Custom Field

I am using the FeedWordPress plugin http://wordpress.org/extend/plugins/feedwordpress/ to pull posts from one site to another.
I have written a filter that after some help from Stack users successfully scans the $content and extracts the image URL into $new_content
define('FWPASTOPC_AUTHOR_NAME', 'radgeek');
add_filter(
/*hook=*/ 'syndicated_item_content',
/*function=*/ 'fwp_add_source_to_content',
/*order=*/ 10,
/*arguments=*/ 2
);
function fwp_add_source_to_content ($content, $post) {
// Use SyndicatedPost::author() to get author
// data in a convenient array
$content = $post->content();
// Authored by someone else
if( preg_match( '/<img[^>]+src\s*=\s*["\']?([^"\' ]+)[^>]*>/', $content, $matches ) ) {
$new_content .= 'URL IS '.$matches[0].'';
return $new_content;
}
else
{
}
}
What I wanted to do now was save this URL into a custom field instead of just returning it. Has anyone achieved anything similar?
So as I understand it, the plugin grabs content from external RSS feeds and creates them as posts in your website.
If this is the case, using your filter you should be able to grab the post ID within the $post variable.
So all you need is the add_post_meta() function to add a custom field to the specific post.
So including your code above it should look something like:
define('FWPASTOPC_AUTHOR_NAME', 'radgeek');
add_filter(
/*hook=*/ 'syndicated_item_content',
/*function=*/ 'fwp_add_source_to_content',
/*order=*/ 10,
/*arguments=*/ 2
);
function fwp_add_source_to_content ($content, $post) {
// Use SyndicatedPost::author() to get author
// data in a convenient array
$content = $post->content();
// Authored by someone else
if( preg_match( '/<img[^>]+src\s*=\s*["\']?([^"\' ]+)[^>]*>/', $content, $matches ) ) {
$new_content .= 'URL IS '.$matches[0].'';
//Add custom field with author info to post
add_post_meta($post->ID, 'post_author', $new_content);
return $new_content;
}
}

Resources