I am using this code to send product data to stripe as metadata.
function filter_wc_stripe_payment_metadata( $metadata, $order, $source ) {
$count = 1;
foreach( $order->get_items() as $item_id => $line_item ){
$item_data = $line_item->get_data();
$product = $line_item->get_product();
$location = $product->get_attribute('location');
$product_name = $product->get_name();
$item_quantity = $line_item->get_quantity();
$item_total = $line_item->get_total();
$metadata['Item '.$count] = '';
$count += 1;
}
return $metadata;
}
add_filter( 'wc_stripe_payment_metadata', 'filter_wc_stripe_payment_metadata', 10, 3 );
How can I get the selected variation of the product and add it to the metadata?
$attribute = $product->get_attribute('location'); didn't work for me for some reason. So I used this which works well so far.
foreach ( $item->get_formatted_meta_data() as $meta_id => $meta ) {
$value = $args['autop'] ? wp_kses_post( $meta->display_value ) : wp_kses_post( make_clickable( trim( $meta->display_value ) ) );
$strings[] = $value;
}
$attribute = $strings[1];
$attribute = str_ireplace('<p>','',$attribute);
$attribute = str_ireplace('</p>','',$attribute);
$metadata['Location'] = $attribute;
Related
I want to export order data in xml when order is created. and i already applied that but i am getting problem when getting order data tax for each items specially tax rate labels example. "7% Mswt", "19% Mswt".
function get_line_items( $order ) {
$items = [];
/** #var \WC_Order_Item_Product $line_items */
$line_items = $order->get_items( 'line_item' );
// loop through each item in order
foreach ( $line_items as $item_id => $item ) {
// get the product
/** #var \WC_Product $product */
$product = $item->get_product();
// instantiate line item meta
$meta_data = $item->get_formatted_meta_data( '_', true );
$display_meta = [];
foreach ( $meta_data as $meta ) {
$display_meta[] = "{$meta->display_key}: {$meta->display_value}";
}
$item_meta = implode( ', ', $display_meta );
// remove all HTML
$item_meta = wp_strip_all_tags( $item_meta );
// strip HTML in legacy format - note: in modern formats,
// SV_WC_Helper::array_to_xml will automatically escape HTML and newlines by wrapping
// the contents of the tag in CDATA when necessary
if ( 'legacy' === $this->export_format ) {
// remove control characters
$item_meta = str_replace( [ "\r", "\n", "\t" ], '', $item_meta );
}
// remove any html entities
$item_meta = preg_replace( '/\&(?:[a-z,A-Z,0-9]+|#\d+|#x[0-9a-f]+);/', '', $item_meta );
$item_data = [];
$item_data['Id'] = $item_id;
$item_data['Name'] = html_entity_decode( $product ? $product->get_title() : $item['name'], ENT_NOQUOTES, 'UTF-8' );
$item_data['ProductId'] = $product ? $product->get_id() : ''; // handling for permanently deleted product
$item_data['SKU'] = $product ? $product->get_sku() : ''; // handling for permanently deleted product
$item_data['Quantity'] = $item['qty'];
$item_data['Price'] = $this->format_decimal( $order->get_item_total( $item ), 2 );
$item_data['Subtotal'] = $this->format_decimal( $order->get_line_subtotal( $item ), 2 );
//$item_data['SubtotalTax'] = $this->format_decimal( $item['line_subtotal_tax'], 2 );
$item_data['Total'] = $this->format_decimal( $order->get_line_total( $item ), 2 );
$item_data['TaxPercentage'] = $item ->get_tax_class()->labels;
$item_data['TotalTax'] = $this->format_decimal( $order->get_line_tax( $item ), 2 );
//$item_data['Refunded'] = $this->format_decimal( $order->get_total_refunded_for_item( $item ), 2 );
//$item_data['RefundedQuantity'] = $order->get_qty_refunded_for_item( $item_id );
/*if ( 'yes' === get_option( 'woocommerce_calc_taxes' ) && 'yes' === get_option( 'woocommerce_prices_include_tax' ) ) {
$item_data['PriceInclTax'] = $this->format_decimal( $order->get_item_total( $item, true ), 2 );
$item_data['TotalInclTax'] = $this->format_decimal( $order->get_line_total( $item, true ), 2 );
}*/
$item_data['Meta'] = $item_meta;
//$item_data['Taxes'] = $this->get_tax_details( $item );
// Keep order items backwards-compatible with legacy version
if ( 'legacy' === $this->export_format ) {
// rename fields to be compatible with pre 2.0.0
$item_data['ItemName'] = $item_data['Name'];
$item_data['LineTotal'] = $item_data['Total'];
if ( 'yes' === get_option( 'woocommerce_calc_taxes' ) && 'yes' === get_option( 'woocommerce_prices_include_tax' ) ) {
$item_data['LineTotalInclTax'] = $item_data['TotalInclTax'];
}
// remove data that wasn't present pre 2.0.0
unset( $item_data['Id'], $item_data['Name'], $item_data['ProductId'], $item_data['Subtotal'], $item_data['SubtotalTax'], $item_data['Total'], $item_data['TotalTax'], $item_data['Refunded'], $item_data['RefundedQuantity'], $item_data['TotalInclTax'], $item_data['Taxes'] );
}
/**
* Allow actors to modify the line item data / format
*
* In 2.0.0 renamed from `wc_customer_order_xml_export_suite_order_export_line_item_format`
* to `wc_customer_order_xml_export_suite_order_line_item`
*
* #since 5.0.0
*
* #param array $item_data
* #param \WC_Order $order Related order
* #param array $item Order line item
*/
$items['OrderLineItem'][] = apply_filters( 'wc_customer_order_export_xml_order_line_item', $item_data, $order, $item );
}
return ! empty( $items ) ? $items : null; }
Can any body guide me please what i am missing here for get tax label for products for to store in xml...
$item_data['TaxPercentage'] = $item ->get_tax_class()->labels;
$order_items = $order->get_items();
foreach ($order_items as $item_key => $item) {
$product = $item->get_product(); // Get the WC_Product Object
if( $product->is_type( 'variation' ) ){
$attributes = $product->get_attributes();
$variation_names = array();
if( $attributes ){
foreach ( $attributes as $key => $value) {
$variation_key = end(explode('-', $key));
$variation_names[] = ucfirst($variation_key) .' : '. $value;
}
}
echo implode( '<br>', $variation_names );
}
}
The output of this code is as follows:
After echo:
%da%86%d8%b1%d8%a8%db%8c
and Incompatible with Persian language
I need the end result to be something like this:
"product Name , color:red, size:85"
.
.
.
.
.
.
.
.
.
.
Thanks to all the friends;
This is my new solution and it has been tested and it works:
Note:attributes $value label added:
//اضافه کردن نام ویژگی به اسم محصول
//Add attribute label name to product name
if( $product->is_type( 'variation' ) ){
$s ='';
$s1 = '';
foreach ($product->get_attributes() as $taxonomy => $attribute_obj ) {
// Get the attribute label
$attribute_label_name = wc_attribute_label($taxonomy);
//convert to array
$attribute_arr = json_decode(json_encode($attribute_obj),true);
$term_name = get_term_by( 'slug', $attribute_arr, $taxonomy)->name;
$s = $s . $s1 .$attribute_label_name.':'.$term_name;
$s1 = ', ';
}
$name = $name . '(' .$s. ')';
echo '<p>' . $name. '</p>';
}
You can use wc_attribute_label() to get the proper label name of the attribute and you can use get_title() to get the product title. try the below code.
function display_attributes_and_name( $order_id ){
$order = wc_get_order($order_id); //<--check this line
$order_items = $order->get_items();
foreach ($order_items as $item_key => $item) {
$product = $item->get_product(); // Get the WC_Product Object
if( $product->is_type( 'variation' ) ){
$attributes = $product->get_attributes();
$variation_names = array();
if( $attributes ){
foreach ( $attributes as $key => $value) {
$variation_key = end(explode('-', $key));
$variation_names[] = wc_attribute_label( $variation_key ) .' : '. $value;
}
}
echo $product->get_title().', '.implode( ',', $variation_names );
}
}
}
add_action( 'woocommerce_thankyou', 'display_attributes_and_name', 10, 1 );
Tested and works
What #Bhautik said
Plus
"Incompatible with Persian language"
To me, it looks like it's been encoded (by your browser perhaps!), so in order to decode it, we could use urldecode function, like so:
$test = '%da%86%d8%b1%d8%a8%db%8c';
$decode_test = urldecode($test);
echo $decode_test;
Which will output this:
چربی
Does that make sense?
I Hope are you okay.
Today I have problems with I open order invoice pdf in admin after products list have components.
I Remove all components as well
I am using woocommerce-pdf-invoices-packing-slips plugin.
Below is my product URL :
https://www.pcguru.lt/produktas/amd-home-guru/
My Invoice PDF screenshot as well.
How can I remove it?
I Searching Google but couldn't Found Anything.
After Code Debugging Step by Step, That's are Found Successfully.
File Path:
/wp-content/plugins/woocommerce-pdf-invoices-packing-slips/includes/documents/abstract-wcpdf-order-document-methods.php
public function get_order_items() {
$items = $this->order->get_items();
$data_list = array();
if( sizeof( $items ) > 0 ) {
foreach ( $items as $item_id => $item ) {
//Find Child Product Of Composite Product
global $wpdb;
$post_id = $wpdb->get_row("SELECT meta_value FROM pcg_woocommerce_order_itemmeta WHERE (meta_key = 'wooco_ids' AND order_item_id = '". $item_id ."')");
if($post_id->meta_value !=''){
$main_id = str_replace('/1/', '', $post_id->meta_value);
$data_ids = explode(",",$main_id);
}
//END Custom Code
$data = array();
// Set the item_id
$data['item_id'] = $item_id;
// Set the id
$data['product_id'] = $item['product_id'];
$data['variation_id'] = $item['variation_id'];
// Compatibility: WooCommerce Composit Products uses a workaround for
// setting the order before the item name filter, so we run this first
if ( class_exists('WC_Composite_Products') ) {
$order_item_class = apply_filters( 'woocommerce_order_item_class', '', $item, $this->order );
}
// Set item name
$data['name'] = apply_filters( 'woocommerce_order_item_name', $item['name'], $item, false );
// Set item quantity
$data['quantity'] = $item['qty'];
//$data['product_desc'] = $item->get_product(); // Get the WC_Product objec
//echo '<pre>'; print_r($product); echo '</pre>'; die;
// Set the line total (=after discount)
$data['line_total'] = $this->format_price( $item['line_total'] );
$data['single_line_total'] = $this->format_price( $item['line_total'] / max( 1, abs( $item['qty'] ) ) );
$data['line_tax'] = $this->format_price( $item['line_tax'] );
$data['single_line_tax'] = $this->format_price( $item['line_tax'] / max( 1, abs( $item['qty'] ) ) );
$data['tax_rates'] = $this->get_tax_rate( $item, $this->order, false );
$data['calculated_tax_rates'] = $this->get_tax_rate( $item, $this->order, true );
// Set the line subtotal (=before discount)
$data['line_subtotal'] = $this->format_price( $item['line_subtotal'] );
$data['line_subtotal_tax'] = $this->format_price( $item['line_subtotal_tax'] );
$data['ex_price'] = $this->get_formatted_item_price( $item, 'total', 'excl' );
$data['price'] = $this->get_formatted_item_price( $item, 'total' );
$data['order_price'] = $this->order->get_formatted_line_subtotal( $item ); // formatted according to WC settings
// Calculate the single price with the same rules as the formatted line subtotal (!)
// = before discount
$data['ex_single_price'] = $this->get_formatted_item_price( $item, 'single', 'excl' );
$data['single_price'] = $this->get_formatted_item_price( $item, 'single' );
// Pass complete item array
$data['item'] = $item;
// Get the product to add more info
if ( is_callable( array( $item, 'get_product' ) ) ) {
$product = $item->get_product();
} else {
$product = $this->order->get_product_from_item( $item );
}
// Checking fo existance, thanks to MDesigner0
if( !empty( $product ) ) {
// Thumbnail (full img tag)
$data['thumbnail'] = $this->get_thumbnail( $product );
$data['get_parent_id'] = is_callable( array( $product, 'get_parent_id' ) ) ? $product->get_parent_id() : '';
// Set item SKU
$data['sku'] = is_callable( array( $product, 'get_sku' ) ) ? $product->get_sku() : '';
// Set item weight
$data['weight'] = is_callable( array( $product, 'get_weight' ) ) ? $product->get_weight() : '';
// Set item dimensions
$data['dimensions'] = $product instanceof \WC_Product ? WCX_Product::get_dimensions( $product ) : '';
// Pass complete product object
$data['product'] = $product;
} else {
$data['product'] = null;
}
// Set item meta
if (function_exists('wc_display_item_meta')) { // WC3.0+
$data['meta'] = wc_display_item_meta( $item, array(
'echo' => false,
) );
} else {
if ( version_compare( WOOCOMMERCE_VERSION, '2.4', '<' ) ) {
$meta = new \WC_Order_Item_Meta( $item['item_meta'], $product );
} else { // pass complete item for WC2.4+
$meta = new \WC_Order_Item_Meta( $item, $product );
}
$data['meta'] = $meta->display( false, true );
}
if (!in_array($data['product_id'], $data_ids)) {
$data_list[$item_id] = apply_filters( 'wpo_wcpdf_order_item_data', $data, $this->order, $this->get_type());
}
}
}
//echo '<pre>'; print_r($data_list); echo '</pre>'; die;
return apply_filters( 'wpo_wcpdf_order_items_data', $data_list, $this->order, $this->get_type() );
}
Solution Screenshot:
I am very happy because solution are completed.
Also Thanks to all helping guys
I am making custom thank you page for my WooCommerce shop where I am able to display the Cart item's attribute and value correctly but in Thankyou page I failed to show that Can you please help me that ?
Working Code for mini cart item:
$items = WC()->cart->get_cart();
foreach($items as $item => $values) {
$cart_item = WC()->cart->cart_contents[ $item ];
$variations = wc_get_formatted_cart_item_data( $cart_item );
if( $cart_item['data']->is_type( 'variation' ) ){
$attributes = $cart_item['data']->get_attributes();
$variation_names = array();
if( $attributes ){
foreach ( $attributes as $key => $value) {
$variation_key = end(explode('-', $key));
$variation_names[] = ucfirst($variation_key) .' : '. $value;
}
}
echo implode( '<br>', $variation_names );
}
}
And the output like
Color : Red
Size : 4mm
Same thing I like to show in thank you page So I re-coded it like order format and loop through it which is not working
$items = $order->get_items();
foreach ($items as $item_key => $item) {
$product = $item->get_product();
if( $product->is_type( 'variation' )){
$attributes = $product->get_variation_attributes();
$variation_names = array();
if( $attributes ){
foreach ( $attributes as $key => $value) {
$variation_key = end(explode('_', $key));
$variation_names[] = ucfirst($variation_key) .' : '. $value;
}
}
echo implode( '<br>', $variation_names );
}
}
Use $item->get_product() to get the current WC_Product Object from order items using get_attributes() method on product variations, instead of get_variation_attributes() which is to be used only on the parent variable products.
$order_items = $order->get_items();
foreach ($order_items as $item_key => $item) {
$product = $item->get_product(); // Get the WC_Product Object
if( $product->is_type( 'variation' ) ){
$attributes = $product->get_attributes();
$variation_names = array();
if( $attributes ){
foreach ( $attributes as $key => $value) {
$variation_key = end(explode('-', $key));
$variation_names[] = ucfirst($variation_key) .' : '. $value;
}
}
echo implode( '<br>', $variation_names );
}
}
It should work now.
I'm trying to create an order programmatically. Using wc_create_order() this is pretty straightforward:
$myProduct = new WC_Product(100);
$order = wc_create_order();
$order->add_product($myProduct, 1);
$order->calculate_totals();
This works as expected, and an order is created for a simple product with ID 100 for the correct amount.
However, if I try to do this with a variation, it doesn't seem to behave correctly. After much trial and error, I got it to sort-of work this way:
$membershipProduct = new WC_Product_Variable(100);
$theMemberships = $membershipProduct->get_available_variations();
$trueProduct = new WC_Product(100);
$variationsArray = array();
foreach ($theMemberships as $membership) {
if ($membership['sku'] == $chosenVariation) {
$variationID = $membership['variation_id'];
$variationsArray = $membership['attributes'];
}
}
if ($variationID) {
$trueProduct->variation_id = $variationID;
}
$order = wc_create_order();
$order->add_product($trueProduct, 1, $variationsArray);
$order->calculate_totals();
However, although it does create the order with the correct product and the correct variation ID, the total for the order is always 0 (which, coincidentally, is the price of the first variation).
Originally I was trying $order->add_product() with the object created from new WC_Product_Variable(), but that resulted in no products being added to the order at all, which leads me to believe it's an issue with creating orders programmatically with variable products. However, following the WooCommerce source code for these calls, I can't see what I'm doing wrong.
Is there something I'm missing, or a better way to create an order with a variable product?
Solved it.
Even though I could have sworn I'd tried (and failed) doing it this way, the answer was to not add the parent product ($trueProduct in the example), but to add the variation product by its ID.
This may have failed previously because, as #helgatheviking noted, my $variationsArray was formatted incorrectly according to the source; I needed an array with a ['variation'] key to send the correct variation array of attributes.
In total, my working code now looks like this:
$membershipProduct = new WC_Product_Variable(100);
$theMemberships = $membershipProduct->get_available_variations();
$variationsArray = array();
foreach ($theMemberships as $membership) {
if ($membership['sku'] == $chosenVariation) {
$variationID = $membership['variation_id'];
$variationsArray['variation'] = $membership['attributes'];
}
}
if ($variationID) {
$varProduct = new WC_Product_Variation($variationID);
$order = wc_create_order();
$order->add_product($varProduct, 1, $variationsArray);
$order->calculate_totals();
}
if you already have the variation_id you can just do this
$product_variation = new WC_Product_Variation($variation_id);
$order = wc_create_order();
$args=array();
foreach($product_variation->get_variation_attributes() as $attribute=>$attribute_value){
$args['variation'][$attribute]=$attribute_value;
}
$order->add_product($product_variation, $product['quantity'], $args);
Here is the solution that worked for me:
function add_item_to_order( $order_id, $prod_id ) {
$order = wc_get_order( $order_id );
$_product = wc_get_product( $prod_id );
// Set values
$item = array();
$item['product_id'] = $_product->id;
$item['variation_id'] = isset( $_product->variation_id ) ? $_product->variation_id : '';
$item['variation_data'] = $item['variation_id'] ? $_product->get_variation_attributes() : '';
$item['name'] = $_product->get_title();
$item['tax_class'] = $_product->get_tax_class();
$item['qty'] = 1;
$item['line_subtotal'] = wc_format_decimal( $_product->get_price_excluding_tax() );
$item['line_subtotal_tax'] = '';
$item['line_total'] = wc_format_decimal( $_product->get_price_excluding_tax() );
$item['line_tax'] = '';
$item['type'] = 'line_item';
// Add line item
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $item['name'],
'order_item_type' => 'line_item'
) );
// Add line item meta
if ( $item_id ) {
wc_add_order_item_meta( $item_id, '_qty', $item['qty'] );
wc_add_order_item_meta( $item_id, '_tax_class', $item['tax_class'] );
wc_add_order_item_meta( $item_id, '_product_id', $item['product_id'] );
wc_add_order_item_meta( $item_id, '_variation_id', $item['variation_id'] );
wc_add_order_item_meta( $item_id, '_line_subtotal', $item['line_subtotal'] );
wc_add_order_item_meta( $item_id, '_line_subtotal_tax', $item['line_subtotal_tax'] );
wc_add_order_item_meta( $item_id, '_line_total', $item['line_total'] );
wc_add_order_item_meta( $item_id, '_line_tax', $item['line_tax'] );
wc_add_order_item_meta( $item_id, '_line_tax_data', array(
'total' => array(),
'subtotal' => array() )
);
// Store variation data in meta
if ( $item['variation_data'] && is_array( $item['variation_data'] ) ) {
foreach ( $item['variation_data'] as $key => $value ) {
wc_add_order_item_meta( $item_id, str_replace( 'attribute_', '', $key ), $value );
}
}
}
$item['item_meta'] = $order->get_item_meta( $item_id );
$item['item_meta_array'] = $order->get_item_meta_array( $item_id );
$item = $order->expand_item_meta( $item );
$order->calculate_totals();
}