I'm trying to send price, name and id of each item in the order, plus an extra static value to a single js variable formatted in this way,
items = eventID::price::name|eventID::price::name|eventID::price::name
I was trying to do it this way, but I'm getting an error on the last line which I mean to add a pipe if there is more than one product.
$line_items = $order->get_items();
//loop over line items
$wgItemCount = $order->get_item_count();
$wgItems = array();
foreach ( $line_items as $item ) {
$wgItem = array();
$wgItem ['eventId'] = '777777';
$wgItem ['eventId'] .= '::';
$wgItem ['price'] = $order->get_line_total( $item, true, true );
$wgItem ['price'] .= '::';
$wgItem ['name'] = $item->get_name();
if ($wgItemCount > 1) { //add divider if more than one item
wgItem .= '|';
}
$wgItems[] = $wgItem;
}
That hasn't worked so far, so I thought maybe I should create a custom object that contains the variables instead:
wgProduct = "77777", $order->get_line_total( $item, true, true ), $item->get_name();
and then call the items in a list later like
echo print ("|", wgProduct)
I had also tried using JSON to encode the data but the third party told me that is not going to work for their needs.
Edit: Code is now doing everything I need it to, but it's only pulling one item from the list instead of a string of all of them.
Here's what it looks like now based on the help I got here:
add_action( 'woocommerce_thankyou','wg_tracking' );
function wg_tracking( $order_id ) {
$order = wc_get_order( $order_id );
$shipping_total = $order->get_shipping_total();
$order_total = $order->get_total();
$currency = $order->get_currency();
$coupons = $order->get_coupon_codes();
$items = $order->get_items();
$total_exc_shipping = $order_total - $shipping_total;
$order_discount = $order->discount_total;
foreach( $coupons as $coupon ){
$coupon_post_object = get_page_by_title($coupon, OBJECT, 'shop_coupon');
$coupon_id = $coupon_post_object->ID;
$coupon = new WC_Coupon($coupon_id);
}
$wgItems = array();
foreach ( $items as $item ) {
$line = '';
$line .= '77777';
$line.= '::' . $order->get_line_total( $item, true, true );
$line .= '::' . $item->get_name();
$line .= '::' . $item->get_id();
}
$wgItems[] = $line;
$itemsList = implode('|', $wgItems);
?>
<script>
(function(w,e,b,g,a,i,n,s){w['ITCVROBJ']=a;w[a]=w[a]||function(){
(w[a].q=w[a].q||[]).push(arguments)},w[a].l=1*new Date();i=e.createElement(b),
n=e.getElementsByTagName(b)[0];i.async=1;i.src=g;n.parentNode.insertBefore(i,n)
})(window,document,'script','https://analytics.webgains.io/cvr.min.js','ITCVRQ');
ITCVRQ('set', 'trk.programId', 88888);
ITCVRQ('set', 'cvr', {
value: '<?php echo $total_exc_shipping ?>',
currency: '<?php echo $currency ?>',
language: 'de_DE',
eventId: 77777,
orderReference : '<?php echo $order_id ?>',
comment: '',
multiple: '',
checksum: '',
items: '<?php echo $itemsList ?>',
voucherId: '<?php if ( $order_discount > 0 ) echo $coupon->get_code(); ?>'
});
ITCVRQ('conversion');
</script>
<?php
}
?>
I think this all can be simplified to just use array's implode() method.
Below are what I would do in your situation:
$wgItems = array();
foreach ( $line_items as $item ) {
$line = '';
$line .= '777777';
$line .= '::' . $order->get_line_total( $item, true, true );
$line .= '::' . $item->get_name();
$wgItems[] = $line;
}
$items = implode('|', $wgItems);
Related
$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'm using ultimate member for years, I created a custom tab in Edit Profile to update a value. In fact my users (students) can edit (add or remove) their pre-registered courses. The problem is that when they try to add or remove course, an error occurs, "An error has encountered". Surprisingly, they can remove the course even though it shows an error, but they can't add any course. It was working flawlessly till the latest update of Ultimate member. The code is as follows:
* */
/* create new tab */
add_filter('um_account_page_default_tabs_hook', 'CoursesTab', 100 );
function CoursesTab( $tabs ) {
$tabs[800]['CoursesTab']['icon'] = 'um-faicon-pencil'; // tab icon
$tabs[800]['CoursesTab']['title'] = 'Registered Courses'; // tab title
$tabs[800]['CoursesTab']['submit_title'] = 'Update'; // button text
$tabs[800]['CoursesTab']['custom'] = true;
return $tabs;
}
/* make our new tab hookable */
add_action('um_account_tab__CoursesTab', 'um_account_tab__CoursesTab');
function um_account_tab__CoursesTab( $info ) {
extract( $info );
$output = UM()->account->get_tab_output('CoursesTab');
if ( $output ) { echo $output; }
}
/* Finally we add some content in the tab */
add_filter('um_account_content_hook_CoursesTab', 'um_account_content_hook_CoursesTab');
function um_account_content_hook_CoursesTab( $output ){
ob_start();
$id = um_user('ID');
$output = '<div class="um-field">';
$names = array('course','course');
$fields = array();
foreach( $names as $name ){
$fields[ $name ] = UM()->builtin()->get_specific_field( $name );
}
$fields = apply_filters('um_account_secure_fields', $fields, $id);
foreach( $fields as $key => $data ){
$output .= UM()->fields()->edit_field( $key, $data );
}
$output .= '</div>';
$output .= ob_get_contents();
ob_end_clean();
return $output;
}
/* ensure that the custom fields are updated when the account is updated */
add_action('um_account_pre_update_profile', 'getUMFormData', 100);
function getUMFormData(){
$id = um_user('ID');
$names = array('course','course'); // ADD THE META-KEYS HERE
foreach( $names as $name )
update_user_meta( $id, $name, $_POST[$name] );
}
I searched a lot, however, found no clue how to solve the issue.
Thank you
I’ve added codes in this function:
add_filter('um_account_content_hook_CoursesTab', 'um_account_content_hook_CoursesTab');
function um_account_content_hook_CoursesTab( $output ){
ob_start();
$id = um_user('ID');
$output = '<div class="um-field">';
$names = array('course','course');
$fields = array();
foreach( $names as $name ){
$fields[ $name ] = UM()->builtin()->get_specific_field( $name );
}
$fields = apply_filters('um_account_secure_fields', $fields, $id);
foreach( $fields as $key => $data ){
$output .= UM()->fields()->edit_field( $key, $data );
}
$output .= '<input type="hidden" name="um_account_nonce_'. esc_attr( 'coursestab' ).'" value="'.esc_attr( wp_create_nonce( 'um_update_account_coursestab' ) ).'" />';
$output .= '</div>';
$output .= ob_get_contents();
ob_end_clean();
return $output;
}
I’ve added a hidden nonce field:
$output .= '<input type="hidden" name="um_account_nonce_'. esc_attr( 'coursestab' ).'" value="'.esc_attr( wp_create_nonce( 'um_update_account_coursestab' ) ).'" />';
Please try it and let me know if you’re still encountering issue.
Regards,
I use Woocommerce latest version 3.4.2.
In this case, we collect the order data: the product and its additives ( I take in meta data).
How to assign the index of variable $skus[] = $product->get_sku(); as the value of variable $product_mod[] = '';?
$product_mod[1] = "0"; // The product ( ingredient Sugar) with key 1 is the product modifier with key 0.
// Get product details
$skus = $item_quantities = $line_item_totals = $product_mod = array();
// Loop though order items
foreach( $order->get_items() as $item_id => $item){
$product_id = $item->get_product_id();
$product = $item->get_product();
$item_quantities[] = $item->get_quantity();
$line_item_totals[] = $item->get_total();
$skus[] = $product->get_sku();
$product_mod[] = NULL;
$ai = $item->get_meta('Optionally select');
if( strpos( $ai, 'Cinnamon' ) !== false ) {
$skus[] = '10001';
$item_quantities[] ='1';
$line_item_totals[] = '50';
$product_mod[] = '';
}
if( strpos( $ai, 'Sugar' ) !== false ) {
$skus[] = '10002';
$item_quantities[] ='1';
$line_item_totals[] = '50';
$product_mod[] = '';
}
if( strpos( $ai, 'Mint' ) !== false ) {
$skus[] = '10003';
$item_quantities[] ='1';
$line_item_totals[] = '50';
$product_mod[] = '';
}
}
// Product details
foreach ($skus as $key => $value){
$data .= "&product_sku[".$key."]=".$value."";
$data .= "&product_quantity[".$key."]=".$item_quantities[$key]."";
$data .= "&product_price[".$key."]=".$line_item_totals[$key]."";
if( isset($product_mod[$key]) ) {
$data .= "&product_mod[".$key."]=".$key."";
}
}
print_r( $data ); now show:
// For the convenience of reading, I wrote in a column, but this is a string.
&product_sku[0]=10030
&product_quantity[0]=1
&product_price[0]=499
&product_sku[1]=10002
&product_quantity[1]=1
&product_price[1]=50
&product_mod[1]=1
Need:
&product_sku[0]=10030 // Coffe sku
&product_quantity[0]=1 // Coffe quantity
&product_price[0]=499 // Coffe price
&product_sku[1]=10002 // Sugar sku
&product_quantity[1]=1 // Sugar quantity
&product_price[1]=50 // Sugar price
&product_mod[1]=0 // Ingredient Sugar with number 1, is a product modifier with number 0.
I think this is right way:
You have been complicating a bit the thing… You need to set the main order item index in a variable to get it for your product modifier in the selected additional options. No need of any complications…
I have revisited, simplified and compacted your code:
// Array of defined options ( sku => option name )
$options = array(
'10001' => 'Cinnamon',
'10002' => 'Sugar',
'10003' => 'Mint',
);
$count = 0;
// Loop though order items
foreach( $order->get_items() as $item_id => $item){
$product_id = $item->get_product_id();
$product = $item->get_product();
$data .= '&product_sku['.$count.']='.$product->get_sku();
$data .= '&product_quantity['.$count.']='.$item->get_quantity();
$data .= '&product_price['.$count.']='.$item->get_total();
$ind = $count; // Here we set the main order item index in a variable
$count++;
// Get order item selected options
$options_selected = $item->get_meta('Optionally select');
// Loop though order items selected options
foreach( $options as $sku_key => $label_value ){
if( strpos( $options_selected, $label_value ) !== false ) {
$data .= '&product_sku['.$count.']='.$sku_key;
$data .= '&product_quantity['.$count.']=1';
$data .= '&product_price['.$count.']=50';
$data .= '&product_mod['.$count.']='.$ind;
$count++;
}
}
}
// Testing output
print_r( $data );
Untested, but it should work as expected.
Just make a class. That's what they are made for.
That way you will always have your data neatly grouped together the way you want it without the messiness of having to remain an order or multiple arrays.
The class below is just a proof of concept, getters and setters you'll have to make yourself, but if you do it like this, you have control of the data, where it goes, what belongs with what, and you can even move data from one array to another or copy the objects over.
What you do is make your own object that has the product data you want.
Then you add an array in it "extras" where you can "extras" to the product.
Then you add a function to count the total of "own price + price of extras"
And some other helper functions you need.
Then you wrap it up and have a nice class to help you.
Please note, it's pseudo code, will need some work.
class ProductData
{
protected $product_id;
protected $product;
protected $quantity;
protected $total;
protected $sku;
protected $extras = [];
public function __construct($product_id, $product, $sku, $total, $quantity)
{
$this->product_id = $product_id;
$this->product = $product;
$this->sku = $sku;
$this->total = $total;
$this->quantity = $quantity;
}
public function addExtra($product)
{
$this->extras[] = $product;
}
public function getTotal()
{
$total = $this->total;
foreach($this->extras as $extra) {
$this->total += $extra->getTotal();
}
return total;
}
public static function fromItem($item)
{
$product = new self(
$item->get_product_id(),
$item->get_product(),
$item->get_sku(),
$item->line_item_totals(),
$item->get_quantity()
);
return $product;
}
}
$preregistered_extras = [
'Cinnamon' => new Product(
wc_get_product_id_by_sku('10001'),
wc_get_product(wc_get_product_id_by_sku('10001')),
'10001',
'50',
'1'),
'Sugar' => new Product(
wc_get_product_id_by_sku('10002'),
wc_get_product(wc_get_product_id_by_sku('10002')),
'10002',
'50',
'1'),
'Mint' => new Product(
wc_get_product_id_by_sku('10003'),
wc_get_product(wc_get_product_id_by_sku('10003')),
'10003',
'50',
'1'),
];
$product_list = [];
foreach( $order->get_items() as $item_id => $item){
$product = Product::fromItem($item);
$ai = $item->get_meta('Optionally select');
foreach($preregistered_extras as $name => $extra) {
if( stripos( $ai, $name ) !== false ) {
$product->addExtra($extra);
}
}
}
var_dump($product_list);
$total = 0;
foreach($product_list as $item) {
$total += $item->getTotal();
}
echo "Total = $total";
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;
I am trying to get the results from my Foreach in another echo way later then the foreach but I am stuck, any help would be much appericated.
$items = $order->get_items();
// Output the loop
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU = $product->get_sku();
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
// this gives all 3 quantities and all 3 sku, added a space at the end for easier reading
// this only gives the 1st entry of both variables but i need all 3 of both variables
echo '<a href="https://www.domainname.someurl'.$product_quantity .$SKU . '" target=_blank>';
echo "<p>TEXT</p></a>";
I hope it is clear like this, thanks
Well, you're overwriting the value of $SKU and product_qty on each iteration, maybe try storing them in an array? Like create an array outsite the loop and use array_push(created_array, array($SKU, $product_qty)). Hope it helps.
$items = $order->get_items();
$push = array();
// Output the loop
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU = $product->get_sku();
array_push($push, array('sku'=>$SKU, 'qty'=>$product_qty));
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
// this gives all 3 quantities and all 3 sku, added a space at the end for easier reading
// this only gives the 1st entry of both variables but i need all 3 of both variables
$link = '<a href="https://www.domainname.someurl';
for ($i=0;$i<count($push);$i++){
$link .= $push[$i]['qty'];
$link .= $push[$i]['sku'];
}
$link .= '" target=_blank>';
echo $link;
Try the below code
$items = $order->get_items();
// Output the loop
$product_qty_string = '';
$sku_string = '';
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty_string .= $item['qty']."-";
// SKU
$SKU = $product->get_sku();
$sku_string .=$SKU."-";
}
$product_quantity = rtrim($product_qty_string,'-');
$SKU = rtrim($sku_string,'-');
echo '<a href="https://www.domainname.someurl'.$product_quantity.''.$SKU.''" target=_blank>';
echo "<p>TEXT</p></a>";
Why don't you add your values in a array and then implode them.
$items = $order->get_items();
// Output the loop
$SKU = $product_qty = [];
foreach ($order->get_items() as $item) {
// Getting some information
$product_qty[] = $item['qty'];
$product_variation_id = $item['variation_id'];
$product = new WC_Product($item['product_id']);
// SKU
$SKU[] = $product->get_sku();
print_r($SKU);
print_r($product_qty);
print_r(' ');
}
$sku_string = implode('-', $SKU);
$product_qty_string = implode('-', $product_qty);
echo '<a href="https://www.domainname.someurl'.$product_qty_string .$sku_string . '" target=_blank>';
echo "<p>TEXT</p></a>";
You can implode your data with any separator you want, i use "-" for my example but its depending on your needs.