I recently migrated my Wordpress website to a hosting server and have had issues getting one function to work. When testing it on my local server it worked perfectly but now I can't seem to figure out why it will not write to my SQL table. The function is here below, any help will be very appreciated. I was also wondering if there is a way to only have the SQL query run when I receive the payment from PayPal if it would require a large change to this program it is not an issue.
add_action( 'woocommerce_order_status_changed', 'checkout_custom_table_insert', 20, 4 );
function checkout_custom_table_insert( $order_id, $old_status, $new_status, $order ){
// Only for 'processing' and 'completed' order status changes
$statuses = array( 'processing', 'completed' );
if ( ! in_array( $new_status, $statuses ) ) return;
// Check if data has been already updated (avoid repetitions)
$is_done = get_post_meta( $order_id, '_checkout_table_updated', true );
if( ! empty($is_done) ) return; // We exit if it has been already done
global $wpdb;
// Loop through order items
foreach ($order->get_items() as $item){
$product = $item->get_product(); // Get the variation product object
// Choose in the array which data you want to insert (each line is a table column)
$args = array(
'rank' => $product->get_attribute( 'pa_rank' ),
'money' => $product->get_attribute( 'pa_money' ),
'spawner' => $product->get_attribute( 'pa_spawner' ),
'permission' => $product->get_attribute( 'pa_permission' ),
'kit' => $product->get_attribute( 'pa_kit' ),
'crate' => $product->get_attribute( 'pa_crate' ),
'stag' => $product->get_attribute( 'pa_stag' ),
'duration' => $product->get_attribute( 'pa_duration' ),
'end_date' => date("Y-m-d", strtotime("+$duration Months")),
'username' => get_post_meta( $order_id, 'My Field', true ),
'executed' => "false",
);
// The SQL INSERT query
$table = "checkout"; // or "{$wpdb->prefix}checkout";
$wpdb->insert( $table, $args ); // Insert the data
}
// Mark this task as done for this order
update_post_meta( $order_id, '_checkout_table_updated', '1' );
}
Ohh, you have order status as below to check against order status:
$statuses = array( 'processing', 'completed' );
but woocommerce order status are as follow:
'wc-pending','wc-processing', 'wc-on-hold' ,'wc-completed' , 'wc-cancelled', 'wc-refunded' , 'wc-failed'
update your array to:
$statuses = array( 'wc-processing', 'wc-completed' );
Related
I am using this code to add admin action to change bulk order statuses.
I have custom build status with name "wc-to-order".
Unfortunatelly, I got error when use code from Woo bulk action.
Can anyone help me to resolve it?
This is code:
add_action( 'admin_action_wc-to-order', 'add_new_order_status_wc_on_hold' ); // admin_action_{action name}
function add_new_order_status_wc_on_hold() {
// if an array with order IDs is not presented, exit the function
if( !isset( $_REQUEST['post'] ) && !is_array( $_REQUEST['post'] ) )
return;
foreach( $_REQUEST['post'] as $order_id ) {
$order = new WC_Order( $order_id );
$order_note = 'That\'s what happened by bulk edit:';
$order->update_status( 'wc-to-order', $order_note, true );
}
$location = add_query_arg( array(
'post_type' => 'shop_order',
'wc-to-order' => 1, // markED_awaiting_shipment=1 is just the $_GET variable for notices
'changed' => count( $_REQUEST['post'] ), // number of changed orders
'ids' => join( $_REQUEST['post'], ',' ),
'post_status' => 'all'
), 'edit.php' );
wp_redirect( admin_url( $location ) );
exit;
}
I got this in debug log
PHP Fatal error: Uncaught TypeError: join(): Argument #2 ($array) must be of type ?array, string given in /public_html/sitename/wp-content/themes/themename/functions.php:648
From the log, it appears that $_REQUEST['post'] may not be an array. In the below code we first check if it is an array. If it is not, then we cast it as array.
add_action( 'admin_action_wc-to-order', 'add_new_order_status_wc_on_hold' ); // admin_action_{action name}
function add_new_order_status_wc_on_hold() {
// if an array with order IDs is not presented, exit the function
if( !isset( $_REQUEST['post'] ) ) {
return;
}
//check if it is an array. If not, cast it as array
$orders_array = is_array($_REQUEST['post']) ? $_REQUEST['post'] : array($_REQUEST['post']);
foreach( $orders_array as $order_id ) {
$order = new WC_Order( $order_id );
$order_note = 'That\'s what happened by bulk edit:';
$order->update_status( 'wc-to-order', $order_note, true );
}
$location = add_query_arg( array(
'post_type' => 'shop_order',
'wc-to-order' => 1, // markED_awaiting_shipment=1 is just the $_GET variable for notices
'changed' => count( $orders_array ), // number of changed orders
'ids' => join( $orders_array, ',' ),
'post_status' => 'all'
), 'edit.php' );
wp_redirect( admin_url( $location ) );
exit;
}
This way we ensure that array is always provided to join function.
The woe_order_export_started filter hook is related to a plugin
This code is used for exporting orders with total > 10
add_filter( 'woe_order_export_started', function ( $order_id ) {
$order = new WC_Order($order_id);
return ($order->get_total() > 10.00) ? $order_id: false;
});
I am trying to create a php code to find out whether the order has order note or not, and to ignore the orders which has no order note.
I found out the code to get the order notes
$args = array(
'post_id' => $order->id,
'approve' => 'approve',
'type' => 'order_note',
'search' => 'Order status changed from Pending Payment to Processing.',
);
// woocommerce hides such records by default
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10 );
$notes = get_comments( $args );
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ), 10, 1 );
How to I implement this with the woe_order_export_started filter hook to determine if the order has order note or not.
Basically I want to avoid exporting the orders which has no order note. So it should return false if there is no order note.
The following answer returns false if there are no order notes, while using the woo_order_export_started filter hook
function filter_woe_order_export_started( $order_id ) {
// Get order notes
$notes = wc_get_order_notes( array(
'order_id' => $order_id,
'order_by' => 'date_created',
'order' => 'ASC',
));
// Notes is empty
if ( empty( $notes ) ) {
return false;
}
return $order_id;
}
add_filter( 'woe_order_export_started', 'filter_woe_order_export_started', 10, 1 );
I'm trying to run the following function daily, to auto-complete all processing order older than 10 days and who have a specific custom meta value.
I'm using the following snippet, however this will simply not work. Any idea as to why?
function autoComplete(){
$orders = wc_get_orders( array(
'status' => 'wc-processing',
'date_created' => '<' . ( time() - 10 * DAY_IN_SECONDS ),
'meta_key' => 'status_us',
'meta_compare' => '=',
'meta_value' => 'Sent to USA',
) );
foreach ($orders as $order){
$order->update_status( 'completed' );
}
}
if ( ! wp_next_scheduled( 'autoComplete' ) ) {
wp_schedule_event( time(), 'daily', 'autoComplete' );
}
Is there any error I've missed? Thanks for your help!
You did a good attempt but you made a few mistakes.
The following code goes inside your functions.php.
add_action( 'wp_loaded','start_custom_code' );
// Once everything theme and plugins are loaded we register our cron job.
function start_custom_code() {
if ( ! wp_next_scheduled( 'bks_mark_processing_order_complete_if_sent_to_usa' ) ) {
wp_schedule_event( time(), 'daily', 'bks_mark_processing_order_complete_if_sent_to_usa' );
}
}
add_action( 'bks_mark_processing_order_complete_if_sent_to_usa', 'bks_mark_processing_order_complete_if_sent_to_usa' );
Your function has minor errors bks_mark_processing_order_complete_if_sent_to_usa()
function bks_mark_processing_order_complete_if_sent_to_usa(){
$args = array(
'status' => array( 'wc-processing'),
'limit' => -1,
'date_created' => '>' . ( time() - 864000 ), // your mistake 1
'status_us' => 'Sent to USA', // your mistake 2
);
$orders = wc_get_orders( $args );
foreach ($orders as $order){
$order->update_status( 'completed' );
$order->save(); // your mistake 3
}
};
Mistake Explanations
While your attempt was in right direction but 'date_created' => '<' . ( time() - 10 * DAY_IN_SECONDS ), you had to use > instead of < also you didn't acutally set DAY_IN_SECONDS You had to replace it with 86400. So the correct value would be '>' . ( time() - 864000 ). For 10 days 10 * 86400 = 864000. You can read about this explanation here in the WooCommerce documentation.
Here I have created new custom variable for you which is set using woocommerce_order_data_store_cpt_get_orders_query and then queried. Code that needs to be added.
function handle_custom_query_var( $query, $query_vars ) {
if ( ! empty( $query_vars['status_us'] ) ) {
$query['meta_query'][] = array(
'key' => 'status_us',
'value' => esc_attr( $query_vars['status_us'] ),
);
}
return $query;
}
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', 'handle_custom_query_var', 10, 2 );
You updated the status but you forgot to save it. $order->save();
So to summarise you have to add the following code in your functions.php
add_action( 'wp_loaded','start_custom_code' );
add_action( 'bks_mark_processing_order_complete_if_sent_to_usa', 'bks_mark_processing_order_complete_if_sent_to_usa' );
function start_custom_code() {
if ( ! wp_next_scheduled( 'bks_mark_processing_order_complete_if_sent_to_usa' ) ) {
wp_schedule_event( time(), 'daily', 'bks_mark_processing_order_complete_if_sent_to_usa' );
}
}
function bks_mark_processing_order_complete_if_sent_to_usa(){
$args = array(
'status' => array( 'wc-processing'),
'limit' => -1,
'date_created' => '>' . ( time() - 864000 ),
'status_us' => 'Sent to USA',
);
$orders = wc_get_orders( $args );
foreach ($orders as $order){
$order->update_status( 'completed' );
$order->save();
}
};
function handle_custom_query_var( $query, $query_vars ) {
if ( ! empty( $query_vars['status_us'] ) ) {
$query['meta_query'][] = array(
'key' => 'status_us',
'value' => esc_attr( $query_vars['status_us'] ),
);
}
return $query;
}
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', 'handle_custom_query_var', 10, 2 );
The above code is TESTED and WORKS.
Proof:
Install WP CRON plugin to check your cron. See above screenshot. You can test by hitting Run Now.
Caveat :
WP Cron runs, when somebody visits your website. Thus if nobody visits, ?>the cron never runs.
Read this : https://wordpress.stackexchange.com/a/179774/204925
Here is what I do to validate orders based on a CRON task.
$order->payment_complete('transaction ID string'); //validate payment
wc_reduce_stock_levels($order->get_id()); //reduce stock
$woocommerce->cart->empty_cart(); //empty cart
$order->update_status('completed', 'A order note string'); //change order statyus
I believe that you don't need the "wc-" prefix.
Are you sure that your scheduled event is working? and that $orders is filled? Please test your method without the schedule first.
Here is my problem ! I have a website with Wordpress and i'm selling items with WPForms lite editions. There is 1 form with every client's information that i need to put into my SQL database.
When a client completed a transactions successfully, WPForm as a Entry with all information i need put but i'm not able to transfer this information to my SQL database!
My Wpform information looks like this :
Invoice ID
Full name
Email
Purchase
Unit Price
Quantity
Subtotal
TPS
TVQ
Total
Billing information
Agent Number
Payment Information (stripe)
I've looked through this code......and i'm not sure what's what in this. It seems every ID of my single WPForm will be put into a value...?? but how is it suppose to go into my databse? Need explanation !
add_action( 'wpforms_process_complete', 'process_entry', 5, 4 );
function process_entry( $form_fields, $entry, $form_data, $entry_id ) {
global $wpdb;
$form_id = $form_data['id'];
$entry_data = array(
'form_id' => $form_id,
'status' => 'publish',
'referer' => $_SERVER['HTTP_REFERER'],
'date_created' => current_time( 'mysql' )
);
// Insert into wpforms_entries custom table.
$success = $wpdb->insert( $wpdb->prefix . 'wpforms_entries', $entry_data );
$entry_id = $wpdb->insert_id;
// Create meta data.
if ( $entry_id ) {
foreach ( $form_fields as $field ) {
$field = apply_filters( 'wpforms_process_entry_field', $field, $form_data, $entry_id );
if ( isset( $field['value'] ) && '' !== $field['value'] ) {
$field_value = is_array( $field['value'] ) ? serialize( $field['value'] ) : $field['value'];
$entry_metadata = array(
'entry_id' => $entry_id,
'meta_key' => $field['name'],
'meta_value' => $field_value,
);
// Insert entry meta.
$wpdb->insert( $wpdb->prefix . 'wpforms_entrymeta', $entry_metadata );
}
}
}
}
All i want is to transfer my WPForm information value to SQL database (phpadmin)
Trying this instead and.....still no getting anywhere with it. My Databse is already connected to my wordpress and yet i'm not able to anything to it.
function Formsql( $fields, $entry, $form_data, $entry_id ) {
global $wpdb;
$body = array(
'InvoiceID' => '',
'FullName' => $fields['1']['value'],
'Email' => $fields['2']['value'],
'Purchase' => $fields['3']['value'],
'UnitPrice' => $fields['4']['value'],
'Quantity' => $fields['5']['value'],
'SubTotal' => $fields['6']['value'],
'TPS' => $fields['7']['value'],
'TVQ' => $fields['8']['value'],
'Total' => $fields['9']['value'],
'BillingInfo' => $fields['10']['value'],
'AgentNumber' => $fields['11']['value'],
'Payment' => $fields['12']['value'],
);
$request = wp_remote_post($wpdb->prefix . 'Vente', array( 'body' => $body ) );
}
add_action( 'wpforms_process_complete_4427', 'Formsql', 10, 4 );
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 );