Skip to content

Instantly share code, notes, and snippets.

@willgorham
Last active December 29, 2023 02:06
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save willgorham/874c4ac943fc27443cd862a93764d659 to your computer and use it in GitHub Desktop.
Save willgorham/874c4ac943fc27443cd862a93764d659 to your computer and use it in GitHub Desktop.
WooCommerce: Automatically complete virtual orders
<?php
add_filter( 'woocommerce_payment_complete_order_status', 'wmg_auto_complete_virtual_orders', 10, 3 );
/**
* Automatically complete orders with only virtual products
*
* @param string $payment_complete_status Order status used after an order payment is received
* @param int $order_id ID of the order being processed
* @param WC_Order $order Order object being processed
* @return string $payment_complete_status Updated order status
*/
function wmg_auto_complete_virtual_orders( $payment_complete_status, $order_id, $order ) {
$current_status = $order->get_status();
// We only want to update the status to 'completed' if it's coming from one of the following statuses:
$allowed_current_statuses = array( 'on-hold', 'pending', 'failed' );
if ( 'processing' === $payment_complete_status && in_array( $current_status, $allowed_current_statuses ) ) {
$order_items = $order->get_items();
// Create an array of products in the order
$order_products = array_filter( array_map( function( $item ) {
// Get associated product for each line item
return $item->get_product();
}, $order_items ), function( $product ) {
// Remove non-products
return !! $product;
} );
if ( count( $order_products ) > 0 ) {
// Check if each product is 'virtual'
$is_virtual_order = array_reduce( $order_products, function( $virtual_order_so_far, $product ) {
return $virtual_order_so_far && $product->is_virtual();
}, true );
if ( $is_virtual_order ) {
$payment_complete_status = 'completed';
}
}
}
return $payment_complete_status;
}
@Croolw
Copy link

Croolw commented Nov 17, 2021

Does anyone find the solution for the php 7.4 warning:
Warning: count(): Parameter must be an array or an object that implements Countable.
If so can you tell me?

@colinskuse
Copy link

im a bit of a newbe to code, Wordpress & WooCommerce. where do i need to place this code ?

@jsbls
Copy link

jsbls commented Jun 5, 2022

@colinskuse Your theme's functions.php file. Ideally, you should be using a Child Theme. You can find the functions.php file at wp-content/themes/your-theme.

If there's code there already, just paste the code at the very bottom or the very top. Make sure you remove the starting <?php tag in this script if there's already one in your file, though.

@nmbgeek
Copy link

nmbgeek commented Jun 26, 2023

Any suggestions for the error thrown below. This was working until some recent updates.

2023-06-16T01:25:05+00:00 CRITICAL Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, bool given in /home/runcloud/webapps/bastore/wp-content/themes/oceanwp-child-theme-master/functions.php:192
Stack trace:
#0 /home/runcloud/webapps/bastore/wp-includes/class-wp-hook.php(308): auto_complete_virtual_orders()
#1 /home/runcloud/webapps/bastore/wp-includes/plugin.php(205): WP_Hook->apply_filters()
#2 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce/includes/class-wc-order.php(142): apply_filters()
#3 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce-square/includes/Framework/PaymentGateway/Payment_Gateway_Direct.php(329): WC_Order->payment_complete()
#4 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce/includes/class-wc-checkout.php(1050): WooCommerce\Square\Framework\PaymentGateway\Payment_Gateway_Direct->process_payment()
#5 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce/includes/class-wc-checkout.php(1279): WC_Checkout->process_order_payment()
#6 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce/includes/class-wc-ajax.php(485): WC_Checkout->process_checkout()
#7 /home/runcloud/webapps/bastore/wp-includes/class-wp-hook.php(308): WC_AJAX::checkout()
#8 /home/runcloud/webapps/bastore/wp-includes/class-wp-hook.php(332): WP_Hook->apply_filters()
#9 /home/runcloud/webapps/bastore/wp-includes/plugin.php(517): WP_Hook->do_action()
#10 /home/runcloud/webapps/bastore/wp-content/plugins/woocommerce/includes/class-wc-ajax.php(96): do_action()
#11 /home/runcloud/webapps/bastore/wp-includes/class-wp-hook.php(308): WC_AJAX::do_wc_ajax()
#12 /home/runcloud/webapps/bastore/wp-includes/class-wp-hook.php(332): WP_Hook->apply_filters()
#13 /home/runcloud/webapps/bastore/wp-includes/plugin.php(517): WP_Hook->do_action()
#14 /home/runcloud/webapps/bastore/wp-includes/template-loader.php(13): do_action()
#15 /home/runcloud/webapps/bastore/wp-blog-header.php(19): require_once('...')
#16 /home/runcloud/webapps/bastore/index.php(17): require('...')
#17 {main}
  thrown in /home/runcloud/webapps/bastore/wp-content/themes/oceanwp-child-theme-master/functions.php on line 192

@daza110
Copy link

daza110 commented Aug 25, 2023

@Croolw @gbozzetti @nmbgeek

The line:
if ( count( $order_products > 0 ) ) {

Needs to be changed to:

if ( count( $order_products ) > 0 ) {

Note the correct placement of the close bracket on the count() function - this fixes the error you are all encountering

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment