PHP Fatal error in cron when $subscription_ids is an empty array.
Closed this issue · 1 comments
I ran into an issue when updating an old subscription where the $subscription_ids variable turned out to contain an empty array. Which triggers a PHP Fatal error that prevents wp cron from finishing the rest of the queue of subscriptions.
PHP Fatal error: Uncaught TypeError: rsort(): Argument #1 ($array) must be of type array, bool given in /mnt/persist/www/arbetaren.se/release/web/app/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/includes/data-stores/class-wcs-customer-store-cached-cpt.php:117
Perhaps error handling with empty would be in order here to ensure wp cron doesn't abort?
if ( ! empty( $subscription_ids ) ) {
rsort( $subscription_ids );
}
Im getting a similar error on'
PHP Fatal error: Uncaught TypeError: array_sum(): Argument #1 ($array) must be of type array, null given in /wp-content/plugins/woocommerce-subscriptions/vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:449
Adding an extra check in the "get_cart_item_from_session" function (@class-wcs-cart-renewal.php) to see if the line item ID exists in the subscription items array seems to fix this too. Checks added are commented with HOTFIX:
/**
* Restore renewal flag when cart is reset and modify Product object with renewal order related info
*
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/
public function get_cart_item_from_session( $cart_item_session_data, $cart_item, $key ) {
if ( $this->should_honor_subscription_prices( $cart_item ) ) {
$cart_item_session_data[ $this->cart_item_key ] = $cart_item[ $this->cart_item_key ];
$_product = $cart_item_session_data['data'];
// Need to get the original subscription or order price, not the current price
$subscription = $this->get_order( $cart_item );
if ( $subscription ) {
$subscription_items = $subscription->get_items();
// HOTFIX - Check if the line item ID exists in the subscription items array to prevent a fatal error from wp core
if ( isset( $cart_item_session_data[ $this->cart_item_key ]['line_item_id'] ) && isset( $subscription_items[ $cart_item_session_data[ $this->cart_item_key ]['line_item_id'] ] ) ) {
$item_to_renew = $subscription_items[ $cart_item_session_data[ $this->cart_item_key ]['line_item_id'] ];
$price = $item_to_renew['line_subtotal'];
if ( $_product->is_taxable() && $subscription->get_prices_include_tax() ) {
// If this item's subtracted tax data hasn't been repaired, do that now.
if ( isset( $item_to_renew['_subtracted_base_location_tax'] ) ) {
WC_Subscriptions_Upgrader::repair_subtracted_base_taxes( $item_to_renew->get_id() );
// The item has been updated so get a refreshed version of the item.
$item_to_renew = WC_Order_Factory::get_order_item( $item_to_renew->get_id() );
}
if ( isset( $item_to_renew['_subtracted_base_location_taxes'] ) ) {
$price += array_sum( $item_to_renew['_subtracted_base_location_taxes'] ) * $item_to_renew['qty'];
} else {
// HOTFIX - Check if the taxes array and subtotal key exist before accessing them to prevent fatal errors from wp core
if ( isset( $item_to_renew['taxes']['subtotal'] ) ) {
$price += array_sum( $item_to_renew['taxes']['subtotal'] ); // Use the taxes array items here as they contain taxes to a more accurate number of decimals.
}
}
}
// In rare cases quantity can be zero. Check first to prevent triggering a fatal error in php8+
if ( isset( $item_to_renew['qty'] ) && 0 !== (int) $item_to_renew['qty'] ) {
$_product->set_price( $price / $item_to_renew['qty'] );
}
// Don't carry over any sign up fee
wcs_set_objects_property( $_product, 'subscription_sign_up_fee', 0, 'set_prop_only' );
// Allow plugins to add additional strings to the product name for renewals
$line_item_name = is_callable( $item_to_renew, 'get_name' ) ? $item_to_renew->get_name() : $item_to_renew['name'];
wcs_set_objects_property( $_product, 'name', apply_filters( 'woocommerce_subscriptions_renewal_product_title', $line_item_name, $_product ), 'set_prop_only' );
// Make sure the same quantity is renewed
$cart_item_session_data['quantity'] = $item_to_renew['qty'];
}
}
}
return $cart_item_session_data;
}