Updates to 5.7.0

This commit is contained in:
WooCommerce
2023-11-09 10:12:17 +00:00
parent 5eedf6aedb
commit a87183cf97
31 changed files with 925 additions and 442 deletions

View File

@@ -1,5 +1,18 @@
*** Woo Subscriptions Changelog *** *** Woo Subscriptions Changelog ***
2023-11-09 - version 5.7.0
* Add: Introduce a new REST API endpoint to create subscription(s) from a given order. This endpoint is available at POST `/wc/v3/orders/{order_id}/subscriptions` and accepts a single order ID.
* Add: When a customer toggles automatic renewals on or off via their My Account page, add a note to the subscription to record that event.
* Fix: Set and update a subscription's trial end date via the REST API.
* Fix: Ensure the `woocommerce_subscription_renewal_payment_complete` hook is always triggered when processing early renewals via the checkout page (introduced in 5.6.0).
* Fix: When a subscription is flagged as requiring manual payments, allow admin users to turn on automatic payments for a subscription via the Edit Subscription page by selecting a new payment method.
* Fix: When processing an early renewal order, make sure the suspension count is reset back to 0 on payment complete.
* Fix: Ensure proper backfilling of subscription metadata (i.e. dates and cache) to the postmeta table when HPOS is enabled and compatibility mode (data syncing) is turned on.
* Fix: Fetch and update the `_cancelled_email_sent` meta in a HPOS compatibile way.
* Dev: Introduce a new wcs_get_subscription_grouping_key() function to generate a unique key for a subscription based on its billing schedule. This function uses the existing recurring cart key concept.
* Dev: Deprecate the WC_Subscriptions_Synchroniser::add_to_recurring_cart_key(). Use WC_Subscriptions_Synchroniser::add_to_recurring_product_grouping_key() instead.
* Dev: Update subscriptions-core to 6.5.0.
2023-10-18 - version 5.6.0 2023-10-18 - version 5.6.0
* Add: Introduce the "Subscription Relationship" column under the Orders list admin page when HPOS is enabled. * Add: Introduce the "Subscription Relationship" column under the Orders list admin page when HPOS is enabled.
* Add: Use admin theme color and the correct WooCommerce colors. * Add: Use admin theme color and the correct WooCommerce colors.

View File

@@ -60,6 +60,16 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
), ),
'schema' => array( $this, 'get_public_item_schema' ), 'schema' => array( $this, 'get_public_item_schema' ),
) ); ) );
register_rest_route( $this->namespace, "/orders/(?P<id>[\d]+)/{$this->rest_base}", array(
array(
'methods' => WP_REST_Server::CREATABLE,
'callback' => array( $this, 'create_subscriptions_from_order' ),
'permission_callback' => array( $this, 'create_item_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
) );
} }
/** /**
@@ -261,7 +271,7 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
$this->update_address( $subscription, $value, $key ); $this->update_address( $subscription, $value, $key );
break; break;
case 'start_date': case 'start_date':
case 'trial_end': case 'trial_end_date':
case 'next_payment_date': case 'next_payment_date':
case 'cancelled_date': case 'cancelled_date':
case 'end_date': case 'end_date':
@@ -413,8 +423,8 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
'type' => 'date-time', 'type' => 'date-time',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),
), ),
'trial_date' => array( 'trial_end_date' => array(
'description' => __( "The subscription's trial date, as GMT.", 'woocommerce-subscriptions' ), 'description' => __( "The subscription's trial end date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time', 'type' => 'date-time',
'context' => array( 'view', 'edit' ), 'context' => array( 'view', 'edit' ),
), ),
@@ -512,4 +522,196 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
throw new WC_REST_Exception( 'woocommerce_rest_invalid_payment_data', sprintf( __( 'Subscription payment method could not be set to %1$s with error message: %2$s', 'woocommerce-subscriptions' ), $payment_method, $e->getMessage() ), 400 ); throw new WC_REST_Exception( 'woocommerce_rest_invalid_payment_data', sprintf( __( 'Subscription payment method could not be set to %1$s with error message: %2$s', 'woocommerce-subscriptions' ), $payment_method, $e->getMessage() ), 400 );
} }
} }
/**
* Creates subscriptions from an order.
*
* @param WP_REST_Request $request
* @return array Subscriptions created from the order.
*/
public function create_subscriptions_from_order( $request ) {
$order_id = absint( $request->get_param( 'id' ) );
if ( empty( $order_id ) ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', __( 'Invalid order ID.', 'woocommerce-subscriptions' ), array( 'status' => 404 ) );
}
$order = wc_get_order( $order_id );
if ( ! $order || ! wcs_is_order( $order ) ) {
return new WP_Error( 'woocommerce_rest_order_invalid_id', sprintf( __( 'Failed to load order object with the ID %d.', 'woocommerce-subscriptions' ), $order_id ), array( 'status' => 404 ) );
}
if ( ! $order->get_customer_id() ) {
return new WP_Error( 'woocommerce_rest_invalid_order', __( 'Order does not have a customer associated with it. Subscriptions require a customer.', 'woocommerce-subscriptions' ), array( 'status' => 404 ) );
}
if ( wcs_order_contains_subscription( $order, 'any' ) ) {
return new WP_Error( 'woocommerce_rest_invalid_order', __( 'Order already has subscriptions associated with it.', 'woocommerce-subscriptions' ), array( 'status' => 404 ) );
}
$subscription_groups = [];
$subscriptions = [];
// Group the order items into subscription groups.
foreach ( $order->get_items() as $item ) {
$product = $item->get_product();
if ( ! WC_Subscriptions_Product::is_subscription( $product ) ) {
continue;
}
$subscription_groups[ wcs_get_subscription_item_grouping_key( $item ) ][] = $item;
}
// Return a 204 if there are no subscriptions to be created.
if ( empty( $subscription_groups ) ) {
$response = rest_ensure_response( $subscriptions );
$response->set_status( 204 );
return $response;
}
/**
* Start creating any subscriptions start transaction if available.
*
* To ensure data integrity, if any subscription fails to be created, the transaction will be rolled back. This will enable
* the client to resubmit the request without having to worry about duplicate subscriptions being created.
*/
$transaction = new WCS_SQL_Transaction();
$transaction->start();
try {
// Create subscriptions.
foreach ( $subscription_groups as $items ) {
// Get the first item in the group to use as the base for the subscription.
$product = $items[0]->get_product();
$start_date = wcs_get_datetime_utc_string( $order->get_date_created( 'edit' ) );
$subscription = wcs_create_subscription( [
'order_id' => $order_id,
'created_via' => 'rest-api',
'start_date' => $start_date,
'status' => $order->is_paid() ? 'active' : 'pending',
'billing_period' => WC_Subscriptions_Product::get_period( $product ),
'billing_interval' => WC_Subscriptions_Product::get_interval( $product ),
'customer_note' => $order->get_customer_note(),
] );
if ( is_wp_error( $subscription ) ) {
throw new Exception( $subscription->get_error_message() );
}
wcs_copy_order_address( $order, $subscription );
$subscription->update_dates(
array(
'trial_end' => WC_Subscriptions_Product::get_trial_expiration_date( $product, $start_date ),
'next_payment' => WC_Subscriptions_Product::get_first_renewal_payment_date( $product, $start_date ),
'end' => WC_Subscriptions_Product::get_expiration_date( $product, $start_date ),
)
);
$subscription->set_payment_method( $order->get_payment_method() );
wcs_copy_order_meta( $order, $subscription, 'subscription' );
// Add items.
$subscription_needs_shipping = false;
foreach ( $items as $item ) {
// Create order line item.
$item_id = wc_add_order_item(
$subscription->get_id(),
[
'order_item_name' => $item->get_name(),
'order_item_type' => $item->get_type(),
]
);
$subscription_item = $subscription->get_item( $item_id );
wcs_copy_order_item( $item, $subscription_item );
$subscription_item->save();
// Check if this subscription will need shipping.
if ( ! $subscription_needs_shipping ) {
$product = $item->get_product();
if ( $product ) {
$subscription_needs_shipping = $product->needs_shipping() && ! WC_Subscriptions_Product::needs_one_time_shipping( $product );
}
}
}
// Add coupons.
foreach ( $order->get_coupons() as $coupon_item ) {
$coupon = new WC_Coupon( $coupon_item->get_code() );
try {
// validate_subscription_coupon_for_order will throw an exception if the coupon cannot be applied to the subscription.
WC_Subscriptions_Coupon::validate_subscription_coupon_for_order( true, $coupon, $subscription );
$subscription->apply_coupon( $coupon->get_code() );
} catch ( Exception $e ) {
// Do nothing. The coupon will not be applied to the subscription.
}
}
// Add shipping.
if ( $subscription_needs_shipping ) {
foreach ( $order->get_shipping_methods() as $shipping_item ) {
$rate = new WC_Shipping_Rate( $shipping_item->get_method_id(), $shipping_item->get_method_title(), $shipping_item->get_total(), $shipping_item->get_taxes(), $shipping_item->get_instance_id() );
$item = new WC_Order_Item_Shipping();
$item->set_order_id( $subscription->get_id() );
$item->set_shipping_rate( $rate );
$subscription->add_item( $item );
}
}
// Add fees.
foreach ( $order->get_fees() as $fee_item ) {
if ( ! apply_filters( 'wcs_should_copy_fee_item_to_subscription', true, $fee_item, $subscription, $order ) ) {
continue;
}
$item = new WC_Order_Item_Fee();
$item->set_props(
array(
'name' => $fee_item->get_name(),
'tax_class' => $fee_item->get_tax_class(),
'amount' => $fee_item->get_amount(),
'total' => $fee_item->get_total(),
'total_tax' => $fee_item->get_total_tax(),
'taxes' => $fee_item->get_taxes(),
)
);
$subscription->add_item( $item );
}
$subscription->calculate_totals();
$subscription->save();
/**
* Fires after a single subscription is created or updated via the REST API.
*
* @param WC_Subscription $object Inserted subscription.
* @param WP_REST_Request $request Request object.
* @param boolean $creating True when creating object, false when updating.
*/
do_action( "woocommerce_rest_insert_{$this->post_type}_object", $subscription, $request, true );
$response = $this->prepare_object_for_response( wcs_get_subscription( $subscription->get_id() ), $request );
$subscriptions[] = $this->prepare_response_for_collection( $response );
}
} catch ( Exception $e ) {
$transaction->rollback();
return new WP_Error( 'woocommerce_rest_invalid_subscription_data', $e->getMessage(), array( 'status' => 404 ) );
}
// If we got here, the subscription was created without problems
$transaction->commit();
return rest_ensure_response( $subscriptions );
}
} }

View File

@@ -479,6 +479,9 @@ class WCS_Cart_Early_Renewal extends WCS_Cart_Renewal {
// Payment success - if payment was successful and dates haven't been updated for this order, update the subscription dates and store meta to prevent dates being updated multiple times for the same order. // Payment success - if payment was successful and dates haven't been updated for this order, update the subscription dates and store meta to prevent dates being updated multiple times for the same order.
if ( $subscription && $order->is_paid() && ! $order->meta_exists( self::SUBSCRIPTION_DATES_UPDATED_META_KEY ) ) { if ( $subscription && $order->is_paid() && ! $order->meta_exists( self::SUBSCRIPTION_DATES_UPDATED_META_KEY ) ) {
// Call the subscription payment complete function to trigger the payment complete hook and reset suspension counts and update user roles.
$subscription->payment_complete();
wcs_update_dates_after_early_renewal( $subscription, $order ); wcs_update_dates_after_early_renewal( $subscription, $order );
$order->update_meta_data( self::SUBSCRIPTION_DATES_UPDATED_META_KEY, wc_bool_to_string( true ) ); $order->update_meta_data( self::SUBSCRIPTION_DATES_UPDATED_META_KEY, wc_bool_to_string( true ) );

View File

@@ -2,14 +2,14 @@
# This file is distributed under the same license as the Woo Subscriptions plugin. # This file is distributed under the same license as the Woo Subscriptions plugin.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Woo Subscriptions 5.6.0\n" "Project-Id-Version: Woo Subscriptions 5.7.0\n"
"Report-Msgid-Bugs-To: https://woocommerce.com/contact-us\n" "Report-Msgid-Bugs-To: https://woocommerce.com/contact-us\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"POT-Creation-Date: 2023-10-18T04:37:04+00:00\n" "POT-Creation-Date: 2023-11-09T05:16:09+00:00\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"X-Generator: WP-CLI 2.8.1\n" "X-Generator: WP-CLI 2.8.1\n"
"X-Domain: woocommerce-subscriptions\n" "X-Domain: woocommerce-subscriptions\n"
@@ -669,55 +669,55 @@ msgstr ""
msgid "Payment Gateway Feature Support." msgid "Payment Gateway Feature Support."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:155 #: includes/api/class-wc-rest-subscriptions-controller.php:165
msgid "Invalid subscription ID." msgid "Invalid subscription ID."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:161 #: includes/api/class-wc-rest-subscriptions-controller.php:171
msgid "Failed to load subscription object with the ID %d." msgid "Failed to load subscription object with the ID %d."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:323 #: includes/api/class-wc-rest-subscriptions-controller.php:333
msgid "Subscription dates could not be set. Error message: %s" msgid "Subscription dates could not be set. Error message: %s"
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:359 #: includes/api/class-wc-rest-subscriptions-controller.php:369
msgid "Subscription status." msgid "Subscription status."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:362 #: includes/api/class-wc-rest-subscriptions-controller.php:372
msgid "Where the subscription was created." msgid "Where the subscription was created."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:363 #: includes/api/class-wc-rest-subscriptions-controller.php:373
msgid "Currency the subscription was created with, in ISO format." msgid "Currency the subscription was created with, in ISO format."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:364 #: includes/api/class-wc-rest-subscriptions-controller.php:374
msgid "The date the subscription was created, in the site's timezone." msgid "The date the subscription was created, in the site's timezone."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:365 #: includes/api/class-wc-rest-subscriptions-controller.php:375
msgid "The date the subscription was created, as GMT." msgid "The date the subscription was created, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:366 #: includes/api/class-wc-rest-subscriptions-controller.php:376
msgid "The date the subscription was last modified, in the site's timezone." msgid "The date the subscription was last modified, in the site's timezone."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:367 #: includes/api/class-wc-rest-subscriptions-controller.php:377
msgid "The date the subscription was last modified, as GMT." msgid "The date the subscription was last modified, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:368 #: includes/api/class-wc-rest-subscriptions-controller.php:378
msgid "User ID who owns the subscription." msgid "User ID who owns the subscription."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:378 #: includes/api/class-wc-rest-subscriptions-controller.php:388
msgid "The status to transition a subscription to." msgid "The status to transition a subscription to."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:384 #: includes/api/class-wc-rest-subscriptions-controller.php:394
#: includes/api/legacy/class-wc-rest-subscriptions-controller.php:350 #: includes/api/legacy/class-wc-rest-subscriptions-controller.php:350
#: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:506 #: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:506
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:179 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:179
@@ -725,7 +725,7 @@ msgstr ""
msgid "The number of billing periods between subscription renewals." msgid "The number of billing periods between subscription renewals."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:389 #: includes/api/class-wc-rest-subscriptions-controller.php:399
#: includes/api/legacy/class-wc-rest-subscriptions-controller.php:355 #: includes/api/legacy/class-wc-rest-subscriptions-controller.php:355
#: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:511 #: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:511
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:172 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:172
@@ -733,56 +733,72 @@ msgstr ""
msgid "Billing period for the subscription." msgid "Billing period for the subscription."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:395 #: includes/api/class-wc-rest-subscriptions-controller.php:405
#: includes/api/legacy/class-wc-rest-subscriptions-controller.php:361 #: includes/api/legacy/class-wc-rest-subscriptions-controller.php:361
#: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:517 #: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:517
msgid "Subscription payment details." msgid "Subscription payment details."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:400 #: includes/api/class-wc-rest-subscriptions-controller.php:410
msgid "Payment method meta and token in a post_meta_key: token format." msgid "Payment method meta and token in a post_meta_key: token format."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:405 #: includes/api/class-wc-rest-subscriptions-controller.php:415
msgid "Payment method meta and token in a user_meta_key : token format." msgid "Payment method meta and token in a user_meta_key : token format."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:412 #: includes/api/class-wc-rest-subscriptions-controller.php:422
msgid "The subscription's start date, as GMT." msgid "The subscription's start date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:417
msgid "The subscription's trial date, as GMT."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:422
msgid "The subscription's next payment date, as GMT."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:427 #: includes/api/class-wc-rest-subscriptions-controller.php:427
msgid "The subscription's cancelled date, as GMT." msgid "The subscription's trial end date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:432 #: includes/api/class-wc-rest-subscriptions-controller.php:432
msgid "The subscription's next payment date, as GMT."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:437
msgid "The subscription's cancelled date, as GMT."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:442
msgid "The subscription's end date, as GMT." msgid "The subscription's end date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:451 #: includes/api/class-wc-rest-subscriptions-controller.php:461
msgid "Limit result set to subscriptions which have specific statuses." msgid "Limit result set to subscriptions which have specific statuses."
msgstr "" msgstr ""
#. translators: placeholder is the payment method ID. #. translators: placeholder is the payment method ID.
#: includes/api/class-wc-rest-subscriptions-controller.php:495 #: includes/api/class-wc-rest-subscriptions-controller.php:505
msgid "The %s payment gateway does not support admin changing the payment method." msgid "The %s payment gateway does not support admin changing the payment method."
msgstr "" msgstr ""
#. translators: 1$: gateway id, 2$: error message #. translators: 1$: gateway id, 2$: error message
#: includes/api/class-wc-rest-subscriptions-controller.php:512 #: includes/api/class-wc-rest-subscriptions-controller.php:522
#: includes/api/legacy/class-wc-rest-subscriptions-controller.php:336 #: includes/api/legacy/class-wc-rest-subscriptions-controller.php:336
#: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:405 #: includes/api/v1/class-wc-rest-subscriptions-v1-controller.php:405
msgid "Subscription payment method could not be set to %1$s with error message: %2$s" msgid "Subscription payment method could not be set to %1$s with error message: %2$s"
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:536
msgid "Invalid order ID."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:542
msgid "Failed to load order object with the ID %d."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:546
msgid "Order does not have a customer associated with it. Subscriptions require a customer."
msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:550
msgid "Order already has subscriptions associated with it."
msgstr ""
#: includes/api/legacy/class-wc-api-subscriptions.php:102 #: includes/api/legacy/class-wc-api-subscriptions.php:102
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:136 #: vendor/woocommerce/subscriptions-core/wcs-functions.php:136
msgid "Invalid subscription status given." msgid "Invalid subscription status given."
@@ -1287,11 +1303,11 @@ msgid "Order %s created to record early renewal."
msgstr "" msgstr ""
#: includes/early-renewal/class-wcs-cart-early-renewal.php:294 #: includes/early-renewal/class-wcs-cart-early-renewal.php:294
#: includes/early-renewal/class-wcs-cart-early-renewal.php:624 #: includes/early-renewal/class-wcs-cart-early-renewal.php:627
msgid "Cancel" msgid "Cancel"
msgstr "" msgstr ""
#: includes/early-renewal/class-wcs-cart-early-renewal.php:592 #: includes/early-renewal/class-wcs-cart-early-renewal.php:595
msgctxt "used in order note as reason for why subscription status changed" msgctxt "used in order note as reason for why subscription status changed"
msgid "Customer requested to renew early:" msgid "Customer requested to renew early:"
msgstr "" msgstr ""
@@ -1718,13 +1734,13 @@ msgid "When switching to a subscription with a length, you can take into account
msgstr "" msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:437 #: includes/switching/class-wc-subscriptions-switcher.php:437
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:225 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:226
msgctxt "when to prorate first payment / subscription length" msgctxt "when to prorate first payment / subscription length"
msgid "For Virtual Subscription Products Only" msgid "For Virtual Subscription Products Only"
msgstr "" msgstr ""
#: includes/switching/class-wc-subscriptions-switcher.php:438 #: includes/switching/class-wc-subscriptions-switcher.php:438
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:226 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:227
msgctxt "when to prorate first payment / subscription length" msgctxt "when to prorate first payment / subscription length"
msgid "For All Subscription Products" msgid "For All Subscription Products"
msgstr "" msgstr ""
@@ -1870,6 +1886,46 @@ msgstr ""
msgid "Want to renew early via the checkout? Click %shere.%s" msgid "Want to renew early via the checkout? Click %shere.%s"
msgstr "" 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. #. translators: 1: relation type, 2: list of valid relation types.
#: vendor/woocommerce/subscriptions-core/includes/abstracts/abstract-wcs-related-order-store.php:148 #: 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." msgid "Invalid relation type: %1$s. Order relationship type must be one of: %2$s."
@@ -1952,7 +2008,7 @@ msgid "Optionally include an amount to be charged at the outset of the subscript
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wc-subscriptions-admin.php:371 #: vendor/woocommerce/subscriptions-core/includes/admin/class-wc-subscriptions-admin.php:371
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2469 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2422
#: vendor/woocommerce/subscriptions-core/templates/admin/html-variation-price.php:25 #: vendor/woocommerce/subscriptions-core/templates/admin/html-variation-price.php:25
msgid "Free trial" msgid "Free trial"
msgstr "" msgstr ""
@@ -2463,7 +2519,7 @@ msgstr[1] ""
#. translators: placeholder is the display name of a payment gateway a subscription was paid by #. translators: placeholder is the display name of a payment gateway a subscription was paid by
#. translators: %s: payment method. #. translators: %s: payment method.
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:646 #: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:646
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2047 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2052
msgid "Via %s" msgid "Via %s"
msgstr "" msgstr ""
@@ -2531,7 +2587,7 @@ msgid "None"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1129 #: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:1129
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2029 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2034
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:170 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:170
msgid "Manual Renewal" msgid "Manual Renewal"
msgstr "" msgstr ""
@@ -2783,14 +2839,14 @@ msgid "No billing address set."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/class-wcs-meta-box-subscription-data.php:188 #: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/class-wcs-meta-box-subscription-data.php:188
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:39 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:36
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:52 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:47
msgid "Payment Method" msgid "Payment method"
msgstr "" msgstr ""
#. translators: %s: gateway ID. #. translators: %s: gateway ID.
#: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/class-wcs-meta-box-subscription-data.php:193 #: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/class-wcs-meta-box-subscription-data.php:193
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:54 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:49
msgctxt "The gateway ID displayed on the Edit Subscriptions screen when editing payment method." msgctxt "The gateway ID displayed on the Edit Subscriptions screen when editing payment method."
msgid "Gateway ID: [%s]" msgid "Gateway ID: [%s]"
msgstr "" msgstr ""
@@ -2950,7 +3006,7 @@ msgstr ""
#. translators: %d: subscription ID. #. translators: %d: subscription ID.
#. translators: %d: order ID. #. translators: %d: order ID.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1365 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1365
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2470 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2475
msgid "Subscription #%d: " msgid "Subscription #%d: "
msgstr "" msgstr ""
@@ -2958,67 +3014,67 @@ msgstr ""
msgid "Payment status marked complete." msgid "Payment status marked complete."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1807 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1812
msgid "Payment failed." msgid "Payment failed."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1812 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1817
msgid "Subscription Cancelled: maximum number of failed payments reached." msgid "Subscription Cancelled: maximum number of failed payments reached."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1922 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:1927
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." 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 "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2126 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2131
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:835 #: vendor/woocommerce/subscriptions-core/wcs-functions.php:835
msgid "Payment method meta must be an array." msgid "Payment method meta must be an array."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2362 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2367
msgid "Invalid format. First parameter needs to be an array." msgid "Invalid format. First parameter needs to be an array."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2366 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2371
msgid "Invalid data. First parameter was empty when passed to update_dates()." msgid "Invalid data. First parameter was empty when passed to update_dates()."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2373 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2378
msgid "Invalid data. First parameter has a date that is not in the registered date types." msgid "Invalid data. First parameter has a date that is not in the registered date types."
msgstr "" msgstr ""
#. translators: placeholder is date type (e.g. "end", "next_payment"...) #. translators: placeholder is date type (e.g. "end", "next_payment"...)
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2400 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2405
msgctxt "appears in an error message if date is wrong format" 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\"." msgid "Invalid %s date. The date must be of the format: \"Y-m-d H:i:s\"."
msgstr "" msgstr ""
#. translators: %s: date type (e.g. "end"). #. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2438 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2443
msgid "The %s date must occur after the cancellation date." msgid "The %s date must occur after the cancellation date."
msgstr "" msgstr ""
#. translators: %s: date type (e.g. "end"). #. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2444 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2449
msgid "The %s date must occur after the last payment date." msgid "The %s date must occur after the last payment date."
msgstr "" msgstr ""
#. translators: %s: date type (e.g. "end"). #. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2449 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2454
msgid "The %s date must occur after the next payment date." msgid "The %s date must occur after the next payment date."
msgstr "" msgstr ""
#. translators: %s: date type (e.g. "end"). #. translators: %s: date type (e.g. "end").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2455 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2460
msgid "The %s date must occur after the trial end date." msgid "The %s date must occur after the trial end date."
msgstr "" msgstr ""
#. translators: %s: date type (e.g. "next_payment"). #. translators: %s: date type (e.g. "next_payment").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2460 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2465
msgid "The %s date must occur after the start date." msgid "The %s date must occur after the start date."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2490 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscription.php:2495
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-checkout.php:348 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-checkout.php:348
msgid "Backordered" msgid "Backordered"
msgstr "" msgstr ""
@@ -3069,7 +3125,7 @@ msgid "Your cart has been emptied of subscription products. Only one subscriptio
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart-validator.php:128 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart-validator.php:128
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:1529 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:1482
msgid "That subscription product can not be added to your cart as it already contains a subscription renewal." msgid "That subscription product can not be added to your cart as it already contains a subscription renewal."
msgstr "" msgstr ""
@@ -3081,16 +3137,16 @@ msgstr ""
msgid "Please enter a valid postcode/ZIP." msgid "Please enter a valid postcode/ZIP."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:1167 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:1120
msgid "Invalid recurring shipping method." msgid "Invalid recurring shipping method."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2205 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2158
msgid "now" msgid "now"
msgstr "" msgstr ""
#. translators: placeholder is a number of days. #. translators: placeholder is a number of days.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2364 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2317
#: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:58 #: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:58
msgid "%s day" msgid "%s day"
msgid_plural "%s days" msgid_plural "%s days"
@@ -3098,7 +3154,7 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: placeholder is a number of weeks. #. translators: placeholder is a number of weeks.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2368 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2321
#: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:60 #: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:60
msgid "%s week" msgid "%s week"
msgid_plural "%s weeks" msgid_plural "%s weeks"
@@ -3106,7 +3162,7 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: placeholder is a number of months. #. translators: placeholder is a number of months.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2372 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2325
#: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:62 #: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:62
msgid "%s month" msgid "%s month"
msgid_plural "%s months" msgid_plural "%s months"
@@ -3114,7 +3170,7 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: placeholder is a number of years. #. translators: placeholder is a number of years.
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2376 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2329
#: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:64 #: vendor/woocommerce/subscriptions-core/includes/wcs-time-functions.php:64
msgid "%s year" msgid "%s year"
msgid_plural "%s years" msgid_plural "%s years"
@@ -3122,49 +3178,49 @@ msgstr[0] ""
msgstr[1] "" msgstr[1] ""
#. translators: 1$: day of the week (e.g. "every Wednesday"). #. translators: 1$: day of the week (e.g. "every Wednesday").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2398 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2351
msgid "every %1$s" msgid "every %1$s"
msgstr "" msgstr ""
#. translators: 1$: period, 2$: day of the week (e.g. "every 2nd week on Wednesday"). #. translators: 1$: period, 2$: day of the week (e.g. "every 2nd week on Wednesday").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2402 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2355
msgid "every %1$s on %2$s" msgid "every %1$s on %2$s"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2411 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2364
msgid "on the last day of each month" msgid "on the last day of each month"
msgstr "" msgstr ""
#. translators: 1$: day of the month (e.g. "23rd") (e.g. "every 23rd of each month"). #. translators: 1$: day of the month (e.g. "23rd") (e.g. "every 23rd of each month").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2415 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2368
msgid "on the %1$s of each month" msgid "on the %1$s of each month"
msgstr "" msgstr ""
#. translators: 1$: interval (e.g. "3rd") (e.g. "on the last day of every 3rd month"). #. translators: 1$: interval (e.g. "3rd") (e.g. "on the last day of every 3rd month").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2423 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2376
msgid "on the last day of every %1$s month" msgid "on the last day of every %1$s month"
msgstr "" msgstr ""
#. translators: on the, 1$: <date> day of every, 2$: <interval> month (e.g. "on the 23rd day of every 2nd month"). #. translators: on the, 1$: <date> day of every, 2$: <interval> month (e.g. "on the 23rd day of every 2nd month").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2429 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2382
msgid "on the %1$s day of every %2$s month" msgid "on the %1$s day of every %2$s month"
msgstr "" msgstr ""
#. translators: on, 1$: <date>, 2$: <month> each year (e.g. "on March 15th each year"). #. translators: on, 1$: <date>, 2$: <month> each year (e.g. "on March 15th each year").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2440 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2393
msgid "on %1$s %2$s each year" msgid "on %1$s %2$s each year"
msgstr "" msgstr ""
#. translators: 1$: month (e.g. "March"), 2$: day of the month (e.g. "23rd), 3$: interval year (r.g March 23rd every 2nd year"). #. translators: 1$: month (e.g. "March"), 2$: day of the month (e.g. "23rd), 3$: interval year (r.g March 23rd every 2nd year").
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2447 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2400
msgid "on %1$s %2$s every %3$s year" msgid "on %1$s %2$s every %3$s year"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2479 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2432
msgid "Sign up fee" msgid "Sign up fee"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2489 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-cart.php:2442
msgid "Renews" msgid "Renews"
msgstr "" msgstr ""
@@ -3965,92 +4021,92 @@ msgctxt "used in subscription product edit screen"
msgid "Align the payment date for this subscription to a specific day of the year. If the date has already taken place this year, the first payment will be processed in %s. Set the day to 0 to disable payment syncing for this product." msgid "Align the payment date for this subscription to a specific day of the year. If the date has already taken place this year, the first payment will be processed in %s. Set the day to 0 to disable payment syncing for this product."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:199 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:200
msgid "Synchronisation" msgid "Synchronisation"
msgstr "" msgstr ""
#. translators: placeholders are opening and closing link tags #. translators: placeholders are opening and closing link tags
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:202 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:203
msgctxt "used in the general subscription options page" msgctxt "used in the general subscription options page"
msgid "Align subscription renewal to a specific day of the week, month or year. For example, the first day of the month. %1$sLearn more%2$s." msgid "Align subscription renewal to a specific day of the week, month or year. For example, the first day of the month. %1$sLearn more%2$s."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:208 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:209
msgid "Align Subscription Renewal Day" msgid "Align Subscription Renewal Day"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:215 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:216
msgid "Prorate First Renewal" msgid "Prorate First Renewal"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:216 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:217
msgid "If a subscription is synchronised to a specific day of the week, month or year, charge a prorated amount for the subscription at the time of sign up." msgid "If a subscription is synchronised to a specific day of the week, month or year, charge a prorated amount for the subscription at the time of sign up."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:223
msgctxt "when to prorate first payment / subscription length"
msgid "Never (do not charge any recurring amount)"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:224 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:224
msgctxt "when to prorate first payment / subscription length" msgctxt "when to prorate first payment / subscription length"
msgid "Never (do not charge any recurring amount)"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:225
msgctxt "when to prorate first payment / subscription length"
msgid "Never (charge the full recurring amount at sign-up)" msgid "Never (charge the full recurring amount at sign-up)"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:232 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:233
msgid "Sign-up grace period" msgid "Sign-up grace period"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:233 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:234
msgctxt "there's a number immediately in front of this text" msgctxt "there's a number immediately in front of this text"
msgid "days prior to Renewal Day" msgid "days prior to Renewal Day"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:237 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:238
msgid "Subscriptions created within this many days prior to the Renewal Day will not be charged at sign-up. Set to zero for all new Subscriptions to be charged the full recurring amount. Must be a positive number." msgid "Subscriptions created within this many days prior to the Renewal Day will not be charged at sign-up. Set to zero for all new Subscriptions to be charged the full recurring amount. Must be a positive number."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:306 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:307
msgid "Month for Synchronisation" msgid "Month for Synchronisation"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:314 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:315
#: vendor/woocommerce/subscriptions-core/templates/admin/deprecated/html-variation-synchronisation.php:36 #: vendor/woocommerce/subscriptions-core/templates/admin/deprecated/html-variation-synchronisation.php:36
#: vendor/woocommerce/subscriptions-core/templates/admin/html-variation-synchronisation.php:42 #: vendor/woocommerce/subscriptions-core/templates/admin/html-variation-synchronisation.php:42
msgctxt "input field placeholder for day field for annual subscriptions" msgctxt "input field placeholder for day field for annual subscriptions"
msgid "Day" msgid "Day"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:745 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:746
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:762 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:763
msgid "Do not synchronise" msgid "Do not synchronise"
msgstr "" msgstr ""
#. translators: placeholder is a day of the week #. translators: placeholder is a day of the week
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:770 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:771
msgid "%s each week" msgid "%s each week"
msgstr "" msgstr ""
#. translators: placeholder is a number of day with language specific suffix applied (e.g. "1st", "3rd", "5th", etc...) #. 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:776 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:777
msgid "%s day of the month" msgid "%s day of the month"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:778 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:779
msgid "Last day of the month" msgid "Last day of the month"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:826 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:827
msgid "Today!" msgid "Today!"
msgstr "" msgstr ""
#. translators: placeholder is a date #. translators: placeholder is a date
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:833 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:834
msgid "First payment prorated. Next payment: %s" msgid "First payment prorated. Next payment: %s"
msgstr "" msgstr ""
#. translators: placeholder is a date #. translators: placeholder is a date
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:836 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-synchroniser.php:837
msgid "First payment: %s" msgid "First payment: %s"
msgstr "" msgstr ""
@@ -4152,10 +4208,15 @@ msgctxt "The place order button text while resubscribing to a subscription"
msgid "Resubscribe" msgid "Resubscribe"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:123 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:116
msgid "Please choose a valid payment gateway to change to." msgid "Please choose a valid payment gateway to change to."
msgstr "" msgstr ""
#. Translators: Placeholder is the payment gateway title.
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-change-payment-method-admin.php:149
msgid "Admin turned on automatic renewals by changing payment method to \"%s\" via the Edit Subscription screen."
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-failed-scheduled-action-manager.php:158 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-failed-scheduled-action-manager.php:158
msgid "Ignore this error" msgid "Ignore this error"
msgstr "" msgstr ""
@@ -4181,15 +4242,23 @@ msgstr ""
msgid "Limit to one of any status" msgid "Limit to one of any status"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:153 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:101
msgid "Auto Renewal Toggle" msgid "Customer turned off automatic renewals via their My Account page."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:154 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:126
msgid "Display the auto renewal toggle" msgid "Customer turned on automatic renewals via their My Account page."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:155 #: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:155
msgid "Auto Renewal Toggle"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:156
msgid "Display the auto renewal toggle"
msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/class-wcs-my-account-auto-renew-toggle.php:157
msgid "Allow customers to turn on and off automatic renewals from their View Subscription page." msgid "Allow customers to turn on and off automatic renewals from their View Subscription page."
msgstr "" msgstr ""
@@ -4443,12 +4512,12 @@ msgid "This will clear the persistent cache of all renewal, switch, resubscribe
msgstr "" msgstr ""
#. translators: %s: Order date #. translators: %s: Order date
#: vendor/woocommerce/subscriptions-core/includes/data-stores/class-wcs-subscription-data-store-cpt.php:248 #: vendor/woocommerce/subscriptions-core/includes/data-stores/class-wcs-subscription-data-store-cpt.php:265
msgid "Subscription &ndash; %s" msgid "Subscription &ndash; %s"
msgstr "" msgstr ""
#. translators: %s: Order date #. translators: %s: Order date
#: vendor/woocommerce/subscriptions-core/includes/data-stores/class-wcs-subscription-data-store-cpt.php:248 #: vendor/woocommerce/subscriptions-core/includes/data-stores/class-wcs-subscription-data-store-cpt.php:265
msgctxt "Order date parsed by DateTime::format" msgctxt "Order date parsed by DateTime::format"
msgid "M d, Y @ h:i A" msgid "M d, Y @ h:i A"
msgstr "" msgstr ""
@@ -4481,7 +4550,7 @@ msgctxt "default email subject for cancelled emails sent to the admin"
msgid "[%s] Subscription Cancelled" msgid "[%s] Subscription Cancelled"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:143 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:145
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-customer-renewal-invoice.php:210 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-customer-renewal-invoice.php:210
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:141 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:141
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:141 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:141
@@ -4489,14 +4558,14 @@ msgctxt "an email notification"
msgid "Enable/Disable" msgid "Enable/Disable"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:145 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:147
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-customer-renewal-invoice.php:212 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-customer-renewal-invoice.php:212
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:143 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:143
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:143 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:143
msgid "Enable this email notification" msgid "Enable this email notification"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:149 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:151
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:147 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:147
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:147 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:147
msgctxt "of an email" msgctxt "of an email"
@@ -4504,13 +4573,13 @@ msgid "Recipient(s)"
msgstr "" msgstr ""
#. translators: placeholder is admin email #. translators: placeholder is admin email
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:152 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:154
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:150 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:150
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:150 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:150
msgid "Enter recipients (comma separated) for this email. Defaults to %s." msgid "Enter recipients (comma separated) for this email. Defaults to %s."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:157 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:159
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:155 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:155
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:155 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:155
msgctxt "of an email" msgctxt "of an email"
@@ -4518,13 +4587,13 @@ msgid "Subject"
msgstr "" msgstr ""
#. translators: %s: default e-mail subject. #. translators: %s: default e-mail subject.
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:160 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:162
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:158 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:158
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:158 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:158
msgid "This controls the email subject line. Leave blank to use the default subject: %s." msgid "This controls the email subject line. Leave blank to use the default subject: %s."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:165 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:167
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:163 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:163
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:163 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:163
msgctxt "Name the setting that controls the main heading contained within the email notification" msgctxt "Name the setting that controls the main heading contained within the email notification"
@@ -4532,38 +4601,38 @@ msgid "Email Heading"
msgstr "" msgstr ""
#. translators: %s: default e-mail heading. #. translators: %s: default e-mail heading.
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:168 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:170
msgid "This controls the main heading contained within the email notification. Leave blank to use the default heading: %s." msgid "This controls the main heading contained within the email notification. Leave blank to use the default heading: %s."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:173 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:175
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:171 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:171
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:171 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:171
msgctxt "text, html or multipart" msgctxt "text, html or multipart"
msgid "Email type" msgid "Email type"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:175 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:177
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:173 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:173
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:173 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:173
msgid "Choose which format of email to send." msgid "Choose which format of email to send."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:179 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:181
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:177 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:177
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:177 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:177
msgctxt "email type" msgctxt "email type"
msgid "Plain text" msgid "Plain text"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:180 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:182
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:178 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:178
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:178 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:178
msgctxt "email type" msgctxt "email type"
msgid "HTML" msgid "HTML"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:181 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-cancelled-subscription.php:183
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:179 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-expired-subscription.php:179
#: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:179 #: vendor/woocommerce/subscriptions-core/includes/emails/class-wcs-email-on-hold-subscription.php:179
msgctxt "email type" msgctxt "email type"
@@ -6325,14 +6394,6 @@ msgctxt "table headings in notification email"
msgid "Price" msgid "Price"
msgstr "" 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 #: vendor/woocommerce/subscriptions-core/templates/emails/cancelled-subscription.php:24
msgctxt "table headings in notification email" msgctxt "table headings in notification email"
msgid "End of Prepaid Term" msgid "End of Prepaid Term"
@@ -6615,12 +6676,6 @@ msgstr ""
msgid "ID" msgid "ID"
msgstr "" 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/my-subscriptions.php:46
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:53 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:53
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:42 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:42
@@ -6800,26 +6855,6 @@ msgstr ""
msgid "Can not get address type display name. Address type is not a string." msgid "Can not get address type display name. Address type is not a string."
msgstr "" 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 #: vendor/woocommerce/subscriptions-core/wcs-functions.php:331
msgid "Date type is not a string." msgid "Date type is not a string."
msgstr "" msgstr ""

20
vendor/autoload.php vendored
View File

@@ -2,24 +2,6 @@
// autoload.php @generated by Composer // autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit59c7b20d3f201de5581a0bc09b6c2289::getLoader(); return ComposerAutoloaderInitfe47e554dced83cd1f1961109287683e::getLoader();

View File

@@ -42,79 +42,30 @@ namespace Composer\Autoload;
*/ */
class ClassLoader class ClassLoader
{ {
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */
private $vendorDir; private $vendorDir;
// PSR-4 // PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array(); private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
*/
private $prefixDirsPsr4 = array(); private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr4 = array(); private $fallbackDirsPsr4 = array();
// PSR-0 // PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
*/
private $prefixesPsr0 = array(); private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
*/
private $fallbackDirsPsr0 = array(); private $fallbackDirsPsr0 = array();
/** @var bool */
private $useIncludePath = false; private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
*/
private $classMap = array(); private $classMap = array();
/** @var bool */
private $classMapAuthoritative = false; private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
*/
private $missingClasses = array(); private $missingClasses = array();
/** @var ?string */
private $apcuPrefix; private $apcuPrefix;
/**
* @var self[]
*/
private static $registeredLoaders = array(); private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
*/
public function __construct($vendorDir = null) public function __construct($vendorDir = null)
{ {
$this->vendorDir = $vendorDir; $this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
} }
/**
* @return string[]
*/
public function getPrefixes() public function getPrefixes()
{ {
if (!empty($this->prefixesPsr0)) { if (!empty($this->prefixesPsr0)) {
@@ -124,47 +75,28 @@ class ClassLoader
return array(); return array();
} }
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
*/
public function getPrefixesPsr4() public function getPrefixesPsr4()
{ {
return $this->prefixDirsPsr4; return $this->prefixDirsPsr4;
} }
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirs() public function getFallbackDirs()
{ {
return $this->fallbackDirsPsr0; return $this->fallbackDirsPsr0;
} }
/**
* @return array[]
* @psalm-return array<string, string>
*/
public function getFallbackDirsPsr4() public function getFallbackDirsPsr4()
{ {
return $this->fallbackDirsPsr4; return $this->fallbackDirsPsr4;
} }
/**
* @return string[] Array of classname => path
* @psalm-return array<string, string>
*/
public function getClassMap() public function getClassMap()
{ {
return $this->classMap; return $this->classMap;
} }
/** /**
* @param string[] $classMap Class to filename map * @param array $classMap Class to filename map
* @psalm-param array<string, string> $classMap
*
* @return void
*/ */
public function addClassMap(array $classMap) public function addClassMap(array $classMap)
{ {
@@ -179,11 +111,9 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either * Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix. * appending or prepending to the ones previously set for this prefix.
* *
* @param string $prefix The prefix * @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories * @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories * @param bool $prepend Whether to prepend the directories
*
* @return void
*/ */
public function add($prefix, $paths, $prepend = false) public function add($prefix, $paths, $prepend = false)
{ {
@@ -226,13 +156,11 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either * Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace. * appending or prepending to the ones previously set for this namespace.
* *
* @param string $prefix The prefix/namespace, with trailing '\\' * @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories * @param array|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories * @param bool $prepend Whether to prepend the directories
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*
* @return void
*/ */
public function addPsr4($prefix, $paths, $prepend = false) public function addPsr4($prefix, $paths, $prepend = false)
{ {
@@ -276,10 +204,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, * Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix. * replacing any others previously set for this prefix.
* *
* @param string $prefix The prefix * @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories * @param array|string $paths The PSR-0 base directories
*
* @return void
*/ */
public function set($prefix, $paths) public function set($prefix, $paths)
{ {
@@ -294,12 +220,10 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, * Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace. * replacing any others previously set for this namespace.
* *
* @param string $prefix The prefix/namespace, with trailing '\\' * @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories * @param array|string $paths The PSR-4 base directories
* *
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*
* @return void
*/ */
public function setPsr4($prefix, $paths) public function setPsr4($prefix, $paths)
{ {
@@ -319,8 +243,6 @@ class ClassLoader
* Turns on searching the include path for class files. * Turns on searching the include path for class files.
* *
* @param bool $useIncludePath * @param bool $useIncludePath
*
* @return void
*/ */
public function setUseIncludePath($useIncludePath) public function setUseIncludePath($useIncludePath)
{ {
@@ -343,8 +265,6 @@ class ClassLoader
* that have not been registered with the class map. * that have not been registered with the class map.
* *
* @param bool $classMapAuthoritative * @param bool $classMapAuthoritative
*
* @return void
*/ */
public function setClassMapAuthoritative($classMapAuthoritative) public function setClassMapAuthoritative($classMapAuthoritative)
{ {
@@ -365,8 +285,6 @@ class ClassLoader
* APCu prefix to use to cache found/not-found classes, if the extension is enabled. * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
* *
* @param string|null $apcuPrefix * @param string|null $apcuPrefix
*
* @return void
*/ */
public function setApcuPrefix($apcuPrefix) public function setApcuPrefix($apcuPrefix)
{ {
@@ -387,8 +305,6 @@ class ClassLoader
* Registers this instance as an autoloader. * Registers this instance as an autoloader.
* *
* @param bool $prepend Whether to prepend the autoloader or not * @param bool $prepend Whether to prepend the autoloader or not
*
* @return void
*/ */
public function register($prepend = false) public function register($prepend = false)
{ {
@@ -408,8 +324,6 @@ class ClassLoader
/** /**
* Unregisters this instance as an autoloader. * Unregisters this instance as an autoloader.
*
* @return void
*/ */
public function unregister() public function unregister()
{ {
@@ -429,8 +343,7 @@ class ClassLoader
public function loadClass($class) public function loadClass($class)
{ {
if ($file = $this->findFile($class)) { if ($file = $this->findFile($class)) {
$includeFile = self::$includeFile; includeFile($file);
$includeFile($file);
return true; return true;
} }
@@ -490,11 +403,6 @@ class ClassLoader
return self::$registeredLoaders; return self::$registeredLoaders;
} }
/**
* @param string $class
* @param string $ext
* @return string|false
*/
private function findFileWithExtension($class, $ext) private function findFileWithExtension($class, $ext)
{ {
// PSR-4 lookup // PSR-4 lookup
@@ -560,26 +468,14 @@ class ClassLoader
return false; return false;
} }
}
/**
* @return void /**
*/ * Scope isolated include.
private static function initializeIncludeClosure() *
{ * Prevents access to $this/self from included files.
if (self::$includeFile !== null) { */
return; function includeFile($file)
} {
include $file;
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
} }

View File

@@ -20,27 +20,12 @@ use Composer\Semver\VersionParser;
* *
* See also https://getcomposer.org/doc/07-runtime.md#installed-versions * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
* *
* To require its presence, you can require `composer-runtime-api ^2.0` * To require it's presence, you can require `composer-runtime-api ^2.0`
*
* @final
*/ */
class InstalledVersions class InstalledVersions
{ {
/**
* @var mixed[]|null
* @psalm-var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}|array{}|null
*/
private static $installed; private static $installed;
/**
* @var bool|null
*/
private static $canGetVendors; private static $canGetVendors;
/**
* @var array[]
* @psalm-var array<string, array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}>
*/
private static $installedByVendor = array(); private static $installedByVendor = array();
/** /**
@@ -98,7 +83,7 @@ class InstalledVersions
{ {
foreach (self::getInstalled() as $installed) { foreach (self::getInstalled() as $installed) {
if (isset($installed['versions'][$packageName])) { if (isset($installed['versions'][$packageName])) {
return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false; return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
} }
} }
@@ -119,7 +104,7 @@ class InstalledVersions
*/ */
public static function satisfies(VersionParser $parser, $packageName, $constraint) public static function satisfies(VersionParser $parser, $packageName, $constraint)
{ {
$constraint = $parser->parseConstraints((string) $constraint); $constraint = $parser->parseConstraints($constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint); return $provided->matches($constraint);
@@ -243,7 +228,7 @@ class InstalledVersions
/** /**
* @return array * @return array
* @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool} * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
*/ */
public static function getRootPackage() public static function getRootPackage()
{ {
@@ -257,7 +242,7 @@ class InstalledVersions
* *
* @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect. * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
* @return array[] * @return array[]
* @psalm-return array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
*/ */
public static function getRawData() public static function getRawData()
{ {
@@ -280,7 +265,7 @@ class InstalledVersions
* Returns the raw data of all installed.php which are currently loaded for custom implementations * Returns the raw data of all installed.php which are currently loaded for custom implementations
* *
* @return array[] * @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
*/ */
public static function getAllRawData() public static function getAllRawData()
{ {
@@ -303,7 +288,7 @@ class InstalledVersions
* @param array[] $data A vendor/composer/installed.php data set * @param array[] $data A vendor/composer/installed.php data set
* @return void * @return void
* *
* @psalm-param array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $data * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
*/ */
public static function reload($data) public static function reload($data)
{ {
@@ -313,7 +298,7 @@ class InstalledVersions
/** /**
* @return array[] * @return array[]
* @psalm-return list<array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>}> * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
*/ */
private static function getInstalled() private static function getInstalled()
{ {
@@ -328,9 +313,7 @@ class InstalledVersions
if (isset(self::$installedByVendor[$vendorDir])) { if (isset(self::$installedByVendor[$vendorDir])) {
$installed[] = self::$installedByVendor[$vendorDir]; $installed[] = self::$installedByVendor[$vendorDir];
} elseif (is_file($vendorDir.'/composer/installed.php')) { } elseif (is_file($vendorDir.'/composer/installed.php')) {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
$required = require $vendorDir.'/composer/installed.php';
$installed[] = self::$installedByVendor[$vendorDir] = $required;
if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) { if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
self::$installed = $installed[count($installed) - 1]; self::$installed = $installed[count($installed) - 1];
} }
@@ -342,17 +325,12 @@ class InstalledVersions
// only require the installed.php file if this file is loaded from its dumped location, // only require the installed.php file if this file is loaded from its dumped location,
// and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937 // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
if (substr(__DIR__, -8, 1) !== 'C') { if (substr(__DIR__, -8, 1) !== 'C') {
/** @var array{root: array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}, versions: array<string, array{pretty_version?: string, version?: string, reference?: string|null, type?: string, install_path?: string, aliases?: string[], dev_requirement: bool, replaced?: string[], provided?: string[]}>} $required */ self::$installed = require __DIR__ . '/installed.php';
$required = require __DIR__ . '/installed.php';
self::$installed = $required;
} else { } else {
self::$installed = array(); self::$installed = array();
} }
} }
$installed[] = self::$installed;
if (self::$installed !== array()) {
$installed[] = self::$installed;
}
return $installed; return $installed;
} }

View File

@@ -2,7 +2,7 @@
// autoload_classmap.php @generated by Composer // autoload_classmap.php @generated by Composer
$vendorDir = dirname(__DIR__); $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(

View File

@@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer // autoload_namespaces.php @generated by Composer
$vendorDir = dirname(__DIR__); $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(

View File

@@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer // autoload_psr4.php @generated by Composer
$vendorDir = dirname(__DIR__); $vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir); $baseDir = dirname($vendorDir);
return array( return array(

View File

@@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit59c7b20d3f201de5581a0bc09b6c2289 class ComposerAutoloaderInitfe47e554dced83cd1f1961109287683e
{ {
private static $loader; private static $loader;
@@ -24,12 +24,31 @@ class ComposerAutoloaderInit59c7b20d3f201de5581a0bc09b6c2289
require __DIR__ . '/platform_check.php'; require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit59c7b20d3f201de5581a0bc09b6c2289', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInitfe47e554dced83cd1f1961109287683e', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
spl_autoload_unregister(array('ComposerAutoloaderInit59c7b20d3f201de5581a0bc09b6c2289', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInitfe47e554dced83cd1f1961109287683e', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php'; $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
call_user_func(\Composer\Autoload\ComposerStaticInit59c7b20d3f201de5581a0bc09b6c2289::getInitializer($loader)); if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitfe47e554dced83cd1f1961109287683e::getInitializer($loader));
} else {
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
$loader->register(true); $loader->register(true);

View File

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

View File

@@ -156,17 +156,17 @@
}, },
{ {
"name": "woocommerce/subscriptions-core", "name": "woocommerce/subscriptions-core",
"version": "6.4.0", "version": "6.5.0",
"version_normalized": "6.4.0.0", "version_normalized": "6.5.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Automattic/woocommerce-subscriptions-core.git", "url": "https://github.com/Automattic/woocommerce-subscriptions-core.git",
"reference": "a94c9aab6d47f32461974ed09a4d3cad590f25b0" "reference": "19ca9b7cf2b48cba4abd6ecf811475382b9d6673"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/a94c9aab6d47f32461974ed09a4d3cad590f25b0", "url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/19ca9b7cf2b48cba4abd6ecf811475382b9d6673",
"reference": "a94c9aab6d47f32461974ed09a4d3cad590f25b0", "reference": "19ca9b7cf2b48cba4abd6ecf811475382b9d6673",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -177,9 +177,9 @@
"dave-liddament/sarb": "^1.1", "dave-liddament/sarb": "^1.1",
"phpunit/phpunit": "9.5.14", "phpunit/phpunit": "9.5.14",
"woocommerce/woocommerce-sniffs": "0.1.0", "woocommerce/woocommerce-sniffs": "0.1.0",
"yoast/phpunit-polyfills": "1.0.3" "yoast/phpunit-polyfills": "1.1.0"
}, },
"time": "2023-10-18T03:32:50+00:00", "time": "2023-11-09T04:27:49+00:00",
"type": "wordpress-plugin", "type": "wordpress-plugin",
"extra": { "extra": {
"phpcodesniffer-search-depth": 2 "phpcodesniffer-search-depth": 2
@@ -209,7 +209,7 @@
"description": "Sell products and services with recurring payments in your WooCommerce Store.", "description": "Sell products and services with recurring payments in your WooCommerce Store.",
"homepage": "https://github.com/Automattic/woocommerce-subscriptions-core", "homepage": "https://github.com/Automattic/woocommerce-subscriptions-core",
"support": { "support": {
"source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/6.4.0", "source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/6.5.0",
"issues": "https://github.com/Automattic/woocommerce-subscriptions-core/issues" "issues": "https://github.com/Automattic/woocommerce-subscriptions-core/issues"
}, },
"install-path": "../woocommerce/subscriptions-core" "install-path": "../woocommerce/subscriptions-core"

View File

@@ -1,22 +1,22 @@
<?php return array( <?php return array(
'root' => array( 'root' => array(
'name' => 'woocommerce/woocommerce-subscriptions', 'pretty_version' => 'dev-release/5.7.0',
'pretty_version' => 'dev-release/5.6.0', 'version' => 'dev-release/5.7.0',
'version' => 'dev-release/5.6.0',
'reference' => '434da4e19c4fde75e431338fa82595320bd5b6c1',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '05388f52bd8a4479997a2672e130fb44de3548f4',
'name' => 'woocommerce/woocommerce-subscriptions',
'dev' => false, 'dev' => false,
), ),
'versions' => array( 'versions' => array(
'composer/installers' => array( 'composer/installers' => array(
'pretty_version' => 'v1.12.0', 'pretty_version' => 'v1.12.0',
'version' => '1.12.0.0', 'version' => '1.12.0.0',
'reference' => 'd20a64ed3c94748397ff5973488761b22f6d3f19',
'type' => 'composer-plugin', 'type' => 'composer-plugin',
'install_path' => __DIR__ . '/./installers', 'install_path' => __DIR__ . '/./installers',
'aliases' => array(), 'aliases' => array(),
'reference' => 'd20a64ed3c94748397ff5973488761b22f6d3f19',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'roundcube/plugin-installer' => array( 'roundcube/plugin-installer' => array(
@@ -32,21 +32,21 @@
), ),
), ),
'woocommerce/subscriptions-core' => array( 'woocommerce/subscriptions-core' => array(
'pretty_version' => '6.4.0', 'pretty_version' => '6.5.0',
'version' => '6.4.0.0', 'version' => '6.5.0.0',
'reference' => 'a94c9aab6d47f32461974ed09a4d3cad590f25b0',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../woocommerce/subscriptions-core', 'install_path' => __DIR__ . '/../woocommerce/subscriptions-core',
'aliases' => array(), 'aliases' => array(),
'reference' => '19ca9b7cf2b48cba4abd6ecf811475382b9d6673',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'woocommerce/woocommerce-subscriptions' => array( 'woocommerce/woocommerce-subscriptions' => array(
'pretty_version' => 'dev-release/5.6.0', 'pretty_version' => 'dev-release/5.7.0',
'version' => 'dev-release/5.6.0', 'version' => 'dev-release/5.7.0',
'reference' => '434da4e19c4fde75e431338fa82595320bd5b6c1',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '05388f52bd8a4479997a2672e130fb44de3548f4',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
), ),

View File

@@ -351,4 +351,17 @@ jQuery( function ( $ ) {
); );
} }
} ); } );
/**
* When the auto-renewal is toggled on or off, show or hide the chosen payment methods meta fields.
*/
$( '#wc-subscription-auto-renew' ).on( 'change', function() {
var $payment_method_meta_elements = $( '#wcs_' + $( '#_payment_method' ).val() + '_fields' );
if ( $( this ).is( ':checked' ) ) {
$payment_method_meta_elements.fadeIn();
} else {
$payment_method_meta_elements.fadeOut();
}
} );
} ); } );

View File

@@ -1,5 +1,14 @@
*** WooCommerce Subscriptions Core Changelog *** *** WooCommerce Subscriptions Core Changelog ***
= 6.5.0 - 2023-11-09 =
* Add - When a customer toggles automatic renewals on or off via their My Account page, add a note to the subscription to record that event.
* Fix - When a subscription is flagged as requiring manual payments, allow admin users to turn on automatic payments for a subscription via the Edit Subscription page by selecting a new payment method.
* Fix - When processing an early renewal order, make sure the suspension count is reset back to 0 on payment complete.
* Fix - Ensure proper backfilling of subscription metadata (i.e. dates and cache) to the postmeta table when HPOS is enabled and compatibility mode (data syncing) is turned on.
* Fix - Fetch and update the `_cancelled_email_sent` meta in a HPOS compatibile way.
* Dev - Introduce a new wcs_get_subscription_grouping_key() function to generate a unique key for a subscription based on its billing schedule. This function uses the existing recurring cart key concept.
* Dev - Deprecate the WC_Subscriptions_Synchroniser::add_to_recurring_cart_key(). Use WC_Subscriptions_Synchroniser::add_to_recurring_product_grouping_key() instead.
= 6.4.0 - 2023-10-18 = = 6.4.0 - 2023-10-18 =
* Add - Use admin theme color and the correct WooCommerce colors. * Add - Use admin theme color and the correct WooCommerce colors.
* Fix - Resolve an issue that would cause 3rd party plugin edit product fields with the show_if_variable-subscription class to be incorrectly hidden. * Fix - Resolve an issue that would cause 3rd party plugin edit product fields with the show_if_variable-subscription class to be incorrectly hidden.

View File

@@ -185,7 +185,7 @@ class WCS_Meta_Box_Subscription_Data extends WC_Meta_Box_Order_Data {
echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( make_clickable( esc_html( $field_value ) ) ) . '</p>'; echo '<p><strong>' . esc_html( $field['label'] ) . ':</strong> ' . wp_kses_post( make_clickable( esc_html( $field_value ) ) ) . '</p>';
} }
echo '<p' . ( ( '' != $subscription->get_payment_method() ) ? ' class="' . esc_attr( $subscription->get_payment_method() ) . '"' : '' ) . '><strong>' . esc_html__( 'Payment Method', 'woocommerce-subscriptions' ) . ':</strong>' . wp_kses_post( nl2br( $subscription->get_payment_method_to_display() ) ); // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison echo '<p' . ( ( '' != $subscription->get_payment_method() ) ? ' class="' . esc_attr( $subscription->get_payment_method() ) . '"' : '' ) . '><strong>' . esc_html__( 'Payment method', 'woocommerce-subscriptions' ) . ':</strong>' . wp_kses_post( nl2br( $subscription->get_payment_method_to_display() ) ); // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
// Display help tip // Display help tip
if ( '' != $subscription->get_payment_method() && ! $subscription->is_manual() ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison if ( '' != $subscription->get_payment_method() && ! $subscription->is_manual() ) { // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison

View File

@@ -1778,7 +1778,12 @@ class WC_Subscription extends WC_Order {
// Add order note depending on initial payment // Add order note depending on initial payment
$this->add_order_note( __( 'Payment status marked complete.', 'woocommerce-subscriptions' ) ); $this->add_order_note( __( 'Payment status marked complete.', 'woocommerce-subscriptions' ) );
$this->update_status( 'active' ); // also saves the subscription // $this->update_status() only calls save if the status has changed.
if ( 'active' !== $this->get_status( 'edit' ) ) {
$this->update_status( 'active' );
} else {
$this->save();
}
do_action( 'woocommerce_subscription_payment_complete', $this ); do_action( 'woocommerce_subscription_payment_complete', $this );

View File

@@ -1022,59 +1022,12 @@ class WC_Subscriptions_Cart {
* Subscriptions groups products by billing schedule when calculating cart totals, so that shipping and other "per order" amounts * Subscriptions groups products by billing schedule when calculating cart totals, so that shipping and other "per order" amounts
* can be calculated for each group of items for each renewal. This method constructs a cart key based on the billing schedule * can be calculated for each group of items for each renewal. This method constructs a cart key based on the billing schedule
* to allow products on the same billing schedule to be grouped together - free trials and synchronisation is accounted for by * to allow products on the same billing schedule to be grouped together - free trials and synchronisation is accounted for by
* using the first renewal date (if any) for the susbcription. * using the first renewal date (if any) for the subscription.
* *
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
public static function get_recurring_cart_key( $cart_item, $renewal_time = '' ) { public static function get_recurring_cart_key( $cart_item, $renewal_time = '' ) {
return apply_filters( 'woocommerce_subscriptions_recurring_cart_key', wcs_get_subscription_grouping_key( $cart_item['data'], $renewal_time ), $cart_item );
$cart_key = '';
$product = $cart_item['data'];
$renewal_time = ! empty( $renewal_time ) ? $renewal_time : WC_Subscriptions_Product::get_first_renewal_payment_time( $product );
$interval = WC_Subscriptions_Product::get_interval( $product );
$period = WC_Subscriptions_Product::get_period( $product );
$length = WC_Subscriptions_Product::get_length( $product );
$trial_period = WC_Subscriptions_Product::get_trial_period( $product );
$trial_length = WC_Subscriptions_Product::get_trial_length( $product );
if ( $renewal_time > 0 ) {
$cart_key .= gmdate( 'Y_m_d_', $renewal_time );
}
// First start with the billing interval and period
switch ( $interval ) {
case 1:
if ( 'day' == $period ) {
$cart_key .= 'daily'; // always gotta be one exception
} else {
$cart_key .= sprintf( '%sly', $period );
}
break;
case 2:
$cart_key .= sprintf( 'every_2nd_%s', $period );
break;
case 3:
$cart_key .= sprintf( 'every_3rd_%s', $period ); // or sometimes two exceptions it would seem
break;
default:
$cart_key .= sprintf( 'every_%dth_%s', $interval, $period );
break;
}
if ( $length > 0 ) {
$cart_key .= '_for_';
$cart_key .= sprintf( '%d_%s', $length, $period );
if ( $length > 1 ) {
$cart_key .= 's';
}
}
if ( $trial_length > 0 ) {
$cart_key .= sprintf( '_after_a_%d_%s_trial', $trial_length, $trial_period );
}
return apply_filters( 'woocommerce_subscriptions_recurring_cart_key', $cart_key, $cart_item );
} }
/** /**

View File

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

View File

@@ -110,7 +110,7 @@ class WC_Subscriptions_Email {
public static function send_cancelled_email( $subscription ) { public static function send_cancelled_email( $subscription ) {
WC()->mailer(); WC()->mailer();
if ( $subscription->has_status( array( 'pending-cancel', 'cancelled' ) ) && 'true' !== get_post_meta( $subscription->get_id(), '_cancelled_email_sent', true ) ) { if ( $subscription->has_status( array( 'pending-cancel', 'cancelled' ) ) && 'true' !== $subscription->get_cancelled_email_sent() ) {
do_action( 'cancelled_subscription_notification', $subscription ); do_action( 'cancelled_subscription_notification', $subscription );
} }
} }

View File

@@ -112,7 +112,8 @@ class WC_Subscriptions_Synchroniser {
// If it's an initial sync order and the total is zero, and nothing needs to be shipped, do not reduce stock // If it's an initial sync order and the total is zero, and nothing needs to be shipped, do not reduce stock
add_filter( 'woocommerce_order_item_quantity', __CLASS__ . '::maybe_do_not_reduce_stock', 10, 3 ); add_filter( 'woocommerce_order_item_quantity', __CLASS__ . '::maybe_do_not_reduce_stock', 10, 3 );
add_filter( 'woocommerce_subscriptions_recurring_cart_key', __CLASS__ . '::add_to_recurring_cart_key', 10, 2 ); add_filter( 'woocommerce_subscriptions_recurring_cart_key', __CLASS__ . '::add_to_recurring_product_grouping_key', 10, 2 );
add_filter( 'woocommerce_subscriptions_item_grouping_key', __CLASS__ . '::add_to_recurring_product_grouping_key', 10, 2 );
// Add defaults for our options. // Add defaults for our options.
add_filter( 'default_option_' . self::$setting_id_days_no_fee, array( __CLASS__, 'option_default' ), 10, 3 ); add_filter( 'default_option_' . self::$setting_id_days_no_fee, array( __CLASS__, 'option_default' ), 10, 3 );
@@ -1207,18 +1208,27 @@ class WC_Subscriptions_Synchroniser {
} }
/** /**
* If the cart item is synced, add a '_synced' string to the recurring cart key. * Alters the subscription grouping key to ensure synced products are grouped separately.
* *
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @param string $key The subscription product's grouping key.
* @param array|WC_Order_Item_Product $item The cart item or order item that the key is being generated for.
*
* @return string The subscription product grouping key with a synced product flag if the product is synced.
*/ */
public static function add_to_recurring_cart_key( $cart_key, $cart_item ) { public static function add_to_recurring_product_grouping_key( $key, $item ) {
$product = $cart_item['data']; $product = false;
if ( false === strpos( $cart_key, '_synced' ) && self::is_product_synced( $product ) ) { if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
$cart_key .= '_synced'; $product = $item->get_product();
} elseif ( is_array( $item ) && isset( $item['data'] ) ) {
$product = $item['data'];
} }
return $cart_key; if ( $product && false === strpos( $key, '_synced' ) && self::is_product_synced( $product ) ) {
$key .= '_synced';
}
return $key;
} }
/** /**
@@ -1591,4 +1601,19 @@ class WC_Subscriptions_Synchroniser {
return $end_date; return $end_date;
} }
/**
* Alters the recurring cart item key to ensure synced products are grouped separately.
*
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
* @deprecated 6.5.0
*
* @param string $cart_key The recurring cart item key.
* @param array $cart_item The cart item's data.
*
* @return string The cart item recurring cart key with a synced product flag if the product is synced.
*/
public static function add_to_recurring_cart_key( $cart_key, $cart_item ) {
wcs_deprecated_function( __METHOD__, '6.5.0', __CLASS__ . '::add_to_recurring_product_grouping_key' );
return self::add_to_recurring_product_grouping_key( $cart_key, $cart_item );
}
} }

View File

@@ -18,7 +18,6 @@ class WCS_Change_Payment_Method_Admin {
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
public static function display_fields( $subscription ) { public static function display_fields( $subscription ) {
$payment_method = $subscription->get_payment_method(); $payment_method = $subscription->get_payment_method();
$valid_payment_methods = self::get_valid_payment_methods( $subscription ); $valid_payment_methods = self::get_valid_payment_methods( $subscription );
@@ -34,22 +33,18 @@ class WCS_Change_Payment_Method_Admin {
echo '<p class="form-field form-field-wide">'; echo '<p class="form-field form-field-wide">';
if ( count( $valid_payment_methods ) > 1 ) { if ( count( $valid_payment_methods ) > 1 ) {
echo '<label>' . esc_html__( 'Payment method', 'woocommerce-subscriptions' ) . '</label>';
$found_method = false;
echo '<label>' . esc_html__( 'Payment Method', 'woocommerce-subscriptions' ) . ':</label>';
echo '<select class="wcs_payment_method_selector" name="_payment_method" id="_payment_method" class="first">'; echo '<select class="wcs_payment_method_selector" name="_payment_method" id="_payment_method" class="first">';
foreach ( $valid_payment_methods as $gateway_id => $gateway_title ) { $selected_payment_method = $subscription->get_requires_manual_renewal() ? 'manual' : $subscription->get_payment_method();
echo '<option value="' . esc_attr( $gateway_id ) . '" ' . selected( $payment_method, $gateway_id, false ) . '>' . esc_html( $gateway_title ) . '</option>'; foreach ( $valid_payment_methods as $gateway_id => $gateway_title ) {
if ( $payment_method == $gateway_id ) { echo '<option value="' . esc_attr( $gateway_id ) . '" ' . selected( $selected_payment_method, $gateway_id, false ) . '>' . esc_html( $gateway_title ) . '</option>';
$found_method = true;
}
} }
echo '</select>'; echo '</select>';
} elseif ( count( $valid_payment_methods ) == 1 ) { } elseif ( count( $valid_payment_methods ) == 1 ) {
echo '<strong>' . esc_html__( 'Payment Method', 'woocommerce-subscriptions' ) . ':</strong><br/>' . esc_html( current( $valid_payment_methods ) ); echo '<strong>' . esc_html__( 'Payment method', 'woocommerce-subscriptions' ) . '</strong><br/>' . esc_html( current( $valid_payment_methods ) );
// translators: %s: gateway ID. // translators: %s: gateway ID.
echo wcs_help_tip( sprintf( _x( 'Gateway ID: [%s]', 'The gateway ID displayed on the Edit Subscriptions screen when editing payment method.', 'woocommerce-subscriptions' ), key( $valid_payment_methods ) ) ); echo wcs_help_tip( sprintf( _x( 'Gateway ID: [%s]', 'The gateway ID displayed on the Edit Subscriptions screen when editing payment method.', 'woocommerce-subscriptions' ), key( $valid_payment_methods ) ) );
echo '<input type="hidden" value="' . esc_attr( key( $valid_payment_methods ) ) . '" id="_payment_method" name="_payment_method">'; echo '<input type="hidden" value="' . esc_attr( key( $valid_payment_methods ) ) . '" id="_payment_method" name="_payment_method">';
@@ -91,12 +86,10 @@ class WCS_Change_Payment_Method_Admin {
} }
echo '</div>'; echo '</div>';
} }
} }
wp_nonce_field( 'wcs_change_payment_method_admin', '_wcsnonce' ); wp_nonce_field( 'wcs_change_payment_method_admin', '_wcsnonce' );
} }
/** /**
@@ -149,6 +142,13 @@ class WCS_Change_Payment_Method_Admin {
// Update the payment method for manual only if it has changed. // Update the payment method for manual only if it has changed.
if ( ! $subscription->is_manual() || 'manual' !== $payment_method ) { if ( ! $subscription->is_manual() || 'manual' !== $payment_method ) {
// If the subscription is being changed away from manual and it is flagged as requiring manual payments turn on automatic renewals.
if ( 'manual' !== $payment_method && $subscription->get_requires_manual_renewal() && ! wcs_is_manual_renewal_required() && $payment_gateway->supports( 'subscriptions' ) ) {
$subscription->set_requires_manual_renewal( false );
// Translators: Placeholder is the payment gateway title.
$subscription->add_order_note( sprintf( __( 'Admin turned on automatic renewals by changing payment method to "%s" via the Edit Subscription screen.', 'woocommerce-subscriptions' ), $payment_gateway->get_title() ), false, true );
}
$subscription->set_payment_method( $payment_gateway, $payment_method_meta ); $subscription->set_payment_method( $payment_gateway, $payment_method_meta );
$subscription->save(); $subscription->save();
} }

View File

@@ -98,6 +98,7 @@ class WCS_My_Account_Auto_Renew_Toggle {
if ( $subscription && self::can_user_toggle_auto_renewal( $subscription ) ) { if ( $subscription && self::can_user_toggle_auto_renewal( $subscription ) ) {
$subscription->set_requires_manual_renewal( true ); $subscription->set_requires_manual_renewal( true );
$subscription->add_order_note( __( 'Customer turned off automatic renewals via their My Account page.', 'woocommerce-subscriptions' ) );
$subscription->save(); $subscription->save();
self::send_ajax_response( $subscription ); self::send_ajax_response( $subscription );
@@ -122,6 +123,7 @@ class WCS_My_Account_Auto_Renew_Toggle {
if ( wc_get_payment_gateway_by_order( $subscription ) && self::can_user_toggle_auto_renewal( $subscription ) ) { if ( wc_get_payment_gateway_by_order( $subscription ) && self::can_user_toggle_auto_renewal( $subscription ) ) {
$subscription->set_requires_manual_renewal( false ); $subscription->set_requires_manual_renewal( false );
$subscription->add_order_note( __( 'Customer turned on automatic renewals via their My Account page.', 'woocommerce-subscriptions' ) );
$subscription->save(); $subscription->save();
self::send_ajax_response( $subscription ); self::send_ajax_response( $subscription );

View File

@@ -882,4 +882,112 @@ class WCS_Orders_Table_Subscription_Data_Store extends \Automattic\WooCommerce\I
return $results ? array_combine( array_column( $results, 'status' ), array_map( 'absint', array_column( $results, 'cnt' ) ) ) : array(); return $results ? array_combine( array_column( $results, 'status' ), array_map( 'absint', array_column( $results, 'cnt' ) ) ) : array();
} }
/**
* Fetches the subscription's start date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_start( $subscription ) {
return $subscription->get_date( 'start' );
}
/**
* Fetches the subscription's trial end date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_trial_end( $subscription ) {
return $subscription->get_date( 'trial_end' );
}
/**
* Fetches the subscription's next payment date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_next_payment( $subscription ) {
return $subscription->get_date( 'next_payment' );
}
/**
* Fetches the subscription's cancelled date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_cancelled( $subscription ) {
return $subscription->get_date( 'cancelled' );
}
/**
* Fetches the subscription's end date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_end( $subscription ) {
return $subscription->get_date( 'end' );
}
/**
* Fetches the subscription's payment retry date.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return string
*/
public function get_schedule_payment_retry( $subscription ) {
return $subscription->get_date( 'payment_retry' );
}
/**
* Returns a list of subscriptions's renewal order IDs stored in cache meta.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return array
*/
public function get_renewal_order_ids_cache( $subscription ) {
return $subscription->get_meta( '_subscription_renewal_order_ids_cache' );
}
/**
* Returns a list of subscriptions's resubscribe order IDs stored in cache meta.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return array
*/
public function get_resubscribe_order_ids_cache( $subscription ) {
return $subscription->get_meta( '_subscription_resubscribe_order_ids_cache' );
}
/**
* Returns a list of subscriptions's switch order IDs stored in cache meta.
* This method is called by @see parent::backfill_post_record() when backfilling subscriptions details to WP_Post DB.
*
* @param \WC_Subscription $subscription Subscription object.
*
* @return array
*/
public function get_switch_order_ids_cache( $subscription ) {
return $subscription->get_meta( '_subscription_switch_order_ids_cache' );
}
} }

View File

@@ -60,6 +60,23 @@ class WCS_Subscription_Data_Store_CPT extends WC_Order_Data_Store_CPT implements
'_subscription_switch_data' => 'switch_data', '_subscription_switch_data' => 'switch_data',
); );
/**
* Custom setters for subscription internal props in the form meta_key => set_|get_{value}.
*
* @var string[]
*/
protected $internal_data_store_key_getters = array(
'_schedule_start' => 'schedule_start',
'_schedule_trial_end' => 'schedule_trial_end',
'_schedule_next_payment' => 'schedule_next_payment',
'_schedule_cancelled' => 'schedule_cancelled',
'_schedule_end' => 'schedule_end',
'_schedule_payment_retry' => 'schedule_payment_retry',
'_subscription_renewal_order_ids_cache' => 'renewal_order_ids_cache',
'_subscription_resubscribe_order_ids_cache' => 'resubscribe_order_ids_cache',
'_subscription_switch_order_ids_cache' => 'switch_order_ids_cache',
);
/** /**
* Constructor. * Constructor.
*/ */
@@ -604,4 +621,146 @@ class WCS_Subscription_Data_Store_CPT extends WC_Order_Data_Store_CPT implements
public function get_subscriptions_count_by_status() { public function get_subscriptions_count_by_status() {
return (array) wp_count_posts( 'shop_subscription' ); return (array) wp_count_posts( 'shop_subscription' );
} }
/**
* Sets the subscription's start date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_start( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_start', $date );
}
/**
* Sets the subscription's trial end date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_trial_end( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_trial_end', $date );
}
/**
* Sets the subscription's next payment date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_next_payment( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_next_payment', $date );
}
/**
* Sets the subscription's cancelled date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_cancelled( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_cancelled', $date );
}
/**
* Sets the subscription's end date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_end( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_end', $date );
}
/**
* Sets the subscription's payment retry date.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param string $date
*/
public function set_schedule_payment_retry( $subscription, $date ) {
update_post_meta( $subscription->get_id(), '_schedule_payment_retry', $date );
}
/**
* Manually sets the list of subscription's renewal order IDs stored in cache.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param array $renewal_order_ids
*/
public function set_renewal_order_ids_cache( $subscription, $renewal_order_ids ) {
$this->cleanup_backfill_related_order_cache_duplicates( $subscription, 'renewal' );
update_post_meta( $subscription->get_id(), '_subscription_renewal_order_ids_cache', $renewal_order_ids );
}
/**
* Manually sets the list of subscription's resubscribe order IDs stored in cache.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param array $resubscribe_order_ids
*/
public function set_resubscribe_order_ids_cache( $subscription, $resubscribe_order_ids ) {
$this->cleanup_backfill_related_order_cache_duplicates( $subscription, 'resubscribe' );
update_post_meta( $subscription->get_id(), '_subscription_resubscribe_order_ids_cache', $resubscribe_order_ids );
}
/**
* Manually sets the list of subscription's switch order IDs stored in cache.
*
* This method is not intended for public use and is called by @see OrdersTableDataStore::backfill_post_record()
* when backfilling subscription data to the WP_Post database.
*
* @param WC_Subscription $subscription
* @param array $switch_order_ids
*/
public function set_switch_order_ids_cache( $subscription, $switch_order_ids ) {
$this->cleanup_backfill_related_order_cache_duplicates( $subscription, 'switch' );
update_post_meta( $subscription->get_id(), '_subscription_switch_order_ids_cache', $switch_order_ids );
}
/**
* Deletes a subscription's related order cache - including any duplicates.
*
* WC core between v8.1 and v8.4 would duplicate related order cache meta when backfilling the post record. This method deletes all
* instances of a order type cache (duplicates included). It is intended to be called before setting the cache manually.
*
* Note: this function assumes that the fix to WC (listed below) will be included in 8.4. If it's pushed back, this function will need to be updated,
* if it's brought forward to 8.3, it can be updated but is not strictly required.
*
* @see https://github.com/woocommerce/woocommerce/pull/41281
* @see https://github.com/Automattic/woocommerce-subscriptions-core/pull/538
*
* @param WC_Subscription $subscription The Subscription.
* @param string $relationship_type The type of subscription related order relationship to delete. One of: 'renewal', 'resubscribe', 'switch'.
*/
private function cleanup_backfill_related_order_cache_duplicates( $subscription, $relationship_type ) {
// Delete the related order cache on versions of WC after 8.1 but before 8.4.
if ( ! wcs_is_woocommerce_pre( '8.1' ) && wcs_is_woocommerce_pre( '8.4' ) ) {
delete_post_meta( $subscription->get_id(), "_subscription_{$relationship_type}_order_ids_cache" );
}
}
} }

View File

@@ -83,7 +83,9 @@ class WCS_Email_Cancelled_Subscription extends WC_Email {
return; return;
} }
update_post_meta( $subscription->get_id(), '_cancelled_email_sent', 'true' ); $subscription->set_cancelled_email_sent( 'true' );
$subscription->save();
$this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() );
} }

View File

@@ -979,3 +979,19 @@ function wcs_order_contains_early_renewal( $order ) {
*/ */
return apply_filters( 'woocommerce_subscriptions_is_early_renewal_order', $is_early_renewal, $order ); return apply_filters( 'woocommerce_subscriptions_is_early_renewal_order', $is_early_renewal, $order );
} }
/**
* Generates a key for grouping subscription products with the same billing schedule.
*
* Used by the orders/<id>/subscriptions REST API endpoint to group order items into subscriptions.
*
* @see https://woocommerce.com/document/subscriptions/develop/multiple-subscriptions/#section-3
*
* @param WC_Order_Item_Product $item The order item to generate the key for.
* @param int $renewal_time The timestamp of the first renewal payment.
*
* @return string The item's subscription grouping key.
*/
function wcs_get_subscription_item_grouping_key( $item, $renewal_time = '' ) {
return apply_filters( 'woocommerce_subscriptions_item_grouping_key', wcs_get_subscription_grouping_key( $item->get_product(), $renewal_time ), $item );
}

View File

@@ -437,3 +437,66 @@ function wcs_calculate_min_max_variations( $variations_data ) {
'identical' => $subscription_details_identical, 'identical' => $subscription_details_identical,
); );
} }
/**
* Generates a key for grouping subscription products with the same billing schedule.
*
* Used in a frontend cart and checkout context to group items by a recurring cart key for use in generating recurring carts.
* Used by the orders/<id>/subscriptions REST API endpoint to group order items into subscriptions.
*
* @see https://woocommerce.com/document/subscriptions/develop/multiple-subscriptions/#section-3
*
* @param WC_Product $product The product to generate the key for.
* @param int $renewal_time The timestamp of the first renewal payment.
*
* @return string The subscription product grouping key.
*/
function wcs_get_subscription_grouping_key( $product, $renewal_time = 0 ) {
$key = '';
$renewal_time = ! empty( $renewal_time ) ? $renewal_time : WC_Subscriptions_Product::get_first_renewal_payment_time( $product );
$interval = WC_Subscriptions_Product::get_interval( $product );
$period = WC_Subscriptions_Product::get_period( $product );
$length = WC_Subscriptions_Product::get_length( $product );
$trial_period = WC_Subscriptions_Product::get_trial_period( $product );
$trial_length = WC_Subscriptions_Product::get_trial_length( $product );
if ( $renewal_time > 0 ) {
$key .= gmdate( 'Y_m_d_', $renewal_time );
}
// First start with the billing interval and period.
switch ( $interval ) {
case 1:
if ( 'day' === $period ) {
$key .= 'daily';
} else {
$key .= sprintf( '%sly', $period );
}
break;
case 2:
$key .= sprintf( 'every_2nd_%s', $period );
break;
case 3:
$key .= sprintf( 'every_3rd_%s', $period ); // or sometimes two exceptions it would seem
break;
default:
$key .= sprintf( 'every_%dth_%s', $interval, $period );
break;
}
if ( $length > 0 ) {
$key .= '_for_';
$key .= sprintf( '%d_%s', $length, $period );
if ( $length > 1 ) {
$key .= 's';
}
}
if ( $trial_length > 0 ) {
$key .= sprintf( '_after_a_%d_%s_trial', $trial_length, $trial_period );
}
return apply_filters( 'wcs_subscription_product_grouping_key', $key, $product, $renewal_time );
}

View File

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

View File

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