Updates to 6.2.0

This commit is contained in:
WooCommerce
2024-04-11 10:13:02 +00:00
parent d3348c6c8f
commit cc9b3f8f53
21 changed files with 358 additions and 233 deletions

View File

@@ -1,5 +1,18 @@
*** Woo Subscriptions Changelog ***
2024-04-11 - version 6.2.0
* Add: Declare WooCommerce as a plugin dependency in the plugin header.
* Fix: Ensure next payment dates are only extended when early renewal orders paid via the modal are fully paid. Prevents extending dates on authorized but not captured payments.
* Fix: Updated the switching calculator to handle situations where an upgrade has a new price per day less than the old price per day. Previously this would result in a negative upgrade cost.
* Fix: Update the failing payment method on a subscription when customers successfully pay for a failed renewal order via the block checkout.
* Fix: Resolved an issue that would cause subscriptions to be directly cancelled by the WooCommerce process of automatically cancelling unpaid orders in-line with the hold stock setting.
* Fix: Prevent duplicate status transition notes on subscriptions and potential infinite loops when processing subscription status transitions.
* Fix: Resolved an issue that could lead to "Undefined array key 'order-received'" errors.
* Fix: Resolved errors that could occur when paying for renewal orders via the checkout when the store has custom checkout fields.
* Fix: Resolved database errors that would occur when ordering the subscriptions list table by the 'Last order date' on sites with HPOS enabled.
* Dev: Introduced a new filter ('wcs_setup_cart_for_subscription_initial_payment') to enable third-party plugins to use the pay-for-order flow to complete a subscription's initial payment.
* Dev: Updated subscriptions-core to 7.0.0.
2024-03-28 - version 6.1.0
* Fix: Ensure the subscription renewal payment process doesn't attempt to reprocess previously paid renewal orders.
* Fix: Resolved an issue where discounts, when reapplied to failed or manual subscription order payments, would incorrectly account for inclusive tax.

View File

@@ -146,7 +146,11 @@ class WCS_Early_Renewal_Modal_Handler {
wc_add_notice( __( 'Payment for the renewal order was unsuccessful with your payment method on file, please try again.', 'woocommerce-subscriptions' ), 'error' );
wp_redirect( wcs_get_early_renewal_url( $subscription ) );
exit();
} else {
}
// Paid early renewals trigger the subscription payment complete hooks, extend next payment dates and reset suspension counts and user roles.
// Orders which are on-hold (manual payment or auth/capture gateways) will be handled when the order eventually is marked as payment complete (process/completed).
if ( $renewal_order->is_paid() ) {
// Trigger the subscription payment complete hooks and reset suspension counts and user roles.
$subscription->payment_complete();

View File

@@ -107,6 +107,12 @@ class WCS_Switch_Totals_Calculator {
$this->reset_prorated_price( $switch_item );
$upgrade_cost = $this->calculate_upgrade_cost( $switch_item );
// If a negative upgrade cost has been calculated. Have the customer pay a full price minus what they are owed and set the next payment to be the new products first payment date.
if ( $upgrade_cost < 0 ) {
$upgrade_cost = $this->calculate_fully_reduced_upgrade_cost( $cart_item_key, $switch_item );
}
$this->set_upgrade_cost( $switch_item, $upgrade_cost );
}
}
@@ -514,6 +520,32 @@ class WCS_Switch_Totals_Calculator {
return $this->cart->cart_contents[ $cart_item_key ]['subscription_switch']['first_payment_timestamp'];
}
/**
* Calculates the cost of the upgrade when the customer pays the new product's full price minus the amount paid and still owing.
*
* This function is used when a switch results in a negative upgrade cost which typically occurs when stores use the `wcs_switch_proration_switch_type` filter to change the default switch type.
* For example, if a customer is switching from a monthly subscription to a yearly subscription, they will pay the yearly product's full price minus whatever is still owed on the monthly product's price.
*
* eg $20/month switched to a $200 yearly product. The upgrade cost would be 200 - ((20/30) * days-left-in-the-current-billing-term).
* Switching on the first day of the month would result in the following calculation: 200 - ((20/30) * 30) = 200 - 20 = 180. The full $20 is owed.
* Switching halfway through the month would result in the following calculation: 200 - ((20/30) * 15) = 200 - 10 = 190. The customer is owed $10 or half what they paid.
*
* @param string $cart_item_key The switch item's cart item key.
* @param WCS_Switch_Cart_Item $switch_item The switch item.
*
* @return float The upgrade cost.
*/
protected function calculate_fully_reduced_upgrade_cost( $cart_item_key, $switch_item ) {
// When a customer pays the full new product price minus the amount already paid, we need to reduce the prepaid term and the subscription's next payment is 1 billing cycle away.
$this->cart->cart_contents[ $cart_item_key ]['subscription_switch']['first_payment_timestamp'] = WC_Subscriptions_Product::get_first_renewal_payment_time( $switch_item->product );
// The customer is owed whatever they didn't use. If they paid $100 for a monthly subscription and are switching half way through the month, they are owed $50.
$remaining_amount_not_consumed = ( $switch_item->get_total_paid_for_current_period() / $switch_item->get_days_in_old_cycle() ) * $switch_item->get_days_until_next_payment();
// The customer pays the full price of the new product minus the amount they didn't use.
return ( WC_Subscriptions_Product::get_price( $switch_item->product ) * $switch_item->cart_item['quantity'] ) - ( $remaining_amount_not_consumed );
}
/** Helpers */
/**

View File

@@ -2,16 +2,16 @@
# This file is distributed under the same license as the Woo Subscriptions plugin.
msgid ""
msgstr ""
"Project-Id-Version: Woo Subscriptions 6.1.0\n"
"Project-Id-Version: Woo Subscriptions 6.2.0\n"
"Report-Msgid-Bugs-To: https://woocommerce.com/contact-us\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2024-03-28T06:13:35+00:00\n"
"POT-Creation-Date: 2024-04-11T02:40:29+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.10.0\n"
"X-Generator: WP-CLI 2.9.0\n"
"X-Domain: woocommerce-subscriptions\n"
#. Plugin Name of the plugin
@@ -1368,7 +1368,7 @@ msgstr ""
msgid "Payment for the renewal order was unsuccessful with your payment method on file, please try again."
msgstr ""
#: includes/early-renewal/class-wcs-early-renewal-modal-handler.php:154
#: includes/early-renewal/class-wcs-early-renewal-modal-handler.php:158
msgid "Your early renewal order was successful."
msgstr ""
@@ -1385,7 +1385,7 @@ msgstr ""
#. translators: %d: subscription ID.
#. translators: placeholder is a subscription ID.
#: includes/gateways/class-wc-subscriptions-payment-gateways.php:77
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:192
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:194
msgid "Subscription doesn't exist in scheduled action: %d"
msgstr ""
@@ -1871,7 +1871,7 @@ msgstr ""
msgid "Invalid switch type \"%s\". Switch must be one of: \"upgrade\", \"downgrade\" or \"crossgrade\"."
msgstr ""
#: includes/switching/class-wcs-switch-totals-calculator.php:196
#: includes/switching/class-wcs-switch-totals-calculator.php:202
msgid "Your cart contained an invalid subscription switch request. It has been removed from your cart."
msgstr ""
@@ -1887,46 +1887,6 @@ msgstr ""
msgid "Want to renew early via the checkout? Click %shere.%s"
msgstr ""
#: tests/unit/scheduler/scheduler.php:65
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:291
msgctxt "table heading"
msgid "Start Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:66
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:292
msgctxt "table heading"
msgid "Trial End"
msgstr ""
#: tests/unit/scheduler/scheduler.php:67
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:40
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:293
msgctxt "table heading"
msgid "Next Payment"
msgstr ""
#: tests/unit/scheduler/scheduler.php:68
#: vendor/woocommerce/subscriptions-core/templates/emails/cancelled-subscription.php:23
#: vendor/woocommerce/subscriptions-core/templates/emails/expired-subscription.php:23
#: vendor/woocommerce/subscriptions-core/templates/emails/on-hold-subscription.php:23
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:294
msgctxt "table heading"
msgid "Last Order Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:69
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:295
msgctxt "table heading"
msgid "Cancelled Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:70
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:296
msgctxt "table heading"
msgid "End Date"
msgstr ""
#. translators: 1: relation type, 2: list of valid relation types.
#: vendor/woocommerce/subscriptions-core/includes/abstracts/abstract-wcs-related-order-store.php:148
msgid "Invalid relation type: %1$s. Order relationship type must be one of: %2$s."
@@ -2408,7 +2368,7 @@ msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:327
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1365
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1754
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1937
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1955
#: vendor/woocommerce/subscriptions-core/includes/wcs-user-functions.php:329
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:78
msgctxt "an action on a subscription"
@@ -2532,7 +2492,7 @@ msgstr[1] ""
#. translators: placeholder is the display name of a payment gateway a subscription was paid by
#. translators: %s: payment method.
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:645
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2126
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2147
msgid "Via %s"
msgstr ""
@@ -2600,7 +2560,7 @@ msgid "None"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1159
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2108
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2129
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:170
msgid "Manual Renewal"
msgstr ""
@@ -2955,139 +2915,139 @@ msgid "Read more"
msgstr ""
#. translators: %s: subscription status.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:425
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:437
msgid "Unable to change subscription status to \"%s\"."
msgstr ""
#. translators: 1: subscription status, 2: error message.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:548
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:560
msgid "Unable to change subscription status to \"%1$s\". Exception: %2$s"
msgstr ""
#. translators: 1: old subscription status 2: new subscription status
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:578
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:593
msgid "Status changed from %1$s to %2$s."
msgstr ""
#. translators: %s: new order status
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:592
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:607
msgid "Status set to %s."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:606
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:621
msgid "Error during subscription status transition."
msgstr ""
#. translators: placeholder is human time diff (e.g. "3 weeks")
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1296
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2387
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1308
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2405
msgid "In %s"
msgstr ""
#. translators: placeholder is human time diff (e.g. "3 weeks")
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1299
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1311
#: vendor/woocommerce/subscriptions-core/includes/wcs-formatting-functions.php:246
msgid "%s ago"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1306
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1318
msgid "Not yet ended"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1309
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1321
msgid "Not cancelled"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1314
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1326
msgctxt "original denotes there is no date to display"
msgid "-"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1422
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1434
msgid "The creation date of a subscription can not be deleted, only updated."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1425
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1437
msgid "The start date of a subscription can not be deleted, only updated."
msgstr ""
#. translators: %s: date type (e.g. "trial_end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1430
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1442
msgid "The %s date of a subscription can not be deleted. You must delete the order."
msgstr ""
#. translators: %d: subscription ID.
#. translators: %d: order ID.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1439
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2549
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1451
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2570
msgid "Subscription #%d: "
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1853
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1865
msgid "Payment status marked complete."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1886
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1907
msgid "Payment failed."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1891
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1912
msgid "Subscription Cancelled: maximum number of failed payments reached."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2001
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2022
msgid "The \"all\" value for $order_type parameter is deprecated. It was a misnomer, as it did not return resubscribe orders. It was also inconsistent with order type values accepted by wcs_get_subscription_orders(). Use array( \"parent\", \"renewal\", \"switch\" ) to maintain previous behaviour, or \"any\" to receive all order types, including switch and resubscribe."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2205
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2226
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:835
msgid "Payment method meta must be an array."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2441
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2462
msgid "Invalid format. First parameter needs to be an array."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2445
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2466
msgid "Invalid data. First parameter was empty when passed to update_dates()."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2452
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2473
msgid "Invalid data. First parameter has a date that is not in the registered date types."
msgstr ""
#. translators: placeholder is date type (e.g. "end", "next_payment"...)
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2479
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2500
msgctxt "appears in an error message if date is wrong format"
msgid "Invalid %s date. The date must be of the format: \"Y-m-d H:i:s\"."
msgstr ""
#. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2517
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2538
msgid "The %s date must occur after the cancellation date."
msgstr ""
#. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2523
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2544
msgid "The %s date must occur after the last payment date."
msgstr ""
#. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2528
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2549
msgid "The %s date must occur after the next payment date."
msgstr ""
#. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2534
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2555
msgid "The %s date must occur after the trial end date."
msgstr ""
#. translators: %s: date type (e.g. "next_payment").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2539
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2560
msgid "The %s date must occur after the start date."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2569
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2590
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-checkout.php:348
msgid "Backordered"
msgstr ""
@@ -3699,145 +3659,145 @@ msgstr ""
msgid "Would you like to add a payment method now?"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:112
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2001
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:114
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2019
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2037
msgctxt "used in order note as reason for why subscription status changed"
msgid "Subscription renewal payment due:"
msgstr ""
#. translators: placeholder %1 is an order note. %2 is the error message that was thrown.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:149
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:151
msgid "Error: Unable to create renewal order with note \"%1$s\". Message: %2$s"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:159
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:161
msgid "Manual renewal order awaiting customer payment."
msgstr ""
#. translators: $1: order number, $2: error message
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:342
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:344
msgid "Failed to activate subscription status for order #%1$s: %2$s"
msgstr ""
#. translators: $1: order number, $2: error message
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:370
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:372
msgid "Failed to update subscription status after order #%1$s was put on-hold: %2$s"
msgstr ""
#. translators: $1: order number, $2: error message
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:398
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:400
msgid "Failed to cancel subscription after order #%1$s was cancelled: %2$s"
msgstr ""
#. translators: $1: order number, $2: error message
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:426
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:428
msgid "Failed to set subscription as expired for order #%1$s: %2$s"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:452
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:454
msgid "Subscription sign up failed."
msgstr ""
#. translators: $1: order number, $2: error message
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:462
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:464
msgid "Failed to process failed payment on subscription for order #%1$s: %2$s"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:536
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:538
msgid "Error: Unable to create subscription. Please try again."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:558
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:560
msgid "Error: Unable to add product to created subscription. Please try again."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:603
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:605
msgid "Pending subscription created."
msgstr ""
#. Translators: 1: The subscription ID number. 2: The current user's username.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:997
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1015
msgid "The related subscription #%1$s has been deleted after the customer was deleted by %2$s."
msgstr ""
#. Translators: Placeholder is the subscription ID number.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1000
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1018
msgid "The related subscription #%s has been deleted after the customer was deleted."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1146
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1164
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:221
msgctxt "Subscription status"
msgid "Active"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1149
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1167
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:223
msgctxt "Subscription status"
msgid "Cancelled"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1152
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1170
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:225
msgctxt "Subscription status"
msgid "Expired"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1155
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1173
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:220
msgctxt "Subscription status"
msgid "Pending"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1158
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1176
msgctxt "Subscription status"
msgid "Failed"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1162
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1180
msgctxt "Subscription status"
msgid "On-hold"
msgstr ""
#. translators: 1$: month number (e.g. "01"), 2$: month abbreviation (e.g. "Jan")
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1914
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1932
msgctxt "used in a select box"
msgid "%1$s-%2$s"
msgstr ""
#. translators: all fields are full html nodes: 1$: month input, 2$: day input, 3$: year input, 4$: hour input, 5$: minute input. Change the order if you'd like
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1927
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1945
msgid "%1$s%2$s, %3$s @ %4$s : %5$s"
msgstr ""
#. translators: all fields are full html nodes: 1$: month input, 2$: day input, 3$: year input. Change the order if you'd like
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1931
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1949
msgid "%1$s%2$s, %3$s"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1936
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:1954
msgid "Change"
msgstr ""
#. translators: placeholder is subscription ID
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2269
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2287
msgid "Failed sign-up for subscription %s."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2360
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2378
msgid "Invalid security token, please reload the page and try again."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2364
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2382
msgid "Only store managers can edit payment dates."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2368
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2386
msgid "Please enter all date fields."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2393
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-manager.php:2411
msgid "Date Changed"
msgstr ""
@@ -4137,7 +4097,7 @@ msgstr ""
msgid "Weekly"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-initial-payment.php:65
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-initial-payment.php:85
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:199
msgid "That doesn't appear to be your order."
msgstr ""
@@ -4177,16 +4137,16 @@ msgid_plural "We couldn't find the original renewal orders for items in your car
msgstr[0] ""
msgstr[1] ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:687
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:698
msgid "All linked subscription items have been removed from the cart."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:716
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:727
msgctxt "Used in WooCommerce by removed item notification: \"_All linked subscription items were_ removed. Undo?\" Filter for item title."
msgid "All linked subscription items were"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:1532
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-cart-renewal.php:1543
msgctxt "The place order button text while renewing a subscription"
msgid "Renew subscription"
msgstr ""
@@ -6407,6 +6367,14 @@ msgctxt "table headings in notification email"
msgid "Price"
msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/emails/cancelled-subscription.php:23
#: vendor/woocommerce/subscriptions-core/templates/emails/expired-subscription.php:23
#: vendor/woocommerce/subscriptions-core/templates/emails/on-hold-subscription.php:23
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:294
msgctxt "table heading"
msgid "Last Order Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/emails/cancelled-subscription.php:24
msgctxt "table headings in notification email"
msgid "End of Prepaid Term"
@@ -6689,6 +6657,12 @@ msgstr ""
msgid "ID"
msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:40
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:293
msgctxt "table heading"
msgid "Next Payment"
msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:46
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:53
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:42
@@ -6868,6 +6842,26 @@ msgstr ""
msgid "Can not get address type display name. Address type is not a string."
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:291
msgctxt "table heading"
msgid "Start Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:292
msgctxt "table heading"
msgid "Trial End"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:295
msgctxt "table heading"
msgid "Cancelled Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:296
msgctxt "table heading"
msgid "End Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:331
msgid "Date type is not a string."
msgstr ""

2
vendor/autoload.php vendored
View File

@@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInite5f25043b4323431d48e7e46b04aa2c9::getLoader();
return ComposerAutoloaderInit270a670e4e35541a06419730c5cc18f6::getLoader();

View File

@@ -45,34 +45,35 @@ class ClassLoader
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
/** @var ?string */
private $vendorDir;
// PSR-4
/**
* @var array<string, array<string, int>>
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array<string, list<string>>
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var list<string>
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array();
/**
* @var list<string>
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array();
@@ -80,7 +81,8 @@ class ClassLoader
private $useIncludePath = false;
/**
* @var array<string, string>
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array();
@@ -88,20 +90,21 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
* @var array<string, bool>
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array();
/** @var string|null */
/** @var ?string */
private $apcuPrefix;
/**
* @var array<string, self>
* @var self[]
*/
private static $registeredLoaders = array();
/**
* @param string|null $vendorDir
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null)
{
@@ -110,7 +113,7 @@ class ClassLoader
}
/**
* @return array<string, list<string>>
* @return string[]
*/
public function getPrefixes()
{
@@ -122,7 +125,8 @@ class ClassLoader
}
/**
* @return array<string, list<string>>
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4()
{
@@ -130,7 +134,8 @@ class ClassLoader
}
/**
* @return list<string>
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs()
{
@@ -138,7 +143,8 @@ class ClassLoader
}
/**
* @return list<string>
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4()
{
@@ -146,7 +152,8 @@ class ClassLoader
}
/**
* @return array<string, string> Array of classname => path
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap()
{
@@ -154,7 +161,8 @@ class ClassLoader
}
/**
* @param array<string, string> $classMap Class to filename map
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/
@@ -171,25 +179,24 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
$paths,
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
$paths
(array) $paths
);
}
@@ -198,19 +205,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = $paths;
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$paths,
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
$paths
(array) $paths
);
}
}
@@ -219,9 +226,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
@@ -229,18 +236,17 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
$paths,
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
$paths
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -250,18 +256,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = $paths;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$paths,
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
$paths
(array) $paths
);
}
}
@@ -270,8 +276,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -288,8 +294,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -475,9 +481,9 @@ class ClassLoader
}
/**
* Returns the currently registered loaders keyed by their corresponding vendor directories.
* Returns the currently registered loaders indexed by their corresponding vendor directories.
*
* @return array<string, self>
* @return self[]
*/
public static function getRegisteredLoaders()
{

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer
class ComposerAutoloaderInite5f25043b4323431d48e7e46b04aa2c9
class ComposerAutoloaderInit270a670e4e35541a06419730c5cc18f6
{
private static $loader;
@@ -24,12 +24,12 @@ class ComposerAutoloaderInite5f25043b4323431d48e7e46b04aa2c9
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInite5f25043b4323431d48e7e46b04aa2c9', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit270a670e4e35541a06419730c5cc18f6', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInite5f25043b4323431d48e7e46b04aa2c9', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit270a670e4e35541a06419730c5cc18f6', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit270a670e4e35541a06419730c5cc18f6::getInitializer($loader));
$loader->register(true);

View File

@@ -4,7 +4,7 @@
namespace Composer\Autoload;
class ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9
class ComposerStaticInit270a670e4e35541a06419730c5cc18f6
{
public static $prefixLengthsPsr4 = array (
'C' =>
@@ -129,9 +129,9 @@ class ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInite5f25043b4323431d48e7e46b04aa2c9::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit270a670e4e35541a06419730c5cc18f6::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit270a670e4e35541a06419730c5cc18f6::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit270a670e4e35541a06419730c5cc18f6::$classMap;
}, null, ClassLoader::class);
}

View File

@@ -156,17 +156,17 @@
},
{
"name": "woocommerce/subscriptions-core",
"version": "6.9.0",
"version_normalized": "6.9.0.0",
"version": "7.0.0",
"version_normalized": "7.0.0.0",
"source": {
"type": "git",
"url": "https://github.com/Automattic/woocommerce-subscriptions-core.git",
"reference": "baf73669ba923b544aec87421282b753e277171f"
"reference": "80a6cff950b4d43932382ebda2bad801b35af229"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/baf73669ba923b544aec87421282b753e277171f",
"reference": "baf73669ba923b544aec87421282b753e277171f",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/80a6cff950b4d43932382ebda2bad801b35af229",
"reference": "80a6cff950b4d43932382ebda2bad801b35af229",
"shasum": ""
},
"require": {
@@ -179,7 +179,7 @@
"woocommerce/woocommerce-sniffs": "0.1.0",
"yoast/phpunit-polyfills": "1.1.0"
},
"time": "2024-03-28T05:12:56+00:00",
"time": "2024-04-11T01:44:20+00:00",
"type": "wordpress-plugin",
"extra": {
"phpcodesniffer-search-depth": 2
@@ -209,7 +209,7 @@
"description": "Sell products and services with recurring payments in your WooCommerce Store.",
"homepage": "https://github.com/Automattic/woocommerce-subscriptions-core",
"support": {
"source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/6.9.0",
"source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/7.0.0",
"issues": "https://github.com/Automattic/woocommerce-subscriptions-core/issues"
},
"install-path": "../woocommerce/subscriptions-core"

View File

@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'woocommerce/woocommerce-subscriptions',
'pretty_version' => 'dev-release/6.1.0',
'version' => 'dev-release/6.1.0',
'reference' => 'a609ac6f082f5fff09d0059eebcc48aa11229f58',
'pretty_version' => 'dev-release/6.2.0',
'version' => 'dev-release/6.2.0',
'reference' => '6c5d3d921f40709889b3f583726869f2fa95877f',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -32,18 +32,18 @@
),
),
'woocommerce/subscriptions-core' => array(
'pretty_version' => '6.9.0',
'version' => '6.9.0.0',
'reference' => 'baf73669ba923b544aec87421282b753e277171f',
'pretty_version' => '7.0.0',
'version' => '7.0.0.0',
'reference' => '80a6cff950b4d43932382ebda2bad801b35af229',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../woocommerce/subscriptions-core',
'aliases' => array(),
'dev_requirement' => false,
),
'woocommerce/woocommerce-subscriptions' => array(
'pretty_version' => 'dev-release/6.1.0',
'version' => 'dev-release/6.1.0',
'reference' => 'a609ac6f082f5fff09d0059eebcc48aa11229f58',
'pretty_version' => 'dev-release/6.2.0',
'version' => 'dev-release/6.2.0',
'reference' => '6c5d3d921f40709889b3f583726869f2fa95877f',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

@@ -1,5 +1,14 @@
*** WooCommerce Subscriptions Core Changelog ***
= 7.0.0 - 2024-04-11 =
* Fix - Update the failing payment method on a subscription when customers successfully pay for a failed renewal order via the block checkout.
* Fix - Resolved an issue that would cause subscriptions to be directly cancelled by the WooCommerce process of automatically cancelling unpaid orders in-line with the hold stock setting.
* Fix - Prevent duplicate status transition notes on subscriptions and potential infinite loops when processing subscription status transitions.
* Fix - Resolved an issue that could lead to "Undefined array key 'order-received'" errors.
* Fix - Resolved errors that could occur when paying for renewal orders via the checkout when the store has custom checkout fields.
* Fix - Resolved database errors that would occur when ordering the subscriptions list table by the 'Last order date' on sites with HPOS enabled.
* Dev - Introduced a new filter ('wcs_setup_cart_for_subscription_initial_payment') to enable third-party plugins to use the pay-for-order flow to complete a subscription's initial payment.
= 6.9.0 - 2024-03-28 =
* Fix - Resolved an issue where discounts, when reapplied to failed or manual subscription order payments, would incorrectly account for inclusive tax.
* Fix - Resolved an issue that could cause an empty error notice to appear on the My Account > Payment methods page when a customer attempted to delete a token used by subscriptions.

View File

@@ -1811,9 +1811,7 @@ class WCS_Admin_Post_Types {
$query_order = strtoupper( $args['order'] );
// fields and order are identical in both cases
$pieces['fields'] .= ', COALESCE(lp.last_payment, orders.date_created_gmt, 0) as lp';
$pieces['orderby'] = "CAST(lp AS DATETIME) {$query_order}";
$pieces['orderby'] = "COALESCE(lp.last_payment, parent_order.date_created_gmt, 0) {$query_order}";
return $pieces;
}
@@ -1841,7 +1839,7 @@ class WCS_Admin_Post_Types {
WHERE order_meta.meta_key = '_subscription_renewal'
GROUP BY order_meta.meta_value) lp
ON {$order_table}.id = lp.meta_value
LEFT JOIN {$order_table} orders on {$order_table}.parent_order_id = orders.ID";
LEFT JOIN {$order_table} as parent_order on {$order_table}.parent_order_id = parent_order.ID";
return $pieces;
}
@@ -1866,24 +1864,22 @@ class WCS_Admin_Post_Types {
$table_name = substr( "{$wpdb->prefix}tmp_{$session}_lastpayment", 0, 64 );
// Create a temporary table, drop the previous one.
$wpdb->query( $wpdb->prepare( 'DROP TEMPORARY TABLE IF EXISTS %s', $table_name ) );
//phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$wpdb->query( "DROP TEMPORARY TABLE IF EXISTS {$table_name}" );
$wpdb->query(
$wpdb->prepare(
"CREATE TEMPORARY TABLE %s (id INT PRIMARY KEY, last_payment DATETIME) AS
SELECT order_meta.meta_value as id, MAX( orders.date_created_gmt ) as last_payment FROM %s order_meta
LEFT JOIN %s as orders ON orders.id = order_meta.order_id
WHERE order_meta.meta_key = '_subscription_renewal'
GROUP BY order_meta.meta_value",
$table_name,
$meta_table,
$order_table
)
"CREATE TEMPORARY TABLE {$table_name} (id INT PRIMARY KEY, last_payment DATETIME) AS
SELECT order_meta.meta_value as id, MAX( orders.date_created_gmt ) as last_payment
FROM {$meta_table} as order_meta
LEFT JOIN {$order_table} as orders ON orders.id = order_meta.order_id
WHERE order_meta.meta_key = '_subscription_renewal'
GROUP BY order_meta.meta_value"
);
//phpcs:enable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$pieces['join'] .= "LEFT JOIN {$table_name} lp
$pieces['join'] .= "LEFT JOIN {$table_name} as lp
ON {$order_table}.id = lp.id
LEFT JOIN {$order_table} orders on {$order_table}.parent_order_id = orders.id";
LEFT JOIN {$order_table} as parent_order on {$order_table}.parent_order_id = parent_order.id";
return $pieces;
}

View File

@@ -92,6 +92,18 @@ class WC_Subscription extends WC_Order {
'suspension_count',
);
/**
* The meta key used to flag that the subscription's payment failed.
*
* Stored on the renewal order itself.
*
* Payments via the Block checkout transition the order status from failed to pending and then to processing.
* This makes it impossible for us to know if the order was initially failed. This meta key flags that the order was initially failed.
*
* @var string
*/
const RENEWAL_FAILED_META_KEY = '_failed_renewal_order';
/**
* Initializes a specific subscription if the ID is passed, otherwise a new and empty instance of a subscription.
*
@@ -564,6 +576,9 @@ class WC_Subscription extends WC_Order {
// Use local copy of status transition value.
$status_transition = $this->status_transition;
// Reset status transition variable.
$this->status_transition = false;
// If we're not currently in the midst of a status transition, bail early.
if ( ! $status_transition ) {
return;
@@ -605,9 +620,6 @@ class WC_Subscription extends WC_Order {
);
$this->add_order_note( __( 'Error during subscription status transition.', 'woocommerce-subscriptions' ) . ' ' . $e->getMessage() );
}
// This has run, so reset status transition variable
$this->status_transition = false;
}
/**
@@ -1862,6 +1874,8 @@ class WC_Subscription extends WC_Order {
do_action( 'woocommerce_subscription_payment_complete', $this );
if ( false !== $last_order && wcs_order_contains_renewal( $last_order ) ) {
$last_order->delete_meta_data( self::RENEWAL_FAILED_META_KEY );
$last_order->save();
do_action( 'woocommerce_subscription_renewal_payment_complete', $this, $last_order );
}
}
@@ -1876,10 +1890,17 @@ class WC_Subscription extends WC_Order {
// Make sure the last order's status is set to failed
$last_order = $this->get_last_order( 'all', 'any' );
if ( false !== $last_order && false === $last_order->has_status( 'failed' ) ) {
remove_filter( 'woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment' );
$last_order->update_status( 'failed' );
add_filter( 'woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment', 10, 3 );
if ( false !== $last_order ) {
$last_order->update_meta_data( self::RENEWAL_FAILED_META_KEY, wc_bool_to_string( true ) );
if ( false === $last_order->has_status( 'failed' ) ) {
remove_filter( 'woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment' );
$last_order->update_status( 'failed' );
add_filter( 'woocommerce_order_status_changed', 'WC_Subscriptions_Renewal_Order::maybe_record_subscription_payment', 10, 3 );
} else {
// If we didn't update the status, save the order to make sure our self::RENEWAL_FAILED_META_KEY meta data is saved.
$last_order->save();
}
}
// Log payment failure on order

View File

@@ -16,7 +16,7 @@ class WC_Subscriptions_Core_Plugin {
* The version of subscriptions-core library.
* @var string
*/
protected $library_version = '6.9.0'; // WRCS: DEFINED_VERSION.
protected $library_version = '7.0.0'; // WRCS: DEFINED_VERSION.
/**
* The subscription scheduler instance.

View File

@@ -57,6 +57,8 @@ class WC_Subscriptions_Manager {
// Do the same thing for WordPress networks
add_action( 'wpmu_delete_user', __CLASS__ . '::trash_users_subscriptions_for_network' );
add_filter( 'woocommerce_cancel_unpaid_order', [ __CLASS__, 'exclude_subscription_from_order_cleanup' ], 10, 2 );
}
/**
@@ -605,6 +607,22 @@ class WC_Subscriptions_Manager {
do_action( 'pending_subscription_created_for_order', $order, $product_id );
}
/**
* Excludes subscriptions from the order cleanup process.
*
* @param bool $should_cancel Whether the order should be cancelled.
* @param WC_Order $order The order object.
*
* @return bool Whether the order should be cancelled.
*/
public static function exclude_subscription_from_order_cleanup( $should_cancel, $order ) {
if ( $should_cancel && 'shop_subscription' === $order->get_type() ) {
$should_cancel = false;
}
return $should_cancel;
}
/**
* Creates subscriptions against a users account with a status of pending when a user creates
* an order containing subscriptions.

View File

@@ -127,7 +127,7 @@ class WC_Subscriptions_Renewal_Order {
if ( $order_completed && ! $subscription->has_status( wcs_get_subscription_ended_statuses() ) && ! $subscription->has_status( 'active' ) ) {
// Included here because calling payment_complete sets the retry status to 'cancelled'
$is_failed_renewal_order = 'failed' === $orders_old_status;
$is_failed_renewal_order = 'failed' === $orders_old_status || wc_string_to_bool( $order->get_meta( WC_Subscription::RENEWAL_FAILED_META_KEY, true ) );
$is_failed_renewal_order = apply_filters( 'woocommerce_subscriptions_is_failed_renewal_order', $is_failed_renewal_order, $order_id, $orders_old_status );
if ( $order_needed_payment ) {

View File

@@ -52,6 +52,26 @@ class WCS_Cart_Initial_Payment extends WCS_Cart_Renewal {
return;
}
/**
* Filter whether to set up the cart during the pay-for-order payment flow.
*
* Allows developers to bypass cart setup for the pay-for-order payment flow.
* This is intended for situations in which re-creating the cart will result in
* the loss of order data.
*
* @since 6.2.0
*
* @param bool $recreate_cart Whether to recreate the initial payment order. Default true.
* @param WC_Order $order The order object.
* @param string $order_key The order key.
* @param int $order_id The order ID.
*/
$recreate_cart = apply_filters( "wcs_setup_cart_for_{$this->cart_item_key}", true, $order, $order_key, $order_id );
if ( ! $recreate_cart ) {
return;
}
if ( ! is_user_logged_in() ) {
// Allow the customer to login first and then redirect them back.
$redirect = add_query_arg(

View File

@@ -494,33 +494,44 @@ class WCS_Cart_Renewal {
* Returns address details from the renewal order if the checkout is for a renewal.
*
* @param string $value Default checkout field value.
* @param string $key The checkout form field name/key
* @param string $key The checkout form field name/key.
*
* @return string $value Checkout field value.
*/
public function checkout_get_value( $value, $key ) {
// Only hook in after WC()->checkout() has been initialised
if ( $this->cart_contains() && did_action( 'woocommerce_checkout_init' ) > 0 ) {
// Only hook in after WC()->checkout() has been initialised.
if ( ! $this->cart_contains() || did_action( 'woocommerce_checkout_init' ) <= 0 ) {
return $value;
}
// Guard against the fake WC_Checkout singleton, see https://github.com/woocommerce/woocommerce-subscriptions/issues/427#issuecomment-260763250
remove_filter( 'woocommerce_checkout_get_value', array( &$this, 'checkout_get_value' ), 10 );
// Get the most specific order object, which will be the renewal order for renewals, initial order for initial payments, or a subscription for switches/resubscribes.
$order = $this->get_order();
if ( is_callable( array( WC()->checkout(), 'get_checkout_fields' ) ) ) { // WC 3.0+
$address_fields = array_merge( WC()->checkout()->get_checkout_fields( 'billing' ), WC()->checkout()->get_checkout_fields( 'shipping' ) );
} else {
$address_fields = array_merge( WC()->checkout()->checkout_fields['billing'], WC()->checkout()->checkout_fields['shipping'] );
}
if ( ! $order ) {
return $value;
}
add_filter( 'woocommerce_checkout_get_value', array( &$this, 'checkout_get_value' ), 10, 2 );
$address_fields = array_merge(
WC()->countries->get_address_fields(
$order->get_billing_country(),
'billing_'
),
WC()->countries->get_address_fields(
$order->get_shipping_country(),
'shipping_'
)
);
if ( array_key_exists( $key, $address_fields ) && false !== ( $item = $this->cart_contains() ) ) {
// Generate the address getter method for the key.
$getter = "get_{$key}";
// Get the most specific order object, which will be the renewal order for renewals, initial order for initial payments, or a subscription for switches/resubscribes
$order = $this->get_order( $item );
if ( array_key_exists( $key, $address_fields ) && is_callable( [ $order, $getter ] ) ) {
$order_value = call_user_func( [ $order, $getter ] );
if ( ( $order_value = wcs_get_objects_property( $order, $key ) ) ) {
$value = $order_value;
}
// Given this is fetching the value for a checkout field, we need to ensure the value is a scalar.
if ( is_scalar( $order_value ) ) {
$value = $order_value;
}
}

View File

@@ -511,11 +511,11 @@ class WCS_PayPal {
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.5.3
*/
public static function maybe_add_payment_lock() {
if ( ! wcs_is_order_received_page() ) {
global $wp;
if ( ! isset( $wp->query_vars['order-received'] ) ) {
return;
}
global $wp;
$order = wc_get_order( absint( $wp->query_vars['order-received'] ) );
if ( $order && self::instance()->get_id() === $order->get_payment_method() && $order->needs_payment() && ! self::are_reference_transactions_enabled() && wcs_order_contains_subscription( $order, array( 'parent' ) ) ) {

View File

@@ -6,5 +6,5 @@
* Author: Automattic
* Author URI: https://woocommerce.com/
* Requires WP: 5.6
* Version: 6.9.0
* Version: 7.0.0
*/

View File

@@ -5,7 +5,8 @@
* Description: Sell products and services with recurring payments in your WooCommerce Store.
* Author: WooCommerce
* Author URI: https://woocommerce.com/
* Version: 6.1.0
* Version: 6.2.0
* Requires Plugins: woocommerce
*
* WC requires at least: 7.7.0
* WC tested up to: 8.7.0
@@ -77,7 +78,7 @@ class WC_Subscriptions {
public static $plugin_file = __FILE__;
/** @var string */
public static $version = '6.1.0'; // WRCS: DEFINED_VERSION.
public static $version = '6.2.0'; // WRCS: DEFINED_VERSION.
/** @var string */
public static $wc_minimum_supported_version = '7.7';