I want to change the download_url on My account downloads section in WooCommerce
current url: http://localhost/i/?download_file=
new url: http://localhost/i/account/downloads/?download_file=
Therefore I changed home_url( '/' ) to home_url( '/account/downloads/' ) using the hook below:
function filter_woocommerce_customer_available_downloads( $downloads, $customer_id ) {
$downloads = array();
$_product = null;
$order = null;
$file_number = 0;
// Get results from valid orders only.
$results = wc_get_customer_download_permissions( $customer_id );
if ( $results ) {
foreach ( $results as $result ) {
$order_id = intval( $result->order_id );
if ( ! $order || $order->get_id() !== $order_id ) {
// New order.
$order = wc_get_order( $order_id );
$_product = null;
}
// Make sure the order exists for this download.
if ( ! $order ) {
continue;
}
// Check if downloads are permitted.
if ( ! $order->is_download_permitted() ) {
continue;
}
$product_id = intval( $result->product_id );
if ( ! $_product || $_product->get_id() !== $product_id ) {
// New product.
$file_number = 0;
$_product = wc_get_product( $product_id );
}
// Check product exists and has the file.
if ( ! $_product || ! $_product->exists() || ! $_product->has_file( $result->download_id ) ) {
continue;
}
$download_file = $_product->get_file( $result->download_id );
// If the downloadable file has been disabled (it may be located in an untrusted location) then do not return it.
if ( ! $download_file->get_enabled() ) {
continue;
}
// Download name will be 'Product Name' for products with a single downloadable file, and 'Product Name - File X' for products with multiple files.
$download_name = apply_filters(
'woocommerce_downloadable_product_name',
$download_file['name'],
$_product,
$result->download_id,
$file_number
);
$downloads[] = array(
'download_url' => add_query_arg(
array(
'download_file' => $product_id,
'order' => $result->order_key,
'email' => rawurlencode( $result->user_email ),
'key' => $result->download_id,
),
home_url( '/account/downloads/' )
),
'download_id' => $result->download_id,
'product_id' => $_product->get_id(),
'product_name' => $_product->get_name(),
'product_url' => $_product->is_visible() ? $_product->get_permalink() : '', // Since 3.3.0.
'download_name' => $download_name,
'order_id' => $order->get_id(),
'order_key' => $order->get_order_key(),
'downloads_remaining' => $result->downloads_remaining,
'access_expires' => $result->access_expires,
'file' => array(
'name' => $download_file->get_name(),
'file' => $download_file->get_file(),
),
);
$file_number++;
}
}
return $downloads;
} add_filter( 'woocommerce_customer_available_downloads', 'filter_woocommerce_customer_available_downloads', 10, 2 );
Code is based on the wc_get_customer_available_downloads( $customer_id ) function, which can be found in /includes/wc-user-functions.php file
Is it possible to summarize the hook?
The woocommerce_customer_available_downloads filter hook does indeed allow you to change download_url, however it is not necessary to rewrite the entire function via the hook, as you only want to change a certain part.
This can be done using the following code, which uses str_replace() in the code :
/**
* Function for `woocommerce_customer_available_downloads` filter-hook.
*
* #param $downloads
* #param $customer_id
*
* #return
*/
function filter_woocommerce_customer_available_downloads( $downloads, $customer_id ) {
// Only on my account downloads section
if ( ! is_wc_endpoint_url( 'downloads' ) )
return $downloads;
// Loop though downloads
foreach( $downloads as $key => $download ) {
// Replace
$downloads[$key]['download_url'] = str_replace( '/?download_file', '/account/downloads/?download_file', $download['download_url'] );
}
return $downloads;
}
add_filter( 'woocommerce_customer_available_downloads', 'filter_woocommerce_customer_available_downloads', 10, 2 );
Related
I have two scripts that are interfering with each other. What I need for this website is that: all successful purchases should go to page https://aefcoaching.com/gracias-por-tu-compra, except successful purchase of Product ID 1813, which should go to https://aefcoaching.com/gracias-gimnasio-mental/
/* # Redirect to the Thank You page after successful payment in WooCommerce */
if( !function_exists('sc_custom_redirect_after_purchase') ):
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
add_action('template_redirect', 'sc_custom_redirect_after_purchase');
endif;
/* # Redirect Gimnasio Mental purchases to a specific Thank You Page */
function action_woocommerce_thankyou( $order_id ) {
if( ! $order_id ) {
return;
}
// Instannce of the WC_Order Object
$order = wc_get_order( $order_id );
// Is a WC_Order
if ( is_a( $order, 'WC_Order' ) ) {
// False
$redirection = false;
// Loop through order items
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
$redirection = true;
}
}
}
// Make the custom redirection when a targeted product has been found in the order
if ( $redirection ) {
wp_safe_redirect( home_url( '/gracias-gimnasio-mental/' ) );
exit;
}
}
add_action( 'woocommerce_thankyou', 'action_woocommerce_thankyou', 10, 1 );
The first piece works great. The second doesn't because of the first one. I'm not sure how to integrate these two rather than have 2 separate codes. Can you help me?
Please merge the two logics into one , by changing your sc_custom_redirect_after_purchase function into the following:
function sc_custom_redirect_after_purchase() {
global $wp;
if ( is_checkout() && !empty($wp->query_vars['order-received']) ) :
$order_id = absint($wp->query_vars['order-received']);
$order_key = wc_clean($_GET['key']);
$th_page_url = 'https://aefcoaching.com/gracias-por-tu-compra';
//////////////////////
$order = wc_get_order( $order_id );
foreach ( $order->get_items() as $item_key => $item ) {
// Product ID(s)
$product_ids = array( $item->get_product_id(), $item->get_variation_id() );
// Product ID in array
if ( in_array( 1813, $product_ids ) ) {
// $redirection = true;
$th_page_url = 'https://aefcoaching.com/gracias-gimnasio-mental/';
}
}
/////////////////////
$redirect = add_query_arg(
array(
'order' => $order_id,
'key' => $order_key,
), $th_page_url);
wp_safe_redirect($redirect);
exit;
endif;
}
I'm trying to override the ajax add to cart function of WooCoommerce and add this simple condition.
$base = true;
if($base){
return the default error just to test...
}else{
default functionality ...
}
I get the idea from here and simply add my condition to it just to test but it doesn't work.
function woocommerce_ajax_add_to_cart() {
global $woocommerce;
check_ajax_referer( 'add-to-cart', 'security' );
$product_id = apply_filters('woocommerce_add_to_cart_product_id', absint( $_POST['product_id'] ) );
$quantity = empty( $_POST['quantity'] ) ? 1 : apply_filters( 'woocommerce_stock_amount', $_POST['quantity'] );
$passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity );
$base = true;
if($base){//simple condition
header( 'Content-Type: application/json; charset=utf-8' );
// If there was an error adding to the cart, redirect to the product page to show any errors
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id)
);
$woocommerce->set_messages();
echo json_encode( $data );
}else{
if ( $passed_validation && $woocommerce->cart->add_to_cart( $product_id, $quantity ) ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) {
woocommerce_add_to_cart_message( $product_id );
$woocommerce->set_messages();
}
// Return fragments
woocommerce_get_refreshed_fragments();
} else {
header( 'Content-Type: application/json; charset=utf-8' );
// If there was an error adding to the cart, redirect to the product page to show any errors
$data = array(
'error' => true,
'product_url' => apply_filters('woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id)
);
$woocommerce->set_messages();
echo json_encode( $data );
}
}
die();
}
add_action('wp_ajax_woocommerce_add_to_cart', 'woocommerce_ajax_add_to_cart');
add_action('wp_ajax_nopriv_woocommerce_add_to_cart', 'woocommerce_ajax_add_to_cart');
Am I missing something?
Yes, you missed the whole thing. Instead of wp_ajax_woocommerce_add_to_cart the action you need is woocommerce_add_to_cart and you don't need the wp_ajax_nopriv_woocommerce_add_to_cart action at all.
Instead of that source, you should be taking the idea from here. It is located on woocommerce/includes/class-wc-ajax.php.
Take note of self::get_refreshed_fragments(), used WC_AJAX::get_refreshed_fragments() instead.
Overall, your code should be:
function woocommerce_ajax_add_to_cart() {
ob_start();
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( !isset( $_POST[ 'product_id' ] ) ) {
return;
}
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_POST[ 'product_id' ] ) );
$product = wc_get_product( $product_id );
$quantity = empty( $_POST[ 'quantity' ] ) ? 1 : wc_stock_amount( wp_unslash( $_POST[ 'quantity' ] ) );
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
$product_status = get_post_status( $product_id );
$variation_id = 0;
$variation = array();
if ( $product && 'variation' === $product->get_type() ) {
$variation_id = $product_id;
$product_id = $product->get_parent_id();
$variation = $product->get_variation_attributes();
}
$base = true;
if ( $base ) { /** Your condition here **/
// If there was an error adding to the cart, redirect to the product page to show any errors.
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ),
);
wp_send_json( $data );
} else {
if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation ) && 'publish' === $product_status ) {
do_action( 'woocommerce_ajax_added_to_cart', $product_id );
if ( 'yes' === get_option( 'woocommerce_cart_redirect_after_add' ) ) {
wc_add_to_cart_message( array( $product_id => $quantity ), true );
}
WC_AJAX::get_refreshed_fragments();
} else {
// If there was an error adding to the cart, redirect to the product page to show any errors.
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ),
);
wp_send_json( $data );
}
}
// phpcs:enable
}
add_action( 'woocommerce_add_to_cart', 'woocommerce_ajax_add_to_cart' );
EDIT: You may be in a known issue (also here) where the action woocommerce_add_to_cart is being called multiple times because of the function WC()->cart->add_to_cart(...).
Base on this source, you can solve it by adding conditional statement so that the WC()->cart->add_to_cart(...) won't cause the issue.
I don't know what you are trying to achieve, but base on your code it looks like you just want to add another condition before adding the products into the cart.
In that case, you could do the following.
function woocommerce_ajax_add_to_cart() {
ob_start();
if ( !isset( $_POST[ 'product_id' ] ) ) {
return;
}
$found = false;
$base = true;
if ( $base ) { /** Your condition here **/
// If there was an error adding to the cart, redirect to the product page to show any errors.
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ),
);
wp_send_json( $data );
}else{
if ( sizeof( WC()->cart->get_cart() ) > 0 ) { //check if product already in cart
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
if ( ! $found ){ // if product not found, add it
WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation );
}
} else {
WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation ); // if no products in cart, add it
}
}
}
add_action( 'woocommerce_add_to_cart', 'woocommerce_ajax_add_to_cart' );
OR
function woocommerce_ajax_add_to_cart() {
ob_start();
if ( !isset( $_POST[ 'product_id' ] ) ) {
return;
}
$found = false;
$base = true;
if ( sizeof( WC()->cart->get_cart() ) > 0 ) { //check if product already in cart
foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
$_product = $values['data'];
if ( $_product->id == $product_id )
$found = true;
}
if ( ! $found ){ // if product not found, add it
if ( $base ) { /** Your condition here **/
$data = array(
'error' => true,
'product_url' => apply_filters( 'woocommerce_cart_redirect_after_error', get_permalink( $product_id ), $product_id ),
);
wp_send_json( $data );
}else{
WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation );
}
}
} else {
WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation ); // if no products in cart, add it
}
}
add_action( 'woocommerce_add_to_cart', 'woocommerce_ajax_add_to_cart' );
I am using woocommerce and I am using a custom post type (products) for my products
This is the code that integrates my custom post type to woocommerce
class WCCPT_Product_Data_Store_CPT extends WC_Product_Data_Store_CPT {
/**
* Method to read a product from the database.
* #param WC_Product
*/
public function read( &$product ) {
$product->set_defaults();
if ( ! $product->get_id() || ! ( $post_object = get_post( $product->get_id() ) ) || ! in_array( $post_object->post_type, array( 'products', 'product' ) ) ) {
throw new Exception( __( 'Invalid product.', 'woocommerce' ) );
}
$id = $product->get_id();
$product->set_props( array(
'name' => $post_object->post_title,
'slug' => $post_object->post_name,
'date_created' => 0 < $post_object->post_date_gmt ? wc_string_to_timestamp( $post_object->post_date_gmt ) : null,
'date_modified' => 0 < $post_object->post_modified_gmt ? wc_string_to_timestamp( $post_object->post_modified_gmt ) : null,
'status' => $post_object->post_status,
'description' => $post_object->post_content,
'short_description' => $post_object->post_excerpt,
'parent_id' => $post_object->post_parent,
'menu_order' => $post_object->menu_order,
'product_id' => $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(),
'reviews_allowed' => 'open' === $post_object->comment_status,
'price' => $post_object->price
) );
$this->read_attributes( $product );
$this->read_downloads( $product );
$this->read_visibility( $product );
$this->read_product_data( $product );
$this->read_extra_data( $product );
$product->set_object_read( true );
}
public function get_product_type( $product_id ) {
$post_type = get_post_type( $product_id );
if ( 'product_variation' === $post_type ) {
return 'variation';
} elseif ( in_array( $post_type, array( 'products', 'product' ) ) ) { // change birds with your post type
$terms = get_the_terms( $product_id, 'product_type' );
return ! empty( $terms ) ? sanitize_title( current( $terms )->name ) : 'simple';
} else {
return false;
}
}
}
add_filter( 'woocommerce_data_stores', 'woocommerce_data_stores' );
function woocommerce_data_stores ( $stores ) {
$stores['product'] = 'WCCPT_Product_Data_Store_CPT';
return $stores;
}
so I know can add to cart the custom post type by adding price on it
I added a custom field using woocommerce_form_field() which is called "Track Length" and will be multiplied per $24 ( 2 x $24 = $28 )
Now I tried using "woocommerce_before_calculate_totals" filter and its not working, the set_price() is not working maybe because its a custom post type
so now I am getting the computation inside "woocommerce_product_get_price" filter but its not working per item in cart
Here is the code inside my functions.php https://codeshare.io/5eN797
I'm trying to bypass the single product page so I've created a custom template page for my subscriptions. On this page I'm generating the buttons to either allow users to signup for a specific subscription or switch their subscription. The problem I'm running into is getting the Switch Subscription URL to go to cart instead of the single product page.
The function below will test whether the user is logged in, if they are not show the add subscription to cart URL. If they are show the switch subscription url which I'm trying to just add it to cart ( or go straight to checkout ).
/**
* Get Subscription URL ( Initial or Switch Subscription ) by Subscription ID
*
* #param Integer $subscription_id
*
* #return void
*/
function woo_subscriptions_checkout_url( $subscription_id, $echo = true ) {
$subscription_id = intval( $subscription_id );
$subscription_url = do_shortcode( '[add_to_cart_url id="' . $subscription_id . '"]' );
if( is_user_logged_in() && function_exists( 'wcs_get_users_subscriptions' ) ) {
$user_subscriptions = wcs_get_users_subscriptions();
if( ! empty( $user_subscriptions ) ) {
foreach( $user_subscriptions as $subscription ) {
$subscription_order_id = $subscription->get_parent_id();
$subscription_key = wcs_get_old_subscription_key( $subscription );
if( ! empty( $subscription_key ) ) {
$plan_parent_id = wp_get_post_parent_id( $subscription_id );
$subscription_url = WC_Subscriptions_Switcher::add_switch_query_arg_post_link( get_permalink( wc_get_page_id( 'subscriptions' ) ), $plan_parent_id );
// Failed Test, Goes to Product
// $subscription_url = WC_Subscriptions_Switcher::get_switch_url( $subscription_order_id, array( 'product_id' => $plan_parent_id ), $subscription );
}
}
}
}
if( $echo ) {
echo $subscription_url;
} else {
return $subscription_url;
}
}
Additional information: There is 1 product with subscriptions as variations. I'm passing the Variation ID to this function in hopes of generating the correct URL.
Here's what we got. We can add it to cart with specific URL arguments: Product, User Subscription ID, New Subscription ID, Subscription Order Line Number, and a nonce. Do not we did this on a single product with subscriptions as variations. This may need to be tweaked in other subscription cases but hopefully it's helpful to someone down the road:
/**
* Generate cart button based on subscription variation ID
*
* #param Array $args
*
* #return void
*/
function prefix_subscriptions_checkout_button( $args = array() ) {
$button_arr = wp_parse_args( $args, array(
'variation_id' => 0,
'btn_class' => array( 'button', 'button-primary' ),
'btn_text' => __( 'Sign Up' ),
'btn_atts' => array(),
) );
$button_arr['btn_url'] = do_shortcode( '[add_to_cart_url id="' . intval( $button_arr['variation_id'] ) . '"]' );
if( is_user_logged_in() && function_exists( 'wcs_get_users_subscriptions' ) ) {
// Grab an array of user subscriptions
$user_subscriptions = wcs_get_users_subscriptions();
if( ! empty( $user_subscriptions ) ) {
// Array( 'Subscription ID' => WC_Subscriptions Object );
foreach( $user_subscriptions as $user_subscription_id => $subscription ) {
// Loop through the users subscription order items to get the subscription order line item
foreach( $subscription->get_items() as $item_line_number => $item_arr ) {
if( $user_subscription_id == $item_arr['order_id'] ) {
if( $item_arr['variation_id'] == $button_arr['variation_id'] ) {
// Change button based on status
switch( $subscription->get_status() ) {
case 'on-hold':
$button_arr['btn_text'] = __( 'On Hold' );
$button_arr['btn_class'] = array( 'button', 'button-secondary' );
$button_arr['btn_url'] = 'javascript:void(0);';
break;
case 'active':
$button_arr['btn_text'] = __( 'Current' );
$button_arr['btn_class'] = array( 'button', 'button-secondary' );
$button_arr['btn_url'] = 'javascript:void(0);';
break;
default:
$button_arr['btn_url'] = add_query_arg( array(
'add-to-cart' => $item_arr['product_id'],
'switch-subscription' => $user_subscription_id,
'variation_id' => $button_arr['variation_id'],
'item' => $item_line_number,
'_wcsnonce' => wp_create_nonce( 'wcs_switch_request' )
),
wc_get_cart_url()
);
}
}
}
}
}
}
}
// Create button attributes
$button_atts = '';
if( ! empty( $button_arr['btn_atts'] ) && is_array( $button_arr['btn_atts'] ) ) {
foreach( $button_arr['btn_atts'] as $attribute => $value ) {
$button_atts .= sprintf( ' %1$s="%2$s"', esc_attr( $attribute ), esc_attr( $value ) );
}
}
// Create button Classes
if( ! empty( $button_arr['btn_class'] ) && is_array( $button_arr['btn_class'] ) ) {
array_walk( $button_arr['btn_class'], 'esc_attr' );
$button_arr['btn_class'] = implode( ' ', $button_arr['btn_class'] );
}
// Display Button
printf( '<a href="%1$s" class="%2$s"%3$s>%4$s</a>',
$button_arr['btn_url'],
esc_attr( $button_arr['btn_class'] ),
( ! empty( $button_atts ) ) ? $button_atts : '',
$button_arr['btn_text']
);
}
I am using the woocommerce action below to call a custom function, but for some reason it's being triggered twice on every order. Does anyone know why this could be or how to fix it so that it only calls once per order?
add_action( 'woocommerce_thankyou', 'parent_referral_for_all', 10, 1 );
function parent_referral_for_all( $order_id ) {
....
}
UPDATE
I thought the action was being triggered twice but I'm not so sure now. I'm using this action to add another referral inside the affiliatewp plugin, which is adding twice, yet my echo of "Thank You" only appears once.
Everything is working as intended except that the referral (and it's associated order note) are being added twice.
Any help would be greatly appreciated.
That full function:
function parent_referral_for_all( $order_id ) {
//Direct referral
$existing = affiliate_wp()->referrals->get_by( 'reference', $order_id );
$affiliate_id = $existing->affiliate_id;
//Total amount
if( ! empty( $existing->products ) ) {
$productsarr = maybe_unserialize( maybe_unserialize( $existing->products ) );
foreach( $productsarr as $productarr ) {
$bigamount = $productarr['price'];
}
}
//Parent amount
$parentamount = $bigamount * .1;
$affiliate_id = $existing->affiliate_id;
$user_info = get_userdata( affwp_get_affiliate_user_id( $existing->affiliate_id ) );
$parentprovider = $user_info->referral;
//Affiliate id by username
$userparent = get_user_by('login',$parentprovider);
$thisid = affwp_get_affiliate_id($userparent->ID);
$args = array(
'amount' => $parentamount,
'reference' => $order_id,
'description' => $existing->description,
'campaign' => $existing->campaign,
'affiliate_id' => $thisid,
'visit_id' => $existing->visit_id,
'products' => $existing->products,
'status' => 'unpaid',
'context' => $existing->context
);
$referral_id2 = affiliate_wp()->referrals->add( $args );
echo "Thank you!";
if($referral_id2){
//Add the order note
$order = apply_filters( 'affwp_get_woocommerce_order', new WC_Order( $order_id ) );
$order->add_order_note( sprintf( __( 'Referral #%d for %s recorded for %s', 'affiliate-wp' ), $referral_id2, $parentamount, $parentamount ) );
}
}
add_action( 'woocommerce_thankyou', 'parent_referral_for_all', 10, 1 );
To avoid this repetition, you couldadd a custom post meta data to the current order, once your "another" referral has been added the first time.
So your code will be:
function parent_referral_for_all( $order_id ) {
## HERE goes the condition to avoid the repetition
$referral_done = get_post_meta( $order_id, '_referral_done', true );
if( empty($referral_done) ) {
//Direct referral
$existing = affiliate_wp()->referrals->get_by( 'reference', $order_id );
$affiliate_id = $existing->affiliate_id;
//Total amount
if( ! empty( $existing->products ) ) {
$productsarr = maybe_unserialize( maybe_unserialize( $existing->products ) );
foreach( $productsarr as $productarr ) {
$bigamount = $productarr['price'];
}
}
//Parent amount
$parentamount = $bigamount * .1;
$affiliate_id = $existing->affiliate_id;
$user_info = get_userdata( affwp_get_affiliate_user_id( $existing->affiliate_id ) );
$parentprovider = $user_info->referral;
//Affiliate id by username
$userparent = get_user_by('login',$parentprovider);
$thisid = affwp_get_affiliate_id($userparent->ID);
$args = array(
'amount' => $parentamount,
'reference' => $order_id,
'description' => $existing->description,
'campaign' => $existing->campaign,
'affiliate_id' => $thisid,
'visit_id' => $existing->visit_id,
'products' => $existing->products,
'status' => 'unpaid',
'context' => $existing->context
);
$referral_id2 = affiliate_wp()->referrals->add( $args );
echo "Thank you!";
if($referral_id2){
//Add the order note
$order = apply_filters( 'affwp_get_woocommerce_order', new WC_Order( $order_id ) );
$order->add_order_note( sprintf( __( 'Referral #%d for %s recorded for %s', 'affiliate-wp' ), $referral_id2, $parentamount, $parentamount ) );
## HERE you Create/update your custom post meta data to avoid repetition
update_post_meta( $order_id, '_referral_done', 'yes' )
}
}
}
add_action( 'woocommerce_thankyou', 'parent_referral_for_all', 10, 1 );
I hope this will help.
You can check for the existence of the _thankyou_action_done post_meta key like so:
<?php
/**
* Allow code execution only once when the hook is fired.
*
* #param int $order_id The Woocommerce order ID.
* #return void
*/
function so41284646_trigger_thankyou_once( $order_id ) {
if ( ! get_post_meta( $order_id, '_thankyou_action_done', true ) ) {
// Your code here.
}
}
add_action( 'woocommerce_thankyou', 'so41284646_trigger_thankyou_once', 10, 1 );