Updates to 6.6.0

This commit is contained in:
WooCommerce
2024-08-22 10:15:00 +00:00
parent b2a4dd8022
commit a8df935923
25 changed files with 404 additions and 227 deletions

View File

@@ -1,5 +1,15 @@
*** WooCommerce Subscriptions Changelog ***
2024-08-22 - version 6.6.0
* Fix: Resolve duplicate subscription creation and PHP warning when switching subscriptions with Prepaid for WooCommerce Subscriptions plugin active.
* Fix: Switch calculations now exclude previous switch orders with a checkout-draft status.
* Dev: Introduce new parameter to WC_Subscription::get_last_order() to enable filtering out orders with specific statuses.
* Update: Schedule subscription-related events with a priority of 1 to allow for earlier execution within the Action Scheduler.
* Fix: Ensure admin notices are displayed after performing bulk actions on subscriptions when HPOS is enabled.
* Fix: Add a year to the next renewal date billing interval is 12 months or more for a synced subscription.
* Dev: Added filter to enable overriding the total paid for current switch period.
* Dev: Updated subscriptions-core to 7.4.1.
2024-07-16 - version 6.5.0
* Add: Include trial_period, suspension_count, and requires_manual_renewal in the REST API response for subscriptions.
* Update: When a renewal order's payment is skipped, include the order's current status in the note to help troubleshooting.

View File

@@ -60,7 +60,7 @@ class WCS_Admin_Reports {
// translators: placeholders $1 and $2 are opening <a> tags linking to the WooCommerce documentation on HPOS and data synchronization. Placeholder $3 is a closing link (<a>) tag.
__( 'Subscription reports are incompatible with the %1$sWooCommerce data storage features%3$s enabled on your store. Please enable %2$stable synchronization%3$s if you wish to use subscription reports.', 'woocommerce-subscriptions' ),
'<a href="https://woocommerce.com/document/high-performance-order-storage/">',
'<a href="https://woocommerce.com/document/high-performance-order-storage/#section-4">',
'<a href="https://woocommerce.com/document/high-performance-order-storage/#synchronization">',
'</a>'
)
)

View File

@@ -40,7 +40,7 @@ class WCS_Manual_Renewal_Manager {
'default' => 'no',
'type' => 'checkbox',
// translators: placeholders are opening and closing link tags
'desc_tip' => sprintf( __( 'With manual renewals, a customer\'s subscription is put on-hold until they login and pay to renew it. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="http://docs.woocommerce.com/document/subscriptions/store-manager-guide/#accept-manual-renewals">', '</a>' ),
'desc_tip' => sprintf( __( 'With manual renewals, a customer\'s subscription is put on-hold until they login and pay to renew it. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="https://woocommerce.com/document/subscriptions/store-manager-guide/#accept-manual-renewals">', '</a>' ),
'checkboxgroup' => 'start',
'show_if_checked' => 'option',
),
@@ -51,7 +51,7 @@ class WCS_Manual_Renewal_Manager {
'default' => 'no',
'type' => 'checkbox',
// translators: placeholders are opening and closing link tags
'desc_tip' => sprintf( __( 'If you don\'t want new subscription purchases to automatically charge renewal payments, you can turn off automatic payments. Existing automatic subscriptions will continue to charge customers automatically. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="http://docs.woocommerce.com/document/subscriptions/store-manager-guide/#turn-off-automatic-payments">', '</a>' ),
'desc_tip' => sprintf( __( 'If you don\'t want new subscription purchases to automatically charge renewal payments, you can turn off automatic payments. Existing automatic subscriptions will continue to charge customers automatically. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="https://woocommerce.com/document/subscriptions/store-manager-guide/#turn-off-automatic-payments">', '</a>' ),
'checkboxgroup' => 'end',
'show_if_checked' => 'yes',
),

View File

@@ -86,7 +86,7 @@ class WCS_Upgrade_Notice_Manager {
'description' => sprintf(
// translators: 1-3: opening/closing <a> tags - link to documentation.
__( 'Webhook and REST API users can now use v3 subscription endpoints. Click here to %1$slearn more%2$s about the REST API and check out the technical API docs %3$shere%2$s.', 'woocommerce-subscriptions' ),
'<a href="https://docs.woocommerce.com/document/woocommerce-rest-api/">',
'<a href="https://woocommerce.com/document/woocommerce-rest-api/">',
'</a>',
'<a href="https://woocommerce.github.io/subscriptions-rest-api-docs/">'
),
@@ -96,7 +96,7 @@ class WCS_Upgrade_Notice_Manager {
'description' => sprintf(
// translators: 1-2: opening/closing <a> tags - link to documentation.
__( 'Subscriptions is now compatible with the WooCommerce cart and checkout blocks. You can learn more about the compatibility status of the cart & checkout blocks %1$shere%2$s.', 'woocommerce-subscriptions' ),
'<a href="https://docs.woocommerce.com/document/cart-checkout-blocks-support-status/">', '</a>'
'<a href="https://woocommerce.com/document/woocommerce-store-editing/customizing-cart-and-checkout/#compatible-extensions">', '</a>'
),
),
);

View File

@@ -65,7 +65,7 @@ class WCS_Early_Renewal_Manager {
/* translators: 1-2: opening/closing <strong> tags , 2-3: opening/closing tags for a link to docs on early renewal. */
__( 'Allow customers to bypass the checkout and renew their subscription early from their %1$sMy Account > View Subscription%2$s page. %3$sLearn more.%4$s', 'woocommerce-subscriptions' ),
'<strong>', '</strong>',
'<a href="https://docs.woocommerce.com/document/subscriptions/early-renewal/">', '</a>'
'<a href="https://woocommerce.com/document/subscriptions/early-renewal/">', '</a>'
),
'default' => 'no',
'type' => 'checkbox',

View File

@@ -149,7 +149,7 @@ class WC_Subscriptions_Payment_Gateways extends WC_Subscriptions_Core_Payment_Ga
public static function add_recurring_payment_gateway_information( $settings, $option_prefix ) {
$settings[] = array(
// translators: $1-$2: opening and closing tags. Link to documents->payment gateways, 3$-4$: opening and closing tags. Link to WooCommerce extensions shop page
'desc' => sprintf( __( 'Find new gateways that %1$ssupport automatic subscription payments%2$s in the official %3$sWooCommerce Marketplace%4$s.', 'woocommerce-subscriptions' ), '<a href="' . esc_url( 'http://docs.woocommerce.com/document/subscriptions/payment-gateways/' ) . '">', '</a>', '<a href="' . esc_url( 'http://www.woocommerce.com/product-category/woocommerce-extensions/' ) . '">', '</a>' ),
'desc' => sprintf( __( 'Find new gateways that %1$ssupport automatic subscription payments%2$s in the official %3$sWooCommerce Marketplace%4$s.', 'woocommerce-subscriptions' ), '<a href="' . esc_url( 'https://woocommerce.com/document/subscriptions/payment-gateways/' ) . '">', '</a>', '<a href="' . esc_url( 'http://www.woocommerce.com/product-category/woocommerce-extensions/' ) . '">', '</a>' ),
'id' => $option_prefix . '_payment_gateways_additional',
'type' => 'informational',
);

View File

@@ -165,7 +165,7 @@ class WCS_Retry_Admin {
'default' => 'no',
'type' => 'checkbox',
// translators: 1,2: opening/closing link tags (to documentation).
'desc_tip' => sprintf( __( 'Attempt to recover recurring revenue that would otherwise be lost due to payment methods being declined only temporarily. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="https://docs.woocommerce.com/document/subscriptions/failed-payment-retry/">', '</a>' ),
'desc_tip' => sprintf( __( 'Attempt to recover recurring revenue that would otherwise be lost due to payment methods being declined only temporarily. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="https://woocommerce.com/document/subscriptions/failed-payment-retry/">', '</a>' ),
),
) );

View File

@@ -145,6 +145,8 @@ class WC_Subscriptions_Switcher {
// Override the add to cart text when switch args are present.
add_filter( 'woocommerce_product_single_add_to_cart_text', array( __CLASS__, 'display_switch_add_to_cart_text' ), 10, 1 );
add_filter( 'woocommerce_subscriptions_calculated_total', [ __CLASS__, 'remove_handled_switch_recurring_carts' ], 100, 1 );
}
/**
@@ -382,7 +384,7 @@ class WC_Subscriptions_Switcher {
'name' => __( 'Switching', 'woocommerce-subscriptions' ),
'type' => 'title',
// translators: placeholders are opening and closing link tags
'desc' => sprintf( __( 'Allow subscribers to switch (upgrade or downgrade) between different subscriptions. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="' . esc_url( 'http://docs.woocommerce.com/document/subscriptions/switching-guide/' ) . '">', '</a>' ),
'desc' => sprintf( __( 'Allow subscribers to switch (upgrade or downgrade) between different subscriptions. %1$sLearn more%2$s.', 'woocommerce-subscriptions' ), '<a href="' . esc_url( 'https://woocommerce.com/document/subscriptions/switching-guide/' ) . '">', '</a>' ),
'id' => WC_Subscriptions_Admin::$option_prefix . '_switch_settings',
),
array(
@@ -1105,7 +1107,15 @@ class WC_Subscriptions_Switcher {
}
}
$switch_order_data[ $subscription->get_id() ]['switches'][ $cart_item['subscription_switch']['order_line_item_id'] ] = $switched_item_data;
// Obtain the new order item id from the cart item switch data.
if ( isset( $cart_item['subscription_switch']['order_line_item_id'] ) ) {
$new_order_item_id = $cart_item['subscription_switch']['order_line_item_id'];
} else {
$new_order_item_id = wc_get_order_item_meta( $cart_item['subscription_switch']['item_id'], '_switched_subscription_new_item_id', true );
}
// Store the switching data for this item.
$switch_order_data[ $subscription->get_id() ]['switches'][ $new_order_item_id ] = $switched_item_data;
// If the old subscription has just one item, we can safely update its billing schedule
if ( $can_update_existing_subscription ) {
@@ -2982,4 +2992,72 @@ class WC_Subscriptions_Switcher {
}
}
/**
* Removes subscription items from recurring carts which have been handled.
*
* It's possible that after we've processed the subscription switches and removed any recurring carts that shouldn't lead to new subscriptions,
* that someone could call WC()->cart->calculate_totals() and that would lead us to recreate all the recurring carts after we've already processed them.
*
* This method runs after subscription recurring carts have been created and removes any recurring carts which have been handled.
*
* @param float $total The total amount of the cart.
* @return float $total. The total amount of the cart. This is a pass-through method and doesn't modify the total.
*/
public static function remove_handled_switch_recurring_carts( $total ) {
if ( ! isset( WC()->cart->recurring_carts ) ) {
return $total;
}
// We only want to remove the recurring cart if the switch order has been processed.
if ( ! did_action( 'woocommerce_subscription_checkout_switch_order_processed' ) ) {
return $total;
}
foreach ( WC()->cart->recurring_carts as $recurring_cart_key => $recurring_cart ) {
// Remove any items from the recurring cart which have been handled.
foreach ( $recurring_cart->get_cart() as $cart_item_key => $cart_item ) {
if ( ! isset( $cart_item['subscription_switch'] ) ) {
continue;
}
$subscription = wcs_get_subscription( $cart_item['subscription_switch']['subscription_id'] );
$switch_order = $subscription->get_last_order( 'all', 'switch' );
if ( empty( $switch_order ) ) {
continue;
}
$switch_order_data = wcs_get_objects_property( $switch_order, 'subscription_switch_data' );
// Skip if the switch order data is not set.
if ( ! isset( $switch_order_data[ $subscription->get_id() ]['switches'] ) ) {
continue;
}
$subscription_switch_data = $switch_order_data[ $subscription->get_id() ]['switches'];
$switched_subscription_item_id = $cart_item['subscription_switch']['item_id'];
foreach ( $subscription_switch_data as $switch_data ) {
// We're only interested in cases where there's a straight swap of items. ie there's a remove and an add.
if ( ! isset( $switch_data['remove_line_item'], $switch_data['add_line_item'] ) ) {
continue;
}
if ( $switch_data['remove_line_item'] === $switched_subscription_item_id ) {
unset( WC()->cart->recurring_carts[ $recurring_cart_key ]->cart_contents[ $cart_item_key ] );
}
}
}
// If the recurring cart is now empty, remove it.
if ( empty( WC()->cart->recurring_carts[ $recurring_cart_key ]->cart_contents ) ) {
unset( WC()->cart->recurring_carts[ $recurring_cart_key ] );
}
}
return $total;
}
}

View File

@@ -24,7 +24,7 @@ class WCS_Switch_Cart_Item {
/**
* The existing subscription line item being switched.
* @var WC_Order_Item_Product
* @var WC_Order_Item
*/
public $existing_item;
@@ -119,7 +119,7 @@ class WCS_Switch_Cart_Item {
*
* @param array $cart_item The cart item.
* @param WC_Subscription $subscription The subscription being switched.
* @param WC_Order_Item_Product $existing_item The subscription line item being switched.
* @param WC_Order_Item $existing_item The subscription line item being switched.
*
* @throws Exception If WC_Subscriptions_Product::get_expiration_date() returns an invalid date.
*/
@@ -263,7 +263,7 @@ class WCS_Switch_Cart_Item {
public function get_total_paid_for_current_period() {
if ( ! isset( $this->total_paid_for_current_period ) ) {
// If the last order was a switch with a fully reduced pre-paid term, the amount the cutomer has paid is just the total in that order.
// If the last order was a switch with a fully reduced pre-paid term, the amount the customer has paid is just the total in that order.
if ( $this->is_switch_after_fully_reduced_prepaid_term() ) {
$this->total_paid_for_current_period = WC_Subscriptions_Switcher::calculate_total_paid_since_last_order( $this->subscription, $this->existing_item, 'exclude_sign_up_fees', array( $this->get_last_switch_order() ) );
} else {
@@ -271,7 +271,7 @@ class WCS_Switch_Cart_Item {
}
}
return $this->total_paid_for_current_period;
return apply_filters( 'wcs_switch_total_paid_for_current_period', $this->total_paid_for_current_period, $this->subscription, $this->existing_item );
}
/**
@@ -446,7 +446,7 @@ class WCS_Switch_Cart_Item {
static $switch_order = null;
if ( ! $switch_order ) {
$switch_order = $this->subscription->get_last_order( 'all', 'switch' );
$switch_order = $this->subscription->get_last_order( 'all', 'switch', [ 'checkout-draft' ] );
}
return $switch_order;
@@ -459,12 +459,12 @@ class WCS_Switch_Cart_Item {
*
* For example:
* - Original purchase of a $70 / week subscription.
* - 5 days into the subscription the customer switches to a $120 / 3 days. The lower freqency triggers the pre-paid term to be reduced.
* - 5 days into the subscription the customer switches to a $120 / 3 days. The lower frequency triggers the pre-paid term to be reduced.
* - The $70 paid at $40 a day only entitles the customer to 1.75 days.
* - Because they are already 5 days into the subscription, that $70 is fully absorbed at the new price and no time is 'owed'.
* - The subscription starts today and the customer pays full price.
*
* @see https://docs.woocommerce.com/document/subscriptions/switching-guide/#section-11
* @see https://woocommerce.com/document/subscriptions/switching-guide/switching-process-and-costs/#upgrades
* @see WCS_Switch_Totals_Calculator::reduce_prepaid_term()
*
* @since 3.0.7
@@ -482,7 +482,7 @@ class WCS_Switch_Cart_Item {
$switch_paid_date = $last_switch_order->get_date_paid();
// If the last switch order occured after the last payment order (parent or renewal)
// If the last switch order occurred before the last payment order (parent or renewal), then the last order wasn't a switch.
if ( $switch_paid_date->getTimestamp() < $this->get_last_order_paid_time() ) {
$this->is_switch_after_fully_reduced_prepaid_term = false;
return false;

View File

@@ -2,38 +2,43 @@
# This file is distributed under the same license as the WooCommerce Subscriptions plugin.
msgid ""
msgstr ""
"Project-Id-Version: WooCommerce Subscriptions 6.5.0\n"
"Project-Id-Version: WooCommerce Subscriptions 6.6.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-07-16T06:24:54+00:00\n"
"POT-Creation-Date: 2024-08-22T07:20:55+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.9.0\n"
"X-Generator: WP-CLI 2.11.0\n"
"X-Domain: woocommerce-subscriptions\n"
#. Plugin Name of the plugin
#: woocommerce-subscriptions.php
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:40
msgid "WooCommerce Subscriptions"
msgstr ""
#. Plugin URI of the plugin
#: woocommerce-subscriptions.php
msgid "https://www.woocommerce.com/products/woocommerce-subscriptions/"
msgstr ""
#. Description of the plugin
#: woocommerce-subscriptions.php
msgid "Sell products and services with recurring payments in your WooCommerce Store."
msgstr ""
#. Author of the plugin
#: woocommerce-subscriptions.php
#: includes/admin/class-wcs-admin-reports.php:136
#: includes/admin/reports/class-wcs-report-cache-manager.php:262
msgid "WooCommerce"
msgstr ""
#. Author URI of the plugin
#: woocommerce-subscriptions.php
msgid "https://woocommerce.com/"
msgstr ""
@@ -1683,226 +1688,226 @@ msgstr ""
msgid "[{site_title}] Automatic payment failed for {order_number}, retry scheduled to run {retry_time}"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:195
#: includes/switching/class-wc-subscriptions-switcher.php:197
msgid "You have a subscription to this product. Choosing a new subscription will replace your existing subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:197
#: includes/switching/class-wc-subscriptions-switcher.php:199
msgid "Choose a new subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:237
#: includes/switching/class-wc-subscriptions-switcher.php:1244
#: includes/switching/class-wc-subscriptions-switcher.php:239
#: includes/switching/class-wc-subscriptions-switcher.php:1254
msgid "Your cart contained an invalid subscription switch request. It has been removed."
msgid_plural "Your cart contained invalid subscription switch requests. They have been removed."
msgstr[0] ""
msgstr[1] ""
#: includes/switching/class-wc-subscriptions-switcher.php:279
#: includes/switching/class-wc-subscriptions-switcher.php:281
msgid "You have already subscribed to this product and it is limited to one per customer. You can not purchase the product again."
msgstr ""
#. translators: 1$: is the "You have already subscribed to this product" notice, 2$-4$: opening/closing link tags, 3$: an order number
#: includes/switching/class-wc-subscriptions-switcher.php:288
#: includes/switching/class-wc-subscriptions-switcher.php:290
msgid "%1$s Complete payment on %2$sOrder %3$s%4$s to be able to change your subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:382
#: includes/switching/class-wc-subscriptions-switcher.php:384
msgid "Switching"
msgstr ""
#. translators: placeholders are opening and closing link tags
#: includes/switching/class-wc-subscriptions-switcher.php:385
#: includes/switching/class-wc-subscriptions-switcher.php:387
msgid "Allow subscribers to switch (upgrade or downgrade) between different subscriptions. %1$sLearn more%2$s."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:393
#: includes/switching/class-wc-subscriptions-switcher.php:395
msgid "Prorate Recurring Payment"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:394
#: includes/switching/class-wc-subscriptions-switcher.php:396
msgid "When switching to a subscription with a different recurring payment or billing period, should the price paid for the existing billing period be prorated when switching to the new subscription?"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:402
#: includes/switching/class-wc-subscriptions-switcher.php:436
#: includes/switching/class-wc-subscriptions-switcher.php:404
#: includes/switching/class-wc-subscriptions-switcher.php:438
msgctxt "when to allow a setting"
msgid "Never"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:403
#: includes/switching/class-wc-subscriptions-switcher.php:405
msgctxt "when to prorate recurring fee when switching"
msgid "For Upgrades of Virtual Subscription Products Only"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:404
#: includes/switching/class-wc-subscriptions-switcher.php:406
msgctxt "when to prorate recurring fee when switching"
msgid "For Upgrades of All Subscription Products"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:405
#: includes/switching/class-wc-subscriptions-switcher.php:407
msgctxt "when to prorate recurring fee when switching"
msgid "For Upgrades & Downgrades of Virtual Subscription Products Only"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:406
#: includes/switching/class-wc-subscriptions-switcher.php:408
msgctxt "when to prorate recurring fee when switching"
msgid "For Upgrades & Downgrades of All Subscription Products"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:411
#: includes/switching/class-wc-subscriptions-switcher.php:413
msgid "Prorate Sign up Fee"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:412
#: includes/switching/class-wc-subscriptions-switcher.php:414
msgid "When switching to a subscription with a sign up fee, you can require the customer pay only the gap between the existing subscription's sign up fee and the new subscription's sign up fee (if any)."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:420
msgctxt "when to prorate signup fee when switching"
msgid "Never (do not charge a sign up fee)"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:421
msgctxt "when to prorate signup fee when switching"
msgid "Never (charge the full sign up fee)"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:422
msgctxt "when to prorate signup fee when switching"
msgid "Never (do not charge a sign up fee)"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:423
msgctxt "when to prorate signup fee when switching"
msgid "Never (charge the full sign up fee)"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:424
msgctxt "when to prorate signup fee when switching"
msgid "Always"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:427
#: includes/switching/class-wc-subscriptions-switcher.php:429
msgid "Prorate Subscription Length"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:428
#: includes/switching/class-wc-subscriptions-switcher.php:430
msgid "When switching to a subscription with a length, you can take into account the payments already completed by the customer when determining how many payments the subscriber needs to make for the new subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:437
#: includes/switching/class-wc-subscriptions-switcher.php:439
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:226
msgctxt "when to prorate first payment / subscription length"
msgid "For Virtual Subscription Products Only"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:438
#: includes/switching/class-wc-subscriptions-switcher.php:440
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:227
msgctxt "when to prorate first payment / subscription length"
msgid "For All Subscription Products"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:443
#: includes/switching/class-wc-subscriptions-switcher.php:445
msgid "Switch Button Text"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:444
#: includes/switching/class-wc-subscriptions-switcher.php:446
msgid "Customise the text displayed on the button next to the subscription on the subscriber's account page. The default is \"Switch Subscription\", but you may wish to change this to \"Upgrade\" or \"Change Subscription\"."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:448
#: includes/switching/class-wc-subscriptions-switcher.php:550
#: includes/switching/class-wc-subscriptions-switcher.php:2683
#: includes/switching/class-wc-subscriptions-switcher.php:450
#: includes/switching/class-wc-subscriptions-switcher.php:552
#: includes/switching/class-wc-subscriptions-switcher.php:2693
msgid "Upgrade or Downgrade"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:487
#: includes/switching/class-wc-subscriptions-switcher.php:489
msgid "Allow Switching"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:494
#: includes/switching/class-wc-subscriptions-switcher.php:496
msgctxt "when to allow switching"
msgid "Between Subscription Variations"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:498
#: includes/switching/class-wc-subscriptions-switcher.php:500
msgctxt "when to allow switching"
msgid "Between Grouped Subscriptions"
msgstr ""
#. translators: %s: order number.
#: includes/switching/class-wc-subscriptions-switcher.php:1153
#: includes/switching/class-wc-subscriptions-switcher.php:1163
msgid "Switch order cancelled due to a new switch order being created #%s."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1372
#: includes/switching/class-wc-subscriptions-switcher.php:1382
msgid "You can only switch to a subscription product."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1378
#: includes/switching/class-wc-subscriptions-switcher.php:1388
msgid "We can not find your old subscription item."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1400
#: includes/switching/class-wc-subscriptions-switcher.php:1410
msgid "You can not switch to the same subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1447
#: includes/switching/class-wc-subscriptions-switcher.php:1457
msgid "You can not switch this subscription. It appears you do not own the subscription."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1488
#: includes/switching/class-wc-subscriptions-switcher.php:1498
msgid "There was an error locating the switch details."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1869
#: includes/switching/class-wc-subscriptions-switcher.php:1879
msgctxt "a switch type"
msgid "Downgrade"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1872
#: includes/switching/class-wc-subscriptions-switcher.php:1882
msgctxt "a switch type"
msgid "Upgrade"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1875
#: includes/switching/class-wc-subscriptions-switcher.php:1885
msgctxt "a switch type"
msgid "Crossgrade"
msgstr ""
#. translators: %1: product subtotal, %2: HTML span tag, %3: direction (upgrade, downgrade, crossgrade), %4: closing HTML span tag
#: includes/switching/class-wc-subscriptions-switcher.php:1880
#: includes/switching/class-wc-subscriptions-switcher.php:1890
msgctxt "product subtotal string"
msgid "%1$s %2$s(%3$s)%4$s"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1996
#: includes/switching/class-wc-subscriptions-switcher.php:2006
msgid "The original subscription item being switched cannot be found."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:1998
#: includes/switching/class-wc-subscriptions-switcher.php:2008
msgid "The item on the switch order cannot be found."
msgstr ""
#. translators: 1$: old item, 2$: new item when switching
#: includes/switching/class-wc-subscriptions-switcher.php:2009
#: includes/switching/class-wc-subscriptions-switcher.php:2019
msgctxt "used in order notes"
msgid "Customer switched from: %1$s to %2$s."
msgstr ""
#. translators: %s: new item name.
#: includes/switching/class-wc-subscriptions-switcher.php:2012
#: includes/switching/class-wc-subscriptions-switcher.php:2022
msgctxt "used in order notes"
msgid "Customer added %s."
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:2407
#: includes/switching/class-wc-subscriptions-switcher.php:2960
#: includes/switching/class-wc-subscriptions-switcher.php:2417
#: includes/switching/class-wc-subscriptions-switcher.php:2970
msgid "Switch Order"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:2422
#: includes/switching/class-wc-subscriptions-switcher.php:2975
#: includes/switching/class-wc-subscriptions-switcher.php:2432
#: includes/switching/class-wc-subscriptions-switcher.php:2985
msgid "Switched Subscription"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:2640
#: includes/switching/class-wc-subscriptions-switcher.php:2650
msgctxt "add to cart button text while switching a subscription"
msgid "Switch subscription"
msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:2824
#: includes/switching/class-wc-subscriptions-switcher.php:2834
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:223
msgctxt "Subscription status"
msgid "Switched"
@@ -2540,7 +2545,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:652
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2147
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2158
msgid "Via %s"
msgstr ""
@@ -2608,7 +2613,7 @@ msgid "None"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1174
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2129
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2140
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:170
msgid "Manual Renewal"
msgstr ""
@@ -3032,7 +3037,7 @@ msgstr ""
#. translators: %d: subscription ID.
#. translators: %d: order ID.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1451
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2570
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2581
msgid "Subscription #%d: "
msgstr ""
@@ -3052,55 +3057,55 @@ msgstr ""
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:2226
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2237
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:834
msgid "Payment method meta must be an array."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2462
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2473
msgid "Invalid format. First parameter needs to be an array."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2466
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2477
msgid "Invalid data. First parameter was empty when passed to update_dates()."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2473
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2484
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:2500
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2511
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:2538
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2549
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:2544
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2555
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:2549
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2560
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:2555
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2566
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:2560
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2571
msgid "The %s date must occur after the start date."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2590
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2601
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-checkout.php:348
msgid "Backordered"
msgstr ""
@@ -3884,53 +3889,53 @@ msgid "Payment completed on order after subscription was cancelled."
msgstr ""
#. translators: $1: opening link tag, $2: order number, $3: closing link tag
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:1085
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:1110
msgid "Subscription cancelled for refunded order %1$s#%2$s%3$s."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2381
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2406
msgctxt "An order type"
msgid "Original"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2382
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2407
msgctxt "An order type"
msgid "Subscription Parent"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2383
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2408
msgctxt "An order type"
msgid "Subscription Renewal"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2384
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2409
msgctxt "An order type"
msgid "Subscription Resubscribe"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2385
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2410
msgctxt "An order type"
msgid "Subscription Switch"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2386
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2411
msgctxt "An order type"
msgid "Non-subscription"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2395
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2420
msgid "All orders types"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2422
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2447
msgid "Renewal Order"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2424
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2449
msgid "Resubscribe Order"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2426
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-order.php:2451
msgid "Parent Order"
msgstr ""
@@ -4104,36 +4109,36 @@ msgstr ""
msgid "Month for Synchronisation"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:752
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:769
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:753
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:770
msgid "Do not synchronise"
msgstr ""
#. translators: placeholder is a day of the week
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:777
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:778
msgid "%s each week"
msgstr ""
#. translators: placeholder is a number of day with language specific suffix applied (e.g. "1st", "3rd", "5th", etc...)
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:783
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:784
msgid "%s day of the month"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:785
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:786
msgid "Last day of the month"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:833
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:834
msgid "Today!"
msgstr ""
#. translators: placeholder is a date
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:840
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:841
msgid "First payment prorated. Next payment: %s"
msgstr ""
#. translators: placeholder is a date
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:843
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:844
msgid "First payment: %s"
msgstr ""
@@ -5220,48 +5225,48 @@ msgid "If you are using PayPal Standard or PayPal Reference transactions please
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:114
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:360
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:362
msgid "Cancel and remove personal data"
msgstr ""
#. translators: %d: number of subscriptions affected.
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:210
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:212
msgid "Removed personal data from %d subscription."
msgid_plural "Removed personal data from %d subscriptions."
msgstr[0] ""
msgstr[1] ""
#. translators: placeholders are opening and closing tags.
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:229
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:231
msgid "%1$sNote:%2$s Orders which are related to subscriptions will not be included in the orders affected by these settings."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:249
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:251
msgid "account erasure request"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:255
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:257
msgid "Remove personal data from subscriptions"
msgstr ""
#. Translators: %s URL to erasure request screen.
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:257
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:259
msgid "When handling an %s, should personal data within subscriptions be retained or removed?"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:266
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:268
msgid "Retain ended subscriptions"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:267
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:269
msgid "Retain ended subscriptions and their related orders for a specified duration before anonymizing the personal data within them."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:270
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:272
msgid "N/A"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:311
#: vendor/woocommerce/subscriptions-core/includes/privacy/class-wcs-privacy.php:313
msgid "Customers with a subscription are excluded from this setting."
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 ComposerAutoloaderInit8810e821b269df6dcc857459761afe4a::getLoader();
return ComposerAutoloaderInit47c9a4f297bb3855920928bfaa252bb8::getLoader();

View File

@@ -45,35 +45,34 @@ class ClassLoader
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
* 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>>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -81,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
* @var array<string, string>
*/
private $classMap = array();
@@ -90,21 +88,20 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
/** @var string|null */
private $apcuPrefix;
/**
* @var self[]
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
@@ -113,7 +110,7 @@ class ClassLoader
}
/**
* @return string[]
* @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -125,8 +122,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -134,8 +130,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirs()
{
@@ -143,8 +138,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -152,8 +146,7 @@ class ClassLoader
}
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -161,8 +154,7 @@ class ClassLoader
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -180,23 +172,24 @@ class ClassLoader
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param list<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(
(array) $paths,
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
$paths
);
}
@@ -205,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
$paths
);
}
}
@@ -227,7 +220,7 @@ class ClassLoader
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
@@ -236,17 +229,18 @@ 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(
(array) $paths,
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -256,18 +250,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] = (array) $paths;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
$paths
);
}
}
@@ -277,7 +271,7 @@ class ClassLoader
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -295,7 +289,7 @@ class ClassLoader
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -481,9 +475,9 @@ class ClassLoader
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return self[]
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{

View File

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

View File

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

View File

@@ -156,17 +156,17 @@
},
{
"name": "woocommerce/subscriptions-core",
"version": "7.3.0",
"version_normalized": "7.3.0.0",
"version": "7.4.1",
"version_normalized": "7.4.1.0",
"source": {
"type": "git",
"url": "https://github.com/Automattic/woocommerce-subscriptions-core.git",
"reference": "f144df5b7ee103c4e792d8ddc0e72f1839def8b2"
"reference": "cfe4169e9c770baf4f3734c6e2baa9a014c023ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/f144df5b7ee103c4e792d8ddc0e72f1839def8b2",
"reference": "f144df5b7ee103c4e792d8ddc0e72f1839def8b2",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/cfe4169e9c770baf4f3734c6e2baa9a014c023ba",
"reference": "cfe4169e9c770baf4f3734c6e2baa9a014c023ba",
"shasum": ""
},
"require": {
@@ -179,7 +179,7 @@
"woocommerce/woocommerce-sniffs": "0.1.0",
"yoast/phpunit-polyfills": "1.1.0"
},
"time": "2024-07-16T05:33:10+00:00",
"time": "2024-08-21T09:17:35+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/7.3.0",
"source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/7.4.1",
"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.5.0',
'version' => 'dev-release/6.5.0',
'reference' => '75ec0cbc31ee105f66684b10fb0433b44b3e58e9',
'pretty_version' => 'dev-release/6.6.0',
'version' => 'dev-release/6.6.0',
'reference' => '0e08ee41671d4cc44c73224008901acd210d4686',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -32,18 +32,18 @@
),
),
'woocommerce/subscriptions-core' => array(
'pretty_version' => '7.3.0',
'version' => '7.3.0.0',
'reference' => 'f144df5b7ee103c4e792d8ddc0e72f1839def8b2',
'pretty_version' => '7.4.1',
'version' => '7.4.1.0',
'reference' => 'cfe4169e9c770baf4f3734c6e2baa9a014c023ba',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../woocommerce/subscriptions-core',
'aliases' => array(),
'dev_requirement' => false,
),
'woocommerce/woocommerce-subscriptions' => array(
'pretty_version' => 'dev-release/6.5.0',
'version' => 'dev-release/6.5.0',
'reference' => '75ec0cbc31ee105f66684b10fb0433b44b3e58e9',
'pretty_version' => 'dev-release/6.6.0',
'version' => 'dev-release/6.6.0',
'reference' => '0e08ee41671d4cc44c73224008901acd210d4686',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

@@ -1,9 +1,18 @@
*** WooCommerce Subscriptions Core Changelog ***
= 7.4.1 - 2024-08-21 =
* Fix - Add a year to the next renewal date billing interval is 12 months or more for a synced subscription.
= 7.4.0 - 2024-08-16 =
* Dev - Introduce new parameter to WC_Subscription::get_last_order() to enable filtering out orders with specific statuses.
* Update - Schedule subscription-related events with a priority of 1 to allow for earlier execution within the Action Scheduler.
* Fix - Ensure admin notices are displayed after performing bulk actions on subscriptions when HPOS is enabled.
= 7.3.0 - 2024-07-16 =
* Fix - Label improvements on subscription and order page templates.
* Fix - Fixed an issue with subscriptions containing multiple renewal orders to mark a random item as processing, instead of the last order.
* Fix - Prevent errors from invalid subscription objects during customer payment method updates.
* Fix - Resolved an error when purchasing subscription products on the block checkout with a limited recurring coupon.
= 7.2.0 - 2024-06-13 =
* Fix - label improvement on my subscription page template.

View File

@@ -2077,9 +2077,10 @@ class WC_Subscription extends WC_Order {
*
* @param string $return_fields The columns to return, either 'all' or 'ids'
* @param array $order_types Can include any combination of 'parent', 'renewal', 'switch' or 'any' which will return the latest renewal order of any type. Defaults to 'parent' and 'renewal'.
* @param array $exclude_statuses An array of statuses to exclude from the search. Defaults to an empty array.
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/
public function get_last_order( $return_fields = 'ids', $order_types = array( 'parent', 'renewal' ) ) {
public function get_last_order( $return_fields = 'ids', $order_types = array( 'parent', 'renewal' ), $exclude_statuses = [] ) {
$return_fields = ( 'ids' == $return_fields ) ? $return_fields : 'all';
$order_types = ( 'any' == $order_types ) ? array( 'parent', 'renewal', 'switch' ) : (array) $order_types;
@@ -2098,6 +2099,16 @@ class WC_Subscription extends WC_Order {
}
}
if ( ! empty( $exclude_statuses ) ) {
$related_orders = array_filter(
$related_orders,
function( $order_id ) use ( $exclude_statuses ) {
$order = wc_get_order( $order_id );
return $order && ! $order->has_status( $exclude_statuses );
}
);
}
if ( empty( $related_orders ) ) {
$last_order = false;
} else {

View File

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

View File

@@ -683,29 +683,54 @@ class WC_Subscriptions_Order {
}
// Skip checks if order total is greater than zero, or
// recurring total is zero, or
// order status isn't valid for payment.
if ( $order->get_total() > 0 || self::get_recurring_total( $order ) <= 0 || ! $order->has_status( $valid_order_statuses ) ) {
if ( $order->get_total() > 0 || ! $order->has_status( $valid_order_statuses ) ) {
return $needs_payment;
}
// Skip checks if manual renewal is required.
if ( wcs_is_manual_renewal_required() ) {
return $needs_payment;
}
// Check if there's a subscription attached to this order that will require a payment method.
foreach ( wcs_get_subscriptions_for_order( $order ) as $subscription ) {
$has_next_payment = false;
$contains_expiring_limited_coupon = false;
$contains_free_trial = false;
$contains_synced = false;
// Check if there's a subscription with a recurring total that would require a payment method.
$recurring_total = (float) $subscription->get_total();
// Check that there is at least 1 subscription with a next payment that would require a payment method.
$has_next_payment = false;
foreach ( wcs_get_subscriptions_for_order( $order ) as $subscription ) {
if ( $subscription->get_time( 'next_payment' ) ) {
$has_next_payment = true;
break;
}
}
if ( ! $has_next_payment ) {
return $needs_payment;
// Check if there's a subscription with a limited recurring coupon that is expiring that would require a payment method after the coupon expires.
if ( class_exists( 'WCS_Limited_Recurring_Coupon_Manager' ) && WCS_Limited_Recurring_Coupon_Manager::order_has_limited_recurring_coupon( $subscription ) ) {
$contains_expiring_limited_coupon = true;
}
// If manual renewals are not required.
if ( ! wcs_is_manual_renewal_required() ) {
// Check if there's a subscription with a free trial that would require a payment method after the trial ends.
if ( $subscription->get_time( 'trial_end' ) ) {
$contains_free_trial = true;
}
// Check if there's a subscription with a synced product that would require a payment method.
if ( WC_Subscriptions_Synchroniser::subscription_contains_synced_product( $subscription ) ) {
$contains_synced = true;
}
/**
* We need to collect a payment method if there's a subscription with a recurring total or a limited recurring coupon that is expiring and
* there's a next payment date or a free trial or a synced product.
*/
if ( ( $contains_expiring_limited_coupon || $recurring_total > 0 ) && ( $has_next_payment || $contains_free_trial || $contains_synced ) ) {
$needs_payment = true;
break; // We've found a subscription that requires a payment method.
}
}
return $needs_payment;

View File

@@ -686,8 +686,9 @@ class WC_Subscriptions_Synchroniser {
$month_number = gmdate( 'm', wcs_add_months( $from_timestamp, $interval ) );
}
}
// when a certain number of months are added and the first payment date moves to next year
if ( $month_number < gmdate( 'm', $from_timestamp ) ) {
if ( $month_number < gmdate( 'm', $from_timestamp ) || $interval >= 12 ) {
$year = gmdate( 'Y', $from_timestamp );
$year++;
$first_payment_timestamp = wcs_strtotime_dark_knight( "{$payment_day} {$month} {$year}", $from_timestamp );

View File

@@ -10,6 +10,16 @@
*/
class WCS_Action_Scheduler extends WCS_Scheduler {
/**
* The action scheduler group to use for scheduled subscription events.
*/
const ACTION_GROUP = 'wc_subscription_scheduled_event';
/**
* The priority of the subscription-related scheduled action.
*/
const ACTION_PRIORITY = 1;
/**
* An internal cache of action hooks and corresponding date types.
*
@@ -55,7 +65,7 @@ class WCS_Action_Scheduler extends WCS_Scheduler {
// Only schedule it if it's valid. It's active, it's a payment retry or it's pending cancelled and the end date being updated.
if ( 'payment_retry' === $date_type || $subscription->has_status( 'active' ) || ( $subscription->has_status( 'pending-cancel' ) && 'end' === $date_type ) ) {
as_schedule_single_action( $timestamp, $action_hook, $action_args );
$this->schedule_action( $timestamp, $action_hook, $action_args );
}
}
}
@@ -110,7 +120,7 @@ class WCS_Action_Scheduler extends WCS_Scheduler {
}
if ( 0 != $event_time && $event_time > current_time( 'timestamp', true ) && $next_scheduled !== $event_time ) {
as_schedule_single_action( $event_time, $action_hook, $action_args );
$this->schedule_action( $event_time, $action_hook, $action_args );
}
}
@@ -139,7 +149,7 @@ class WCS_Action_Scheduler extends WCS_Scheduler {
// The end date was set in WC_Subscriptions::update_dates() to the appropriate value, so we can schedule our action for that time
if ( $end_time > current_time( 'timestamp', true ) && $next_scheduled !== $end_time ) {
as_schedule_single_action( $end_time, 'woocommerce_scheduled_subscription_end_of_prepaid_term', $action_args );
$this->schedule_action( $end_time, 'woocommerce_scheduled_subscription_end_of_prepaid_term', $action_args );
}
break;
case 'on-hold':
@@ -226,4 +236,36 @@ class WCS_Action_Scheduler extends WCS_Scheduler {
protected function unschedule_actions( $action_hook, $action_args ) {
as_unschedule_all_actions( $action_hook, $action_args );
}
/**
* Gets the priority of the subscription-related scheduled action.
*
* @return int The priority of the subscription-related scheduled action.
*/
public function get_action_priority( $action_hook ) {
return apply_filters( 'woocommerce_subscriptions_scheduled_action_priority', self::ACTION_PRIORITY, $action_hook );
}
/**
* Schedule an subscription-related action with the Action Scheduler.
*
* Subscription events are scheduled with a priority of 1 (see self::ACTION_PRIORITY) and the
* group 'wc_subscription_scheduled_event' (see self::ACTION_GROUP).
*
* @param int $timestamp Unix timestamp of when the action should run.
* @param string $action_hook Name of event used as the hook for the scheduled action.
* @param array $action_args Array of name => value pairs stored against the scheduled action.
*
* @return int The action ID.
*/
protected function schedule_action( $timestamp, $action_hook, $action_args ) {
$as_version = ActionScheduler_Versions::instance()->latest_version();
// On older versions of Action Scheduler, we cannot specify a priority.
if ( version_compare( $as_version, '3.6.0', '<' ) ) {
return as_schedule_single_action( $timestamp, $action_hook, $action_args, self::ACTION_GROUP );
}
return as_schedule_single_action( $timestamp, $action_hook, $action_args, self::ACTION_GROUP, false, $this->get_action_priority( $action_hook ) );
}
}

View File

@@ -124,7 +124,7 @@ class WCS_Privacy extends WC_Abstract_Privacy {
*/
public static function handle_privacy_bulk_actions( $redirect_url, $action, $subscription_ids ) {
if ( 'wcs_remove_personal_data' !== $action ) {
return;
return $redirect_url;
}
$changed = 0;
@@ -146,8 +146,7 @@ class WCS_Privacy extends WC_Abstract_Privacy {
$sendback_args['changed'] = $changed;
$sendback = add_query_arg( $sendback_args, $redirect_url );
wp_safe_redirect( esc_url_raw( $sendback ) );
exit();
return esc_url_raw( $sendback );
}
/**
@@ -178,7 +177,10 @@ class WCS_Privacy extends WC_Abstract_Privacy {
$subscription_ids = array_map( 'absint', (array) $_REQUEST['post'] );
$base_redirect_url = wp_get_referer() ? wp_get_referer() : '';
self::handle_privacy_bulk_actions( $base_redirect_url, $action, $subscription_ids );
$redirect_url = self::handle_privacy_bulk_actions( $base_redirect_url, $action, $subscription_ids );
wp_safe_redirect( $redirect_url );
exit();
}
/**

View File

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

View File

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