Updates to 6.3.2

This commit is contained in:
WooCommerce
2024-06-13 10:13:07 +00:00
parent fbfd2242d2
commit f98586942f
27 changed files with 1131 additions and 167 deletions

View File

@@ -2,6 +2,7 @@
"plugins": [ "plugins": [
"https://downloads.wordpress.org/plugin/woocommerce.zip", "https://downloads.wordpress.org/plugin/woocommerce.zip",
"https://downloads.wordpress.org/plugin/email-log.zip", "https://downloads.wordpress.org/plugin/email-log.zip",
"https://github.com/woocommerce/woocommerce-gateway-dummy/releases/download/1.0.8/woocommerce-gateway-dummy.zip",
".", ".",
"./tests/e2e/test-configuration-plugin" "./tests/e2e/test-configuration-plugin"
], ],

View File

@@ -1,5 +1,14 @@
*** WooCommerce Subscriptions Changelog *** *** WooCommerce Subscriptions Changelog ***
2024-06-13 - version 6.4.0
* Add: New WP CLI support to manage subscriptions via command line.
* Add: Introduce wc/v2 subscription REST API endpoints.
* Fix: label improvement on my subscription page template.
* Fix: Regenerate subscriptions related order caches (renewal, resubscribe, switch) if it's stored as an invalid value to prevent fatal errors.
* Update: Show "FREE" instead of 0 when there is no shipping cost in the recurring totals section of the Cart and Checkout blocks (requires WooCommerce 9.0+).
* Dev: New function wcs_set_recurring_item_total() to set line item totals that have been copied from an initial order to their proper recurring totals (i.e. remove sign-up fees).
* Dev: Updated subscriptions-core to 7.2.0.
2024-05-24 - version 6.3.2 2024-05-24 - version 6.3.2
* Fix: Prevent overriding line item totals provided in request data when creating Orders via the REST API. * Fix: Prevent overriding line item totals provided in request data when creating Orders via the REST API.

View File

@@ -626,7 +626,7 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
wcs_copy_order_item( $item, $subscription_item ); wcs_copy_order_item( $item, $subscription_item );
// Don't include sign-up fees or $0 trial periods when setting the subscriptions item totals. // Don't include sign-up fees or $0 trial periods when setting the subscriptions item totals.
$this->maybe_set_recurring_item_total( $subscription_item ); wcs_set_recurring_item_total( $subscription_item );
$subscription_item->save(); $subscription_item->save();
@@ -718,41 +718,4 @@ class WC_REST_Subscriptions_Controller extends WC_REST_Orders_Controller {
return rest_ensure_response( $subscriptions ); return rest_ensure_response( $subscriptions );
} }
/**
* Set the subscription item total to its recurring product price.
*
* This function ensures that sign-up fees and/or $0 trial periods are not carried over from the initial order to the subscription.
* Note: If the line item has a custom total set by the merchant, don't override it with the recurring price.
*
* @param WC_Order_Item $item Subscription line item.
*
*/
private function maybe_set_recurring_item_total( &$item ) {
$product = $item->get_product();
if ( ! $product ) {
return;
}
$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product );
$sign_up_fee = is_numeric( $sign_up_fee ) ? (float) $sign_up_fee : 0;
$trial_length = WC_Subscriptions_Product::get_trial_length( $product );
$recurring_price = (float) $product->get_price();
$initial_price = $trial_length > 0 ? $sign_up_fee : $recurring_price + $sign_up_fee;
$initial_total = wc_get_price_excluding_tax( $product, [ 'qty' => $item->get_quantity(), 'price' => $initial_price ] );
// Check if a custom item total was set on the order. If so, don't override it.
if ( (float) $item->get_subtotal() !== $initial_total ) {
return;
}
$recurring_total = wc_get_price_excluding_tax( $product, [ 'qty' => $item->get_quantity(), 'price' => $recurring_price ] );
$item->set_props( [
'subtotal' => $recurring_total,
'total' => $recurring_total,
] );
}
} }

View File

@@ -0,0 +1,33 @@
<?php
/**
* REST API subscription notes controller
*
* Handles requests to the /subscription/<id>/notes endpoint.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* REST API Subscription Notes controller class.
*
* @package WooCommerce_Subscriptions/API
* @extends WC_REST_Order_Notes_Controller
*/
class WC_REST_Subscription_Notes_V2_Controller extends WC_REST_Order_Notes_V2_Controller {
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'subscriptions/(?P<order_id>[\d]+)/notes';
/**
* Post type.
*
* @var string
*/
protected $post_type = 'shop_subscription';
}

View File

@@ -0,0 +1,787 @@
<?php
/**
* REST API Subscriptions V2 Controller
*
* Handles requests to the wc/v2/subscriptions and wc/v2/orders/ID/subscriptions endpoint.
*
* @since 6.4.0
* @package WooCommerce Subscriptions\Rest Api
*/
defined( 'ABSPATH' ) || exit;
class WC_REST_Subscriptions_V2_Controller extends WC_REST_Orders_V2_Controller {
/**
* @var string Route base.
*/
protected $rest_base = 'subscriptions';
/**
* @var string The post type.
*/
protected $post_type = 'shop_subscription';
/**
* Register the routes for the subscriptions endpoint.
*
* GET|POST /subscriptions
* GET|PUT|DELETE /subscriptions/<subscription_id>
* GET /subscriptions/status
* GET /subscriptions/<subscription_id>/orders
* POST /orders/<order_id>/subscriptions
*
* @since 6.4.0
*/
public function register_routes() {
parent::register_routes();
register_rest_route( $this->namespace, "/{$this->rest_base}/statuses", [ // nosemgrep: audit.php.wp.security.rest-route.permission-callback.return-true -- /subscriptions/statuses is a public endpoint and doesn't need any permission checks.
[
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_statuses' ],
'permission_callback' => '__return_true',
],
'schema' => [ $this, 'get_statuses_schema' ],
] );
register_rest_route( $this->namespace, "/{$this->rest_base}/(?P<id>[\d]+)/orders", [
[
'methods' => WP_REST_Server::READABLE,
'callback' => [ $this, 'get_subscription_orders' ],
'permission_callback' => [ $this, 'get_items_permissions_check' ],
'args' => $this->get_collection_params(),
],
'schema' => [ $this, 'get_subscription_orders_schema' ],
] );
register_rest_route( $this->namespace, "/orders/(?P<id>[\d]+)/{$this->rest_base}", [
[
'methods' => WP_REST_Server::CREATABLE,
'callback' => [ $this, 'create_subscriptions_from_order' ],
'permission_callback' => [ $this, 'create_item_permissions_check' ],
'args' => $this->get_collection_params(),
],
'schema' => [ $this, 'create_subscriptions_from_order_schema' ],
] );
}
/**
* Gets the request object. Return false if the ID is not a subscription.
*
* @since 6.4.0
*
* @param int $id Object ID.
*
* @return WC_Subscription|bool
*/
protected function get_object( $id ) {
$subscription = wcs_get_subscription( $id );
if ( ! $subscription || ! is_a( $subscription, 'WC_Subscription' ) ) {
return false;
}
return $subscription;
}
/**
* Prepare a single subscription output for response.
*
* @since 6.4.0
*
* @param WC_Data $object Subscription object.
* @param WP_REST_Request $request Request object.
*
* @return WP_REST_Response
*/
public function prepare_object_for_response( $object, $request ) {
$response = parent::prepare_object_for_response( $object, $request );
// When generating the `/subscriptions/[id]/orders` response this function is called to generate related-order data so exit early if this isn't a subscription.
if ( ! wcs_is_subscription( $object ) ) {
return $response;
}
// Add subscription specific data to the base order response data.
$response->data['billing_period'] = $object->get_billing_period();
$response->data['billing_interval'] = $object->get_billing_interval();
foreach ( wcs_get_subscription_date_types() as $date_type => $date_name ) {
$date = $object->get_date( wcs_normalise_date_type_key( $date_type ) );
$response->data[ $date_type . '_date' ] = ( ! empty( $date ) ) ? wc_rest_prepare_date_response( $date, false ) : '';
$response->data[ $date_type . '_date_gmt' ] = ( ! empty( $date ) ) ? wc_rest_prepare_date_response( $date ) : '';
}
// Some base WC_Order dates need to be pulled from the subscription object to be correct.
$response->data['date_paid'] = wc_rest_prepare_date_response( $object->get_date_paid(), false );
$response->data['date_paid_gmt'] = wc_rest_prepare_date_response( $object->get_date_paid() );
$response->data['date_completed'] = wc_rest_prepare_date_response( $object->get_date_completed(), false );
$response->data['date_completed_gmt'] = wc_rest_prepare_date_response( $object->get_date_completed() );
// Include resubscribe data.
$resubscribed_subscriptions = array_filter( $object->get_related_orders( 'ids', 'resubscribe' ), 'wcs_is_subscription' );
$response->data['resubscribed_from'] = strval( $object->get_meta( '_subscription_resubscribe' ) );
$response->data['resubscribed_subscription'] = strval( reset( $resubscribed_subscriptions ) ); // Subscriptions can only be resubscribed to once so return the first and only element.
// Include the removed line items.
$response->data['removed_line_items'] = [];
foreach ( $object->get_items( 'line_item_removed' ) as $item ) {
$response->data['removed_line_items'][] = $this->get_order_item_data( $item );
}
// Remove non-subscription properties
unset( $response->data['cart_hash'] );
unset( $response->data['transaction_id'] );
return $response;
}
/**
* Gets the /subscriptions/statuses response.
*
* @since 6.4.0
*
* @return WP_REST_Response The response object.
*/
public function get_statuses() {
return rest_ensure_response( wcs_get_subscription_statuses() );
}
/**
* Gets the /subscriptions/[id]/orders response.
*
* @since 6.4.0
*
* @param WP_REST_Request $request The request object.
*
* @return WP_Error|WP_REST_Response $response The response or an error if one occurs.
*/
public function get_subscription_orders( $request ) {
$id = absint( $request['id'] );
if ( empty( $id ) || ! wcs_is_subscription( $id ) ) {
return new WP_Error( 'woocommerce_rest_invalid_shop_subscription_id', __( 'Invalid subscription ID.', 'woocommerce-subscriptions' ), [ 'status' => 404 ] );
}
$subscription = wcs_get_subscription( $id );
if ( ! $subscription ) {
return new WP_Error( 'woocommerce_rest_invalid_shop_subscription_id', sprintf( __( 'Failed to load subscription object with the ID %d.', 'woocommerce-subscriptions' ), $id ), [ 'status' => 404 ] );
}
$orders = [];
foreach ( [ 'parent', 'renewal', 'switch' ] as $order_type ) {
foreach ( $subscription->get_related_orders( 'ids', $order_type ) as $order_id ) {
if ( ! wc_rest_check_post_permissions( 'shop_order', 'read', $order_id ) ) {
continue;
}
// Validate that the order can be loaded before trying to generate a response object for it.
$order = wc_get_order( $order_id );
if ( ! $order ) {
continue;
}
$response = parent::prepare_object_for_response( $order, $request );
// Add the order's relationship to the response.
$response->data['order_type'] = $order_type . '_order';
$orders[] = $this->prepare_response_for_collection( $response );
}
}
$response = rest_ensure_response( $orders );
$response->header( 'X-WP-Total', count( $orders ) );
$response->header( 'X-WP-TotalPages', 1 );
return apply_filters( 'wcs_rest_subscription_orders_response', $response, $request );
}
/**
* Overrides WC_REST_Orders_V2_Controller::get_order_statuses() so that subscription statuses are
* validated correctly.
*
* @since 6.4.0
*
* @return array An array of valid subscription statuses.
*/
protected function get_order_statuses() {
$subscription_statuses = [];
foreach ( wcs_get_subscription_statuses() as $status => $status_name ) {
$subscription_statuses[] = str_replace( 'wc-', '', $status );
}
return $subscription_statuses;
}
/**
* Prepares a single subscription for creation or update.
*
* @since 6.4.0
*
* @param WP_REST_Request $request Request object.
* @param bool $creating If the request is for creating a new object.
*
* @return WP_Error|WC_Subscription
*/
public function prepare_object_for_database( $request, $creating = false ) {
$id = isset( $request['id'] ) ? absint( $request['id'] ) : 0;
$subscription = new WC_Subscription( $id );
$schema = $this->get_item_schema();
$data_keys = array_keys( array_filter( $schema['properties'], [ $this, 'filter_writable_props' ] ) );
// Prepare variables for properties which need to be saved late (like status) or in a group (dates and payment data).
$status = '';
$payment_method = '';
$payment_meta = [];
$dates = [];
// Both setting (set_status()) and updating (update_status()) are valid ways for requests to set a subscription's status.
$status_transition = 'set';
foreach ( $data_keys as $i => $key ) {
$value = $request[ $key ];
if ( is_null( $value ) ) {
continue;
}
switch ( $key ) {
case 'parent_id':
$subscription->set_parent_id( $value );
break;
case 'transition_status':
$status_transition = 'update';
case 'status':
// This needs to be done later so status changes take into account other data like dates.
$status = $value;
break;
case 'billing':
case 'shipping':
$this->update_address( $subscription, $value, $key );
break;
case 'start_date':
case 'trial_end_date':
case 'next_payment_date':
case 'cancelled_date':
case 'end_date':
// Group all the subscription date properties so they can be validated together.
$dates[ $key ] = $value;
break;
case 'payment_method':
$payment_method = $value;
break;
case 'payment_details':
// Format the value in a way payment gateways expect so it can be validated.
$payment_meta = $value;
break;
case 'line_items':
case 'shipping_lines':
case 'fee_lines':
if ( is_array( $value ) ) {
foreach ( $value as $item ) {
if ( is_array( $item ) ) {
if ( $this->item_is_null( $item ) || ( isset( $item['quantity'] ) && 0 === $item['quantity'] ) ) {
if ( isset( $item['id'] ) ) {
$subscription->remove_item( $item['id'] );
}
} else {
$this->set_item( $subscription, $key, $item );
}
}
}
}
break;
case 'meta_data':
if ( is_array( $value ) ) {
foreach ( $value as $meta ) {
$subscription->update_meta_data( $meta['key'], $meta['value'], isset( $meta['id'] ) ? $meta['id'] : '' );
}
}
break;
default:
if ( is_callable( [ $subscription, "set_{$key}" ] ) ) {
$subscription->{"set_{$key}"}( $value );
}
break;
}
}
if ( ! empty( $payment_method ) ) {
$this->update_payment_method( $subscription, $payment_method, $payment_meta );
}
if ( ! empty( $dates ) ) {
// If the start date is not set in the request when a subscription is being created, set its default to now.
if ( empty( $id ) && ! isset( $dates['start_date'] ) ) {
$dates['start_date'] = gmdate( 'Y-m-d H:i:s' );
}
try {
$subscription->update_dates( $dates );
} catch ( Exception $e ) {
throw new WC_REST_Exception( 'woocommerce_rest_invalid_payment_data', sprintf( __( 'Subscription dates could not be set. Error message: %s', 'woocommerce-subscriptions' ), $e->getMessage() ), 400 );
}
}
if ( ! empty( $status ) ) {
if ( 'set' === $status_transition ) {
$subscription->set_status( $status );
} else {
$subscription->update_status( $status );
$request['status'] = $status; // Set the request status so parent::save_object() doesn't set it to the default 'pending' status.
}
}
/**
* Filters an object before it is inserted via the REST API.
*
* The dynamic portion of the hook name, `$this->post_type`,
* refers to the object type slug.
*
* @param WC_Subscription $subscription The subscription object.
* @param WP_REST_Request $request Request object.
* @param bool $creating If is creating a new object.
*/
return apply_filters( "woocommerce_rest_pre_insert_{$this->post_type}_object", $subscription, $request, $creating );
}
/**
* Adds additional item schema information for subscription requests.
*
* @since 6.4.0
*
* @return array
*/
public function get_item_schema() {
// If this is a request for a subscription's orders, return the subscription orders schema.
if ( $this->request instanceof WP_REST_Request && preg_match( "#/{$this->rest_base}/(?P<id>[\d]+)/orders#", $this->request->get_route() ) ) {
return $this->get_subscription_orders_schema();
}
$schema = parent::get_item_schema();
// Base order schema overrides.
$schema['properties']['status']['description'] = __( 'Subscription status.', 'woocommerce-subscriptions' );
$schema['properties']['status']['enum'] = $this->get_order_statuses();
$schema['properties']['created_via']['description'] = __( 'Where the subscription was created.', 'woocommerce-subscriptions' );
$schema['properties']['currency']['description'] = __( 'Currency the subscription was created with, in ISO format.', 'woocommerce-subscriptions' );
$schema['properties']['date_created']['description'] = __( "The date the subscription was created, in the site's timezone.", 'woocommerce-subscriptions' );
$schema['properties']['date_created_gmt']['description'] = __( 'The date the subscription was created, as GMT.', 'woocommerce-subscriptions' );
$schema['properties']['date_modified']['description'] = __( "The date the subscription was last modified, in the site's timezone.", 'woocommerce-subscriptions' );
$schema['properties']['date_modified_gmt']['description'] = __( 'The date the subscription was last modified, as GMT.', 'woocommerce-subscriptions' );
$schema['properties']['customer_id']['description'] = __( 'User ID who owns the subscription.', 'woocommerce-subscriptions' );
unset( $schema['properties']['transaction_id'] );
unset( $schema['properties']['refunds'] );
unset( $schema['properties']['set_paid'] );
unset( $schema['properties']['cart_hash'] );
// Add subscription schema.
$schema['properties'] += [
'transition_status' => [
'description' => __( 'The status to transition a subscription to.', 'woocommerce-subscriptions' ),
'type' => 'string',
'context' => [ 'edit' ],
'enum' => $this->get_order_statuses(),
],
'billing_interval' => [
'description' => __( 'The number of billing periods between subscription renewals.', 'woocommerce-subscriptions' ),
'type' => 'integer',
'context' => [ 'view', 'edit' ],
],
'billing_period' => [
'description' => __( 'Billing period for the subscription.', 'woocommerce-subscriptions' ),
'type' => 'string',
'enum' => array_keys( wcs_get_subscription_period_strings() ),
'context' => [ 'view', 'edit' ],
],
'payment_details' => [
'description' => __( 'Subscription payment details.', 'woocommerce-subscriptions' ),
'type' => 'object',
'context' => [ 'edit' ],
'properties' => [
'post_meta' => [
'description' => __( 'Payment method meta and token in a post_meta_key: token format.', 'woocommerce-subscriptions' ),
'type' => 'object',
'context' => [ 'edit' ],
],
'user_meta' => [
'description' => __( 'Payment method meta and token in a user_meta_key : token format.', 'woocommerce-subscriptions' ),
'type' => 'object',
'context' => [ 'view' ],
],
],
],
'start_date' => [
'description' => __( "The subscription's start date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time',
'context' => [ 'view', 'edit' ],
],
'trial_end_date' => [
'description' => __( "The subscription's trial end date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time',
'context' => [ 'view', 'edit' ],
],
'next_payment_date' => [
'description' => __( "The subscription's next payment date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time',
'context' => [ 'view', 'edit' ],
],
'cancelled_date' => [
'description' => __( "The subscription's cancelled date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time',
'context' => [ 'view', 'edit' ],
],
'end_date' => [
'description' => __( "The subscription's end date, as GMT.", 'woocommerce-subscriptions' ),
'type' => 'date-time',
'context' => [ 'view', 'edit' ],
],
];
return $schema;
}
/**
* Get the query params for collections.
*
* @since 6.4.0
*
* @return array
*/
public function get_collection_params() {
$params = parent::get_collection_params();
// Override the base order status description to be subscription specific.
$params['status']['description'] = __( 'Limit result set to subscriptions which have specific statuses.', 'woocommerce-subscriptions' );
return $params;
}
/**
* Gets an object's links to include in the response.
*
* Because this class also handles retrieving order data, we need
* to edit the links generated so the correct REST API href is included
* when its generated for an order.
*
* @since 6.4.0
*
* @param WC_Data $object Object data.
* @param WP_REST_Request $request Request object.
*
* @return array Links for the given object.
*/
protected function prepare_links( $object, $request ) {
$links = parent::prepare_links( $object, $request );
if ( isset( $links['self'] ) && wcs_is_order( $object ) ) {
$links['self'] = [
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, 'orders', $object->get_id() ) ),
];
}
return $links;
}
/**
* Updates a subscription's payment method and meta from data provided in a REST API request.
*
* @since 6.4.0
*
* @param WC_Subscription $subscription The subscription to update.
* @param string $payment_method The ID of the payment method to set.
* @param array $payment_meta The payment method meta.
*
* @return void
*/
public function update_payment_method( $subscription, $payment_method, $payment_meta ) {
$updating_subscription = (bool) $subscription->get_id();
try {
if ( $updating_subscription && ! array_key_exists( $payment_method, WCS_Change_Payment_Method_Admin::get_valid_payment_methods( $subscription ) ) ) {
// translators: placeholder is the payment method ID.
throw new Exception( sprintf( __( 'The %s payment gateway does not support admin changing the payment method.', 'woocommerce-subscriptions' ), $payment_method ) );
}
// Format the payment meta in the way payment gateways expect so it can be validated.
$payment_method_meta = [];
foreach ( $payment_meta as $table => $meta ) {
foreach ( $meta as $meta_key => $value ) {
$payment_method_meta[ $table ][ $meta_key ] = [ 'value' => $value ];
}
}
$subscription->set_payment_method( $payment_method, $payment_method_meta );
} catch ( Exception $e ) {
$subscription->set_payment_method();
$subscription->save();
// translators: 1$: gateway id, 2$: error message
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.
*
* @since 6.4.0
*
* @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' ), [ '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 ), [ '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' ), [ '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' ), [ '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(
[
'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 );
// Don't include sign-up fees or $0 trial periods when setting the subscriptions item totals.
wcs_set_recurring_item_total( $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(
[
'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 );
}
/*
* Fetch a fresh instance of the subscription because the current instance has an empty line item cache generated before we had copied the line items.
* Fetching a new instance will ensure the line items are used when calculating totals.
*/
$subscription = wcs_get_subscription( $subscription->get_id() );
$subscription->calculate_totals();
/**
* 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(), [ 'status' => 404 ] );
}
// If we got here, the subscription was created without problems
$transaction->commit();
return rest_ensure_response( $subscriptions );
}
/**
* Subscriptions statuses schema, conforming to JSON Schema.
*
* @return array
*/
public function get_statuses_schema() {
$schema = [
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'shop_subscription statuses', // Use a unique title for the schema so that CLI commands aren't overridden.
'type' => 'object',
'properties' => [],
];
// Add the subscription statuses to the schema.
foreach ( wcs_get_subscription_statuses() as $status => $status_name ) {
$schema['properties'][ $status ] = [
'type' => 'string',
'description' => sprintf( __( 'Subscription status: %s', 'woocommerce-subscription' ), $status_name ),
];
}
return $schema;
}
/**
* Subscriptions orders schema, conforming to JSON Schema.
*
* @return array
*/
public function get_subscription_orders_schema() {
$schema = parent::get_item_schema(); // Fetch the order schema.
$schema['title'] = 'shop_subscription orders'; // Use a unique title for the schema so that CLI commands aren't overridden.
$schema['properties']['order_type'] = [
'type' => 'string',
'description' => __( 'The type of order related to the subscription.', 'woocommerce-subscriptions' ),
];
return $schema;
}
/**
* Subscriptions schema, conforming to JSON Schema.
*
* @return array
*/
public function create_subscriptions_from_order_schema() {
$schema = $this->get_public_item_schema();
$schema['title'] = 'shop_order subscriptions'; // Use a unique title for the schema so that CLI commands aren't overridden and we can target this endpoint specifically.
return $schema;
}
}

View File

@@ -0,0 +1,31 @@
<?php
/**
* WooCommerce Subscriptions CLI class.
*
* @since 6.3.0
*/
defined( 'ABSPATH' ) || exit;
class WC_Subscriptions_CLI {
/**
* Loads WooCommerce Subscriptions CLI related hooks.
*/
public function __construct() {
WP_CLI::add_hook( 'before_invoke:wc shop_order subscriptions create', [ $this, 'abort_create_subscriptions_from_order' ] );
}
/**
* Return an error when the `wc shop_order subscriptions create` WP CLI command is used.
*
* WooCommerce core adds WP CLI commands for each WC REST API endpoints beginning with /wc/v2. This means all of our subscription
* REST API endpoints are added. While the `wc shop_order subscriptions create` CLI command technically works, WooCommerce doesn't have support for
* batch creation via CLI and results in the success message not being displayed correctly.
*
* @param string $command The command name.
*/
public function abort_create_subscriptions_from_order( $command ) {
WP_CLI::error( "The '{$command}' command isn't supported via WP CLI." );
}
}

View File

@@ -33,6 +33,10 @@ class WC_Subscriptions_Plugin extends WC_Subscriptions_Core_Plugin {
WCS_Subscriber_Role_Manager::init(); WCS_Subscriber_Role_Manager::init();
WCS_Upgrade_Notice_Manager::init(); WCS_Upgrade_Notice_Manager::init();
if ( defined( 'WP_CLI' ) && WP_CLI ) {
new WC_Subscriptions_CLI();
}
add_action( 'admin_enqueue_scripts', array( $this, 'maybe_show_welcome_message' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'maybe_show_welcome_message' ) );
} }

View File

@@ -54,6 +54,9 @@ class WCS_API {
// V1 // V1
'WC_REST_Subscriptions_V1_Controller', 'WC_REST_Subscriptions_V1_Controller',
'WC_REST_Subscription_Notes_V1_Controller', 'WC_REST_Subscription_Notes_V1_Controller',
// V2
'WC_REST_Subscriptions_V2_Controller',
'WC_REST_Subscription_Notes_V2_Controller',
// V3 (latest) // V3 (latest)
'WC_REST_Subscriptions_Controller', 'WC_REST_Subscriptions_Controller',
'WC_REST_Subscription_notes_Controller', 'WC_REST_Subscription_notes_Controller',

View File

@@ -45,6 +45,7 @@ class WCS_Autoloader extends WCS_Core_Autoloader {
'wcs_webhooks' => true, 'wcs_webhooks' => true,
'wcs_auth' => true, 'wcs_auth' => true,
'wcs_upgrade_notice_manager' => true, 'wcs_upgrade_notice_manager' => true,
'wc_subscriptions_cli' => true,
); );
/** /**

View File

@@ -2,16 +2,16 @@
# This file is distributed under the same license as the WooCommerce Subscriptions plugin. # This file is distributed under the same license as the WooCommerce Subscriptions plugin.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: WooCommerce Subscriptions 6.3.2\n" "Project-Id-Version: WooCommerce Subscriptions 6.4.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: 2024-05-24T04:44:48+00:00\n" "POT-Creation-Date: 2024-06-13T01:43:31+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.10.0\n" "X-Generator: WP-CLI 2.9.0\n"
"X-Domain: woocommerce-subscriptions\n" "X-Domain: woocommerce-subscriptions\n"
#. Plugin Name of the plugin #. Plugin Name of the plugin
@@ -673,56 +673,69 @@ msgid "Payment Gateway Feature Support."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:165 #: includes/api/class-wc-rest-subscriptions-controller.php:165
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:164
msgid "Invalid subscription ID." msgid "Invalid subscription ID."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:171 #: includes/api/class-wc-rest-subscriptions-controller.php:171
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:170
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:328 #: includes/api/class-wc-rest-subscriptions-controller.php:328
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:329
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:364 #: includes/api/class-wc-rest-subscriptions-controller.php:364
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:371
msgid "Subscription status." msgid "Subscription status."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:367 #: includes/api/class-wc-rest-subscriptions-controller.php:367
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:374
msgid "Where the subscription was created." msgid "Where the subscription was created."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:368 #: includes/api/class-wc-rest-subscriptions-controller.php:368
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:375
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:369 #: includes/api/class-wc-rest-subscriptions-controller.php:369
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:376
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:370 #: includes/api/class-wc-rest-subscriptions-controller.php:370
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:377
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:371 #: includes/api/class-wc-rest-subscriptions-controller.php:371
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:378
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:372 #: includes/api/class-wc-rest-subscriptions-controller.php:372
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:379
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:373 #: includes/api/class-wc-rest-subscriptions-controller.php:373
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:380
msgid "User ID who owns the subscription." msgid "User ID who owns the subscription."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:383 #: includes/api/class-wc-rest-subscriptions-controller.php:383
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:390
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:389 #: includes/api/class-wc-rest-subscriptions-controller.php:389
#: 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
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:396
#: 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
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:453 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:453
msgid "The number of billing periods between subscription renewals." msgid "The number of billing periods between subscription renewals."
@@ -731,6 +744,7 @@ msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:394 #: includes/api/class-wc-rest-subscriptions-controller.php:394
#: 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
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:401
#: 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
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:446 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-extend-store-endpoint.php:446
msgid "Billing period for the subscription." msgid "Billing period for the subscription."
@@ -739,43 +753,53 @@ msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:400 #: includes/api/class-wc-rest-subscriptions-controller.php:400
#: 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
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:407
msgid "Subscription payment details." msgid "Subscription payment details."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:405 #: includes/api/class-wc-rest-subscriptions-controller.php:405
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:412
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:410 #: includes/api/class-wc-rest-subscriptions-controller.php:410
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:417
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:417 #: includes/api/class-wc-rest-subscriptions-controller.php:417
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:424
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:422 #: includes/api/class-wc-rest-subscriptions-controller.php:422
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:429
msgid "The subscription's trial end date, as GMT." msgid "The subscription's trial end date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:427 #: includes/api/class-wc-rest-subscriptions-controller.php:427
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:434
msgid "The subscription's next payment date, as GMT." msgid "The subscription's next payment date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:432 #: includes/api/class-wc-rest-subscriptions-controller.php:432
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:439
msgid "The subscription's cancelled date, as GMT." msgid "The subscription's cancelled date, as GMT."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:437 #: includes/api/class-wc-rest-subscriptions-controller.php:437
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:444
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:456 #: includes/api/class-wc-rest-subscriptions-controller.php:456
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:464
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:500 #: includes/api/class-wc-rest-subscriptions-controller.php:500
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:511
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 ""
@@ -783,22 +807,27 @@ msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:517 #: includes/api/class-wc-rest-subscriptions-controller.php:517
#: 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
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:528
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:531 #: includes/api/class-wc-rest-subscriptions-controller.php:531
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:545
msgid "Invalid order ID." msgid "Invalid order ID."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:537 #: includes/api/class-wc-rest-subscriptions-controller.php:537
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:551
msgid "Failed to load order object with the ID %d." msgid "Failed to load order object with the ID %d."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:541 #: includes/api/class-wc-rest-subscriptions-controller.php:541
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:555
msgid "Order does not have a customer associated with it. Subscriptions require a customer." msgid "Order does not have a customer associated with it. Subscriptions require a customer."
msgstr "" msgstr ""
#: includes/api/class-wc-rest-subscriptions-controller.php:545 #: includes/api/class-wc-rest-subscriptions-controller.php:545
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:559
msgid "Order already has subscriptions associated with it." msgid "Order already has subscriptions associated with it."
msgstr "" msgstr ""
@@ -1002,6 +1031,10 @@ msgstr ""
msgid "Meta value." msgid "Meta value."
msgstr "" msgstr ""
#: includes/api/v2/class-wc-rest-subscriptions-v2-controller.php:770
msgid "The type of order related to the subscription."
msgstr ""
#. translators: 1$-2$: opening and closing <strong> tags, 3$-4$: link tags, takes to woocommerce plugin on wp.org, 5$-6$: opening and closing link tags, leads to plugins.php in admin #. translators: 1$-2$: opening and closing <strong> tags, 3$-4$: link tags, takes to woocommerce plugin on wp.org, 5$-6$: opening and closing link tags, leads to plugins.php in admin
#: includes/class-wc-subscriptions-dependency-manager.php:156 #: includes/class-wc-subscriptions-dependency-manager.php:156
msgid "%1$sWooCommerce Subscriptions is inactive.%2$s The %3$sWooCommerce plugin%4$s must be active for WooCommerce Subscriptions to work. Please %5$sinstall & activate WooCommerce &raquo;%6$s" msgid "%1$sWooCommerce Subscriptions is inactive.%2$s The %3$sWooCommerce plugin%4$s must be active for WooCommerce Subscriptions to work. Please %5$sinstall & activate WooCommerce &raquo;%6$s"
@@ -1013,24 +1046,24 @@ msgid "%1$sWooCommerce Subscriptions is inactive.%2$s This version of Subscripti
msgstr "" msgstr ""
#. translators: 1-2: opening/closing <b> tags, 3: Subscriptions version. #. translators: 1-2: opening/closing <b> tags, 3: Subscriptions version.
#: includes/class-wc-subscriptions-plugin.php:58 #: includes/class-wc-subscriptions-plugin.php:62
msgid "%1$sWarning!%2$s We can see the %1$sWooCommerce Subscriptions Early Renewal%2$s plugin is active. Version %3$s of %1$sWooCommerce Subscriptions%2$s comes with that plugin's functionality packaged into the core plugin. Please deactivate WooCommerce Subscriptions Early Renewal to avoid any conflicts." msgid "%1$sWarning!%2$s We can see the %1$sWooCommerce Subscriptions Early Renewal%2$s plugin is active. Version %3$s of %1$sWooCommerce Subscriptions%2$s comes with that plugin's functionality packaged into the core plugin. Please deactivate WooCommerce Subscriptions Early Renewal to avoid any conflicts."
msgstr "" msgstr ""
#: includes/class-wc-subscriptions-plugin.php:62 #: includes/class-wc-subscriptions-plugin.php:66
msgid "Installed Plugins" msgid "Installed Plugins"
msgstr "" msgstr ""
#. translators: $1-$2: opening and closing <strong> tags, $3-$4: opening and closing <em> tags. #. translators: $1-$2: opening and closing <strong> tags, $3-$4: opening and closing <em> tags.
#: includes/class-wc-subscriptions-plugin.php:204 #: includes/class-wc-subscriptions-plugin.php:208
msgid "%1$sWooCommerce Subscriptions Installed%2$s &#8211; %3$sYou're ready to start selling subscriptions!%4$s" msgid "%1$sWooCommerce Subscriptions Installed%2$s &#8211; %3$sYou're ready to start selling subscriptions!%4$s"
msgstr "" msgstr ""
#: includes/class-wc-subscriptions-plugin.php:222 #: includes/class-wc-subscriptions-plugin.php:226
msgid "Add a Subscription Product" msgid "Add a Subscription Product"
msgstr "" msgstr ""
#: includes/class-wc-subscriptions-plugin.php:223 #: includes/class-wc-subscriptions-plugin.php:227
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-core-plugin.php:548 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-core-plugin.php:548
#: vendor/woocommerce/subscriptions-core/includes/upgrades/templates/wcs-about-2-0.php:35 #: vendor/woocommerce/subscriptions-core/includes/upgrades/templates/wcs-about-2-0.php:35
#: vendor/woocommerce/subscriptions-core/includes/upgrades/templates/wcs-about.php:34 #: vendor/woocommerce/subscriptions-core/includes/upgrades/templates/wcs-about.php:34
@@ -1293,7 +1326,7 @@ msgstr ""
#: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-related-orders-row.php:17 #: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-related-orders-row.php:17
#: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-unknown-related-orders-row.php:18 #: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-unknown-related-orders-row.php:18
#: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-renewal-order.php:170 #: vendor/woocommerce/subscriptions-core/includes/class-wc-subscriptions-renewal-order.php:170
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:34 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:35
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:44 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:44
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:33 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:33
msgctxt "hash before order number" msgctxt "hash before order number"
@@ -1889,46 +1922,6 @@ 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:290
msgctxt "table heading"
msgid "Start Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:66
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:291
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:292
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:293
msgctxt "table heading"
msgid "Last Order Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:69
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:294
msgctxt "table heading"
msgid "Cancelled Date"
msgstr ""
#: tests/unit/scheduler/scheduler.php:70
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:295
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."
@@ -2435,7 +2428,7 @@ msgstr[1] ""
#: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:468 #: vendor/woocommerce/subscriptions-core/includes/admin/class-wcs-admin-post-types.php:468
#: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-related-orders-table.php:21 #: vendor/woocommerce/subscriptions-core/includes/admin/meta-boxes/views/html-related-orders-table.php:21
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:22 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:22
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:37 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:39
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:24 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:24
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:50 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:50
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:22 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:22
@@ -6414,6 +6407,14 @@ 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:293
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"
@@ -6696,37 +6697,43 @@ msgstr ""
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:46 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:42
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:292
msgctxt "table heading"
msgid "Next Payment"
msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:48
#: 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
msgctxt "Used in data attribute. Escaped" msgctxt "Used in data attribute. Escaped"
msgid "Total" msgid "Total"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:50 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:52
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:84 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-orders.php:84
#: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:46 #: vendor/woocommerce/subscriptions-core/templates/myaccount/related-subscriptions.php:46
msgctxt "view a subscription" msgctxt "view a subscription"
msgid "View" msgid "View"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:61 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:63
msgid "Previous" msgid "Previous"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:65 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:67
msgid "Next" msgid "Next"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:72 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:74
msgid "You have reached the end of subscriptions. Go to the %sfirst page%s." msgid "You have reached the end of subscriptions. Go to the %sfirst page%s."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:74 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:76
msgid "You have no active subscriptions." msgid "You have no active subscriptions."
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:77 #: vendor/woocommerce/subscriptions-core/templates/myaccount/my-subscriptions.php:79
msgid "Browse products" msgid "Browse products"
msgstr "" msgstr ""
@@ -6875,6 +6882,26 @@ 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:290
msgctxt "table heading"
msgid "Start Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:291
msgctxt "table heading"
msgid "Trial End"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:294
msgctxt "table heading"
msgid "Cancelled Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:295
msgctxt "table heading"
msgid "End Date"
msgstr ""
#: vendor/woocommerce/subscriptions-core/wcs-functions.php:330 #: vendor/woocommerce/subscriptions-core/wcs-functions.php:330
msgid "Date type is not a string." msgid "Date type is not a string."
msgstr "" msgstr ""
@@ -6916,6 +6943,10 @@ msgstr[1] ""
msgid "%1$s %2$s %3$d %4$s" msgid "%1$s %2$s %3$d %4$s"
msgstr "" msgstr ""
#: vendor/woocommerce/subscriptions-core/build/index.js:6
msgid "Free"
msgstr ""
#. translators: %s selected shipping rate (ex: flat rate) #. translators: %s selected shipping rate (ex: flat rate)
#: vendor/woocommerce/subscriptions-core/build/index.js:7 #: vendor/woocommerce/subscriptions-core/build/index.js:7
msgid "via %s" msgid "via %s"

20
vendor/autoload.php vendored
View File

@@ -2,6 +2,24 @@
// 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 ComposerAutoloaderInit2a572b7cb1c49650721c1f7426949a4c::getLoader(); return ComposerAutoloaderInit02567f250c7765c8ea2ed71a416c6653::getLoader();

View File

@@ -42,6 +42,9 @@ namespace Composer\Autoload;
*/ */
class ClassLoader class ClassLoader
{ {
/** @var \Closure(string):void */
private static $includeFile;
/** @var ?string */ /** @var ?string */
private $vendorDir; private $vendorDir;
@@ -106,6 +109,7 @@ class ClassLoader
public function __construct($vendorDir = null) public function __construct($vendorDir = null)
{ {
$this->vendorDir = $vendorDir; $this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
} }
/** /**
@@ -425,7 +429,8 @@ class ClassLoader
public function loadClass($class) public function loadClass($class)
{ {
if ($file = $this->findFile($class)) { if ($file = $this->findFile($class)) {
includeFile($file); $includeFile = self::$includeFile;
$includeFile($file);
return true; return true;
} }
@@ -555,18 +560,26 @@ class ClassLoader
return false; return false;
} }
}
/** /**
* Scope isolated include. * @return void
* */
* Prevents access to $this/self from included files. private static function initializeIncludeClosure()
* {
* @param string $file if (self::$includeFile !== null) {
* @return void return;
* @private }
*/
function includeFile($file) /**
{ * Scope isolated include.
include $file; *
* 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

@@ -28,7 +28,7 @@ class InstalledVersions
{ {
/** /**
* @var mixed[]|null * @var mixed[]|null
* @psalm-var array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}|array{}|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;
@@ -39,7 +39,7 @@ class InstalledVersions
/** /**
* @var array[] * @var array[]
* @psalm-var array<string, array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> * @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 +98,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 || empty($installed['versions'][$packageName]['dev_requirement']); return $includeDevRequirements || !isset($installed['versions'][$packageName]['dev_requirement']) || $installed['versions'][$packageName]['dev_requirement'] === false;
} }
} }
@@ -119,7 +119,7 @@ class InstalledVersions
*/ */
public static function satisfies(VersionParser $parser, $packageName, $constraint) public static function satisfies(VersionParser $parser, $packageName, $constraint)
{ {
$constraint = $parser->parseConstraints($constraint); $constraint = $parser->parseConstraints((string) $constraint);
$provided = $parser->parseConstraints(self::getVersionRanges($packageName)); $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
return $provided->matches($constraint); return $provided->matches($constraint);
@@ -243,7 +243,7 @@ class InstalledVersions
/** /**
* @return array * @return array
* @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string} * @psalm-return array{name: string, pretty_version: string, version: string, reference: string|null, type: string, install_path: string, aliases: string[], dev: bool}
*/ */
public static function getRootPackage() public static function getRootPackage()
{ {
@@ -257,7 +257,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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} * @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[]}>}
*/ */
public static function getRawData() public static function getRawData()
{ {
@@ -280,7 +280,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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> * @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[]}>}>
*/ */
public static function getAllRawData() public static function getAllRawData()
{ {
@@ -303,7 +303,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, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>} $data * @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
*/ */
public static function reload($data) public static function reload($data)
{ {
@@ -313,7 +313,7 @@ class InstalledVersions
/** /**
* @return array[] * @return array[]
* @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string, type: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string, type?: string}>}> * @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[]}>}>
*/ */
private static function getInstalled() private static function getInstalled()
{ {
@@ -328,7 +328,9 @@ 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')) {
$installed[] = self::$installedByVendor[$vendorDir] = require $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 */
$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];
} }
@@ -340,12 +342,17 @@ 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') {
self::$installed = require __DIR__ . '/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 */
$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_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInit2a572b7cb1c49650721c1f7426949a4c class ComposerAutoloaderInit02567f250c7765c8ea2ed71a416c6653
{ {
private static $loader; private static $loader;
@@ -24,12 +24,12 @@ class ComposerAutoloaderInit2a572b7cb1c49650721c1f7426949a4c
require __DIR__ . '/platform_check.php'; require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit2a572b7cb1c49650721c1f7426949a4c', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit02567f250c7765c8ea2ed71a416c6653', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__)); self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit2a572b7cb1c49650721c1f7426949a4c', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit02567f250c7765c8ea2ed71a416c6653', 'loadClassLoader'));
require __DIR__ . '/autoload_static.php'; require __DIR__ . '/autoload_static.php';
\Composer\Autoload\ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c::getInitializer($loader)(); call_user_func(\Composer\Autoload\ComposerStaticInit02567f250c7765c8ea2ed71a416c6653::getInitializer($loader));
$loader->register(true); $loader->register(true);

View File

@@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c class ComposerStaticInit02567f250c7765c8ea2ed71a416c6653
{ {
public static $prefixLengthsPsr4 = array ( public static $prefixLengthsPsr4 = array (
'C' => 'C' =>
@@ -129,9 +129,9 @@ class ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c
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 = ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit02567f250c7765c8ea2ed71a416c6653::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit02567f250c7765c8ea2ed71a416c6653::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInit2a572b7cb1c49650721c1f7426949a4c::$classMap; $loader->classMap = ComposerStaticInit02567f250c7765c8ea2ed71a416c6653::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@@ -156,17 +156,17 @@
}, },
{ {
"name": "woocommerce/subscriptions-core", "name": "woocommerce/subscriptions-core",
"version": "7.1.1", "version": "7.2.0",
"version_normalized": "7.1.1.0", "version_normalized": "7.2.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": "5ba92addca2996576d39376907157243b061175e" "reference": "9f42efee04a8e8966c2fda22c25ee1793fe9839e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/5ba92addca2996576d39376907157243b061175e", "url": "https://api.github.com/repos/Automattic/woocommerce-subscriptions-core/zipball/9f42efee04a8e8966c2fda22c25ee1793fe9839e",
"reference": "5ba92addca2996576d39376907157243b061175e", "reference": "9f42efee04a8e8966c2fda22c25ee1793fe9839e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -179,7 +179,7 @@
"woocommerce/woocommerce-sniffs": "0.1.0", "woocommerce/woocommerce-sniffs": "0.1.0",
"yoast/phpunit-polyfills": "1.1.0" "yoast/phpunit-polyfills": "1.1.0"
}, },
"time": "2024-05-09T07:21:43+00:00", "time": "2024-06-13T01:14:44+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/7.1.1", "source": "https://github.com/Automattic/woocommerce-subscriptions-core/tree/7.2.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(
'pretty_version' => 'dev-release/6.3.2', 'name' => 'woocommerce/woocommerce-subscriptions',
'version' => 'dev-release/6.3.2', 'pretty_version' => 'dev-release/6.4.0',
'version' => 'dev-release/6.4.0',
'reference' => '4f5a7362b75b8b0f747cc271320809adba667cb7',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '1d9382ce5301ebe8df492ad898947a5d4534b5b1',
'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' => '7.1.1', 'pretty_version' => '7.2.0',
'version' => '7.1.1.0', 'version' => '7.2.0.0',
'reference' => '9f42efee04a8e8966c2fda22c25ee1793fe9839e',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../woocommerce/subscriptions-core', 'install_path' => __DIR__ . '/../woocommerce/subscriptions-core',
'aliases' => array(), 'aliases' => array(),
'reference' => '5ba92addca2996576d39376907157243b061175e',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
'woocommerce/woocommerce-subscriptions' => array( 'woocommerce/woocommerce-subscriptions' => array(
'pretty_version' => 'dev-release/6.3.2', 'pretty_version' => 'dev-release/6.4.0',
'version' => 'dev-release/6.3.2', 'version' => 'dev-release/6.4.0',
'reference' => '4f5a7362b75b8b0f747cc271320809adba667cb7',
'type' => 'wordpress-plugin', 'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../', 'install_path' => __DIR__ . '/../../',
'aliases' => array(), 'aliases' => array(),
'reference' => '1d9382ce5301ebe8df492ad898947a5d4534b5b1',
'dev_requirement' => false, 'dev_requirement' => false,
), ),
), ),

View File

@@ -1 +1 @@
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => 'b74144542a686437daa06d7e57f2567f'); <?php return array('dependencies' => array('wc-blocks-checkout', 'wc-price-format', 'wc-settings', 'wp-element', 'wp-i18n', 'wp-plugins'), 'version' => '7e9abfc482fe190e29673f828b33f482');

View File

@@ -1,9 +1,9 @@
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var c=t[r]={i:r,l:!1,exports:{}};return e[r].call(c.exports,c,c.exports,n),c.l=!0,c.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(r,c,function(t){return e[t]}.bind(null,c));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=10)}([function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wc.blocksCheckout},function(e,t,n){var r=n(7);e.exports=function(e,t){if(null==e)return{};var n,c,i=r(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(c=0;c<o.length;c++)n=o[c],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}},function(e,t){e.exports=window.wc.wcSettings},function(e,t){e.exports=window.wp.plugins},function(e,t){e.exports=window.wc.priceFormat},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,c={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(c[n]=e[n]);return c}},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var r=n(1),c=n(5),i=n(2),o=n(3),s=n.n(o),l=n(0),a=n(6),u=n(4);function p(e){return{day:Object(l._nx)("day","days",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),week:Object(l._nx)("week","weeks",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),month:Object(l._nx)("month","months",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),year:Object(l._nx)("year","years",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions")}}function b(e,t,n){var r=e.billing_interval,c=e.billing_period,i=p(r)[c];switch(t=t.trim(),r){case 1:return"".concat(n," ").concat(t," ").concat(i);default:return Object(l.sprintf)( !function(e){var t={};function n(r){if(t[r])return t[r].exports;var c=t[r]={i:r,l:!1,exports:{}};return e[r].call(c.exports,c,c.exports,n),c.l=!0,c.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var c in e)n.d(r,c,function(t){return e[t]}.bind(null,c));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=10)}([function(e,t){e.exports=window.wp.i18n},function(e,t){e.exports=window.wp.element},function(e,t){e.exports=window.wc.blocksCheckout},function(e,t){e.exports=window.wc.wcSettings},function(e,t,n){var r=n(7);e.exports=function(e,t){if(null==e)return{};var n,c,i=r(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(c=0;c<o.length;c++)n=o[c],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}},function(e,t){e.exports=window.wp.plugins},function(e,t){e.exports=window.wc.priceFormat},function(e,t){e.exports=function(e,t){if(null==e)return{};var n,r,c={},i=Object.keys(e);for(r=0;r<i.length;r++)n=i[r],t.indexOf(n)>=0||(c[n]=e[n]);return c}},function(e,t,n){},function(e,t,n){},function(e,t,n){"use strict";n.r(t);var r=n(1),c=n(5),i=n(2),o=n(4),s=n.n(o),l=n(0),a=n(6),u=n(3);function p(e){return{day:Object(l._nx)("day","days",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),week:Object(l._nx)("week","weeks",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),month:Object(l._nx)("month","months",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions"),year:Object(l._nx)("year","years",e,"Used in recurring totals section in Cart. 2+ will need plural, 1 will need singular.","woocommerce-subscriptions")}}function b(e,t,n){var r=e.billing_interval,c=e.billing_period,i=p(r)[c];switch(t=t.trim(),r){case 1:return"".concat(n," ").concat(t," ").concat(i);default:return Object(l.sprintf)(
/* /*
* translators: %1$s is the price of the product. %2$s is the separator used e.g "every" or "/", * translators: %1$s is the price of the product. %2$s is the separator used e.g "every" or "/",
* %3$d is the length, %4$s is week, month, year * %3$d is the length, %4$s is week, month, year
*/ */
Object(l.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),n,t,r,i)}}function m(e){return e.subscriptionLength===e.billingInterval}n(8);var g=Object(u.getSetting)("displayCartPricesIncludingTax",!1),d=function(e){var t=e.currency,n=e.values,c=n.total_discount,o=n.total_discount_tax,s=parseInt(c,10);if(!s)return null;var a=parseInt(o,10),u=g?s+a:s;return Object(r.createElement)(i.TotalsItem,{className:"wc-block-components-totals-discount",currency:t,label:Object(l.__)("Discount","woocommerce-subscriptions"),value:-1*u})},_=function(e){var t=e.values,n=e.currency,c=e.selectedRate,o=e.needsShipping,s=e.calculatedShipping;if(!o||!s)return null;var a=g?parseInt(t.total_shipping,10)+parseInt(t.total_shipping_tax,10):parseInt(t.total_shipping,10);return Object(r.createElement)(i.TotalsItem,{value:a,label:Object(l.__)("Shipping","woocommerce-subscriptions"),currency:n,description:!!c&&Object(l.sprintf)(// translators: %s selected shipping rate (ex: flat rate) Object(l.__)("%1$s %2$s %3$d %4$s","woocommerce-subscriptions"),n,t,r,i)}}function m(e){return e.subscriptionLength===e.billingInterval}n(8);var g=Object(u.getSetting)("displayCartPricesIncludingTax",!1),d=function(e){var t=e.currency,n=e.values,c=n.total_discount,o=n.total_discount_tax,s=parseInt(c,10);if(!s)return null;var a=parseInt(o,10),u=g?s+a:s;return Object(r.createElement)(i.TotalsItem,{className:"wc-block-components-totals-discount",currency:t,label:Object(l.__)("Discount","woocommerce-subscriptions"),value:-1*u})},_=function(e){var t=e.values,n=e.currency,c=e.selectedRate,o=e.needsShipping,s=e.calculatedShipping;if(!o||!s)return null;var a=g?parseInt(t.total_shipping,10)+parseInt(t.total_shipping_tax,10):parseInt(t.total_shipping,10),p=0===a&&Object(u.isWcVersion)("9.0",">=")?Object(r.createElement)("strong",null,Object(l.__)("Free","woocommerce-subscriptions")):a;return Object(r.createElement)(i.TotalsItem,{value:p,label:Object(l.__)("Shipping","woocommerce-subscriptions"),currency:n,description:!!c&&Object(l.sprintf)(// translators: %s selected shipping rate (ex: flat rate)
Object(l.__)("via %s","woocommerce-subscriptions"),c)})},f=function(e){var t=e.nextPaymentDate,n=e.subscriptionLength,c=e.billingPeriod,i=e.billingInterval,o=function(e){var t=e.subscriptionLength,n=e.billingPeriod,r=p(t);return Object(l.sprintf)("For %1$d %2$s",t,r[n],"woocommerce-subscriptions")}({subscriptionLength:n,billingPeriod:c}),s=m({subscriptionLength:n,billingInterval:i})?Object(l.sprintf)( Object(l.__)("via %s","woocommerce-subscriptions"),c)})},f=function(e){var t=e.nextPaymentDate,n=e.subscriptionLength,c=e.billingPeriod,i=e.billingInterval,o=function(e){var t=e.subscriptionLength,n=e.billingPeriod,r=p(t);return Object(l.sprintf)("For %1$d %2$s",t,r[n],"woocommerce-subscriptions")}({subscriptionLength:n,billingPeriod:c}),s=m({subscriptionLength:n,billingInterval:i})?Object(l.sprintf)(
/* Translators: %1$s is a date. */ /* Translators: %1$s is a date. */
Object(l.__)("Due: %1$s","woocommerce-subscriptions"),t):Object(l.sprintf)( Object(l.__)("Due: %1$s","woocommerce-subscriptions"),t):Object(l.sprintf)(
@@ -14,7 +14,7 @@ Object(l.__)("Recurring total every 2nd %1$s","woocommerce-subscriptions"),n);ca
/* Translators: %1$s is week, month, year */ /* Translators: %1$s is week, month, year */
Object(l.__)("Recurring total every 3rd %1$s","woocommerce-subscriptions"),n);default:return Object(l.sprintf)( Object(l.__)("Recurring total every 3rd %1$s","woocommerce-subscriptions"),n);default:return Object(l.sprintf)(
/* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */ /* Translators: %1$d is number of weeks, months, days, years. %2$s is week, month, year */
Object(l.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),t,n)}}({billingInterval:n,billingPeriod:c});return Object(r.createElement)(i.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:t,label:u,value:a,description:Object(r.createElement)(f,{nextPaymentDate:o,subscriptionLength:s,billingInterval:n,billingPeriod:c})})},j=function(e){var t,n,c,o=e.subscription,s=e.needsShipping,u=e.calculatedShipping,p=o.totals,b=o.billing_interval,m=o.billing_period,f=o.next_payment_date,j=o.subscription_length,w=o.shipping_rates;if(!f)return null;var v=null==w||null===(t=w[0])||void 0===t||null===(n=t.shipping_rates)||void 0===n||null===(c=n.find((function(e){return e.selected})))||void 0===c?void 0:c.name,y=Object(a.getCurrencyFromPriceResponse)(p);return Object(r.createElement)("div",{className:"wcs-recurring-totals-panel"},Object(r.createElement)(O,{billingInterval:b,billingPeriod:m,nextPaymentDate:f,subscriptionLength:j,totals:parseInt(p.total_price,10),currency:y}),Object(r.createElement)(i.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:Object(l.__)("Details","woocommerce-subscriptions")},Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.Subtotal,{currency:y,values:p}),Object(r.createElement)(d,{currency:y,values:p})),Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(_,{currency:y,needsShipping:s,calculatedShipping:u,values:p,selectedRate:v})),!g&&Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.TotalsTaxes,{currency:y,values:p})),Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:y,label:Object(l.__)("Total","woocommerce-subscriptions"),value:parseInt(p.total_price,10)}))))},w=function(e){var t=e.extensions,n=e.cart,c=t.subscriptions,i=n.cartNeedsShipping,o=n.cartHasCalculatedShipping;return c&&0!==c.length?c.map((function(e){var t=e.key,n=s()(e,["key"]);return Object(r.createElement)(j,{subscription:n,needsShipping:i,calculatedShipping:o,key:t})})):null},v=function(e){var t=e.extensions,n=e.collapsible,c=e.collapse,i=e.showItems,o=e.noResultsMessage,l=e.renderOption,a=e.components,u=e.context,p=t.subscriptions,b=void 0===p?[]:p,m=a.ShippingRatesControlPackage,g=Object(r.useMemo)((function(){return Object.values(b).map((function(e){return e.shipping_rates})).filter(Boolean).flat()}),[b]),d=Object(r.useMemo)((function(){return 1<g.length||c}),[g.length,c]),_=Object(r.useMemo)((function(){return 1<g.length||i}),[g.length,i]);return g.map((function(e){var t=e.package_id,c=s()(e,["package_id"]);return Object(r.createElement)(m,{key:t,packageId:t,packageData:c,collapsible:n,collapse:d,showItems:_,noResultsMessage:o,renderOption:l,highlightChecked:"woocommerce/checkout"===u})}))};n(9),Object(c.registerPlugin)("woocommerce-subscriptions",{render:function(){return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(i.ExperimentalOrderShippingPackages,null,Object(r.createElement)(v,null)),Object(r.createElement)(i.ExperimentalOrderMeta,null,Object(r.createElement)(w,null)))},scope:"woocommerce-checkout"}),Object(i.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:function(e,t){var n=t.subscriptions;return 0<(null==n?void 0:n.length)?Object(l.__)("Total due today","woocommerce-subscriptions"):e},subtotalPriceFormat:function(e,t){var n=t.subscriptions;if(null!=n&&n.billing_period&&null!=n&&n.billing_interval){var r=n.billing_interval,c=n.subscription_length;return m({subscriptionLength:c,billingInterval:r})?b(n,1===c?// translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month. Object(l.__)("Recurring total every %1$dth %2$s","woocommerce-subscriptions"),t,n)}}({billingInterval:n,billingPeriod:c});return Object(r.createElement)(i.TotalsItem,{className:"wcs-recurring-totals-panel__title",currency:t,label:u,value:a,description:Object(r.createElement)(f,{nextPaymentDate:o,subscriptionLength:s,billingInterval:n,billingPeriod:c})})},j=function(e){var t,n,c,o=e.subscription,s=e.needsShipping,u=e.calculatedShipping,p=o.totals,b=o.billing_interval,m=o.billing_period,f=o.next_payment_date,j=o.subscription_length,w=o.shipping_rates;if(!f)return null;var v=null==w||null===(t=w[0])||void 0===t||null===(n=t.shipping_rates)||void 0===n||null===(c=n.find((function(e){return e.selected})))||void 0===c?void 0:c.name,h=Object(a.getCurrencyFromPriceResponse)(p);return Object(r.createElement)("div",{className:"wcs-recurring-totals-panel"},Object(r.createElement)(O,{billingInterval:b,billingPeriod:m,nextPaymentDate:f,subscriptionLength:j,totals:parseInt(p.total_price,10),currency:h}),Object(r.createElement)(i.Panel,{className:"wcs-recurring-totals-panel__details",initialOpen:!1,title:Object(l.__)("Details","woocommerce-subscriptions")},Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.Subtotal,{currency:h,values:p}),Object(r.createElement)(d,{currency:h,values:p})),Object(r.createElement)(i.TotalsWrapper,{className:"wc-block-components-totals-shipping"},Object(r.createElement)(_,{currency:h,needsShipping:s,calculatedShipping:u,values:p,selectedRate:v})),!g&&Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.TotalsTaxes,{currency:h,values:p})),Object(r.createElement)(i.TotalsWrapper,null,Object(r.createElement)(i.TotalsItem,{className:"wcs-recurring-totals-panel__details-total",currency:h,label:Object(l.__)("Total","woocommerce-subscriptions"),value:parseInt(p.total_price,10)}))))},w=function(e){var t=e.extensions,n=e.cart,c=t.subscriptions,i=n.cartNeedsShipping,o=n.cartHasCalculatedShipping;return c&&0!==c.length?c.map((function(e){var t=e.key,n=s()(e,["key"]);return Object(r.createElement)(j,{subscription:n,needsShipping:i,calculatedShipping:o,key:t})})):null},v=function(e){var t=e.extensions,n=e.collapsible,c=e.collapse,i=e.showItems,o=e.noResultsMessage,l=e.renderOption,a=e.components,u=e.context,p=t.subscriptions,b=void 0===p?[]:p,m=a.ShippingRatesControlPackage,g=Object(r.useMemo)((function(){return Object.values(b).map((function(e){return e.shipping_rates})).filter(Boolean).flat()}),[b]),d=Object(r.useMemo)((function(){return 1<g.length||c}),[g.length,c]),_=Object(r.useMemo)((function(){return 1<g.length||i}),[g.length,i]);return g.map((function(e){var t=e.package_id,c=s()(e,["package_id"]);return Object(r.createElement)(m,{key:t,packageId:t,packageData:c,collapsible:n,collapse:d,showItems:_,noResultsMessage:o,renderOption:l,highlightChecked:"woocommerce/checkout"===u})}))};n(9),Object(c.registerPlugin)("woocommerce-subscriptions",{render:function(){return Object(r.createElement)(r.Fragment,null,Object(r.createElement)(i.ExperimentalOrderShippingPackages,null,Object(r.createElement)(v,null)),Object(r.createElement)(i.ExperimentalOrderMeta,null,Object(r.createElement)(w,null)))},scope:"woocommerce-checkout"}),Object(i.registerCheckoutFilters)("woocommerce-subscriptions",{totalLabel:function(e,t){var n=t.subscriptions;return 0<(null==n?void 0:n.length)?Object(l.__)("Total due today","woocommerce-subscriptions"):e},subtotalPriceFormat:function(e,t){var n=t.subscriptions;if(null!=n&&n.billing_period&&null!=n&&n.billing_interval){var r=n.billing_interval,c=n.subscription_length;return m({subscriptionLength:c,billingInterval:r})?b(n,1===c?// translators: the word used to describe billing frequency, e.g. "for" 1 day or "for" 1 month.
Object(l.__)("for 1","woocommerce-subscriptions"):// translators: the word used to describe billing frequency, e.g. "for" 6 days or "for" 2 weeks. Object(l.__)("for 1","woocommerce-subscriptions"):// translators: the word used to describe billing frequency, e.g. "for" 6 days or "for" 2 weeks.
Object(l.__)("for","woocommerce-subscriptions"),e):b(n,// translators: the word used to describe billing frequency, e.g. "every" 6 days or "every" 2 weeks. Object(l.__)("for","woocommerce-subscriptions"),e):b(n,// translators: the word used to describe billing frequency, e.g. "every" 6 days or "every" 2 weeks.
Object(l.__)("every","woocommerce-subscriptions"),e)}return e},saleBadgePriceFormat:function(e,t){var n=t.subscriptions;return null!=n&&n.billing_period&&null!=n&&n.billing_interval?b(n,"/",e):e},itemName:function(e,t){var n=t.subscriptions;return null!=n&&n.is_resubscribe?Object(l.sprintf)(// translators: %s Product name. Object(l.__)("every","woocommerce-subscriptions"),e)}return e},saleBadgePriceFormat:function(e,t){var n=t.subscriptions;return null!=n&&n.billing_period&&null!=n&&n.billing_interval?b(n,"/",e):e},itemName:function(e,t){var n=t.subscriptions;return null!=n&&n.is_resubscribe?Object(l.sprintf)(// translators: %s Product name.

View File

@@ -1,5 +1,11 @@
*** WooCommerce Subscriptions Core Changelog *** *** WooCommerce Subscriptions Core Changelog ***
= 7.2.0 - 2024-06-13 =
* Fix - label improvement on my subscription page template.
* Fix - Regenerate subscriptions related order caches (renewal, resubscribe, switch) if it's stored as an invalid value to prevent fatal errors.
* Update - Show "FREE" instead of 0 when there is no shipping cost in the recurring totals section of the Cart and Checkout blocks (requires WooCommerce 9.0+).
* Dev - New function wcs_set_recurring_item_total() to set line item totals that have been copied from an initial order to their proper recurring totals (i.e. remove sign-up fees).
= 7.1.1 - 2024-05-09 = = 7.1.1 - 2024-05-09 =
* Fix - Resolved an issue that caused "WC_DateTime could not be converted to int" warnings to occur on non-hpos sites while editing a subscription. * Fix - Resolved an issue that caused "WC_DateTime could not be converted to int" warnings to occur on non-hpos sites while editing a subscription.

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 = '7.1.1'; // WRCS: DEFINED_VERSION. protected $library_version = '7.2.0'; // WRCS: DEFINED_VERSION.
/** /**
* The subscription scheduler instance. * The subscription scheduler instance.

View File

@@ -210,7 +210,9 @@ class WCS_Related_Order_Store_Cached_CPT extends WCS_Related_Order_Store_CPT imp
$meta_data = $this->get_related_order_metadata( $subscription, $relation_type ); $meta_data = $this->get_related_order_metadata( $subscription, $relation_type );
return $meta_data ? maybe_unserialize( $meta_data->meta_value ) : ''; $related_orders = $meta_data ? maybe_unserialize( $meta_data->meta_value ) : '';
return is_array( $related_orders ) ? $related_orders : '';
} }
/** /**

View File

@@ -1003,3 +1003,55 @@ function wcs_order_contains_early_renewal( $order ) {
function wcs_get_subscription_item_grouping_key( $item, $renewal_time = '' ) { 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 ); return apply_filters( 'woocommerce_subscriptions_item_grouping_key', wcs_get_subscription_grouping_key( $item->get_product(), $renewal_time ), $item );
} }
/**
* Sets the order item total to its recurring product price.
*
* This function takes an order item and checks if its totals have been modified to account for free trials or sign-up fees (i.e. parent orders).
* If the totals have been adjusted, the function sets the item's total back to their recurring total.
*
* Note: If the line item has a custom total that doesn't match the expected price, don't override it.
*
* @param WC_Order_Item $item Subscription line item.
*/
function wcs_set_recurring_item_total( &$item ) {
$product = $item->get_product();
if ( ! $product || ! WC_Subscriptions_Product::is_subscription( $product ) ) {
return;
}
$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product );
$sign_up_fee = is_numeric( $sign_up_fee ) ? (float) $sign_up_fee : 0;
$trial_length = WC_Subscriptions_Product::get_trial_length( $product );
$recurring_price = (float) $product->get_price();
$initial_price = $trial_length > 0 ? $sign_up_fee : $recurring_price + $sign_up_fee;
$initial_total = wc_get_price_excluding_tax(
$product,
[
'qty' => $item->get_quantity(),
'price' => $initial_price,
]
);
// Check if a custom item total was set on the order. If so, don't override it.
if ( (float) $item->get_subtotal() !== $initial_total ) {
return;
}
$recurring_total = wc_get_price_excluding_tax(
$product,
[
'qty' => $item->get_quantity(),
'price' => $recurring_price,
]
);
$item->set_props(
[
'subtotal' => $recurring_total,
'total' => $recurring_total,
]
);
}

View File

@@ -20,8 +20,8 @@ if ( ! defined( 'ABSPATH' ) ) {
* This method simply creates an order with the same post meta, order items and order item meta as the subscription * This method simply creates an order with the same post meta, order items and order item meta as the subscription
* passed to it. * passed to it.
* *
* @param int | WC_Subscription $subscription Post ID of a 'shop_subscription' post, or instance of a WC_Subscription object * @param int|WC_Subscription $subscription Post ID of a 'shop_subscription' post, or instance of a WC_Subscription object
* @return WC_Order | WP_Error * @return WC_Order|WP_Error
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
function wcs_create_renewal_order( $subscription ) { function wcs_create_renewal_order( $subscription ) {
@@ -41,7 +41,8 @@ function wcs_create_renewal_order( $subscription ) {
/** /**
* Check if a given order is a subscription renewal order. * Check if a given order is a subscription renewal order.
* *
* @param WC_Order|int $order The WC_Order object or ID of a WC_Order order. * @param WC_Order|int $order The WC_Order object or ID of a WC_Order order.
* @return bool Whether the order contains renewal.
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
function wcs_order_contains_renewal( $order ) { function wcs_order_contains_renewal( $order ) {
@@ -64,8 +65,7 @@ function wcs_order_contains_renewal( $order ) {
/** /**
* Checks the cart to see if it contains a subscription product renewal. * Checks the cart to see if it contains a subscription product renewal.
* *
* @param bool | Array The cart item containing the renewal, else false. * @return bool|array The cart item containing the renewal, else false.
* @return string
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
function wcs_cart_contains_renewal() { function wcs_cart_contains_renewal() {
@@ -111,6 +111,7 @@ function wcs_cart_contains_failed_renewal_order_payment() {
* Get the subscription/s to which a resubscribe order relates. * Get the subscription/s to which a resubscribe order relates.
* *
* @param WC_Order|int $order The WC_Order object or ID of a WC_Order order. * @param WC_Order|int $order The WC_Order object or ID of a WC_Order order.
* @return WC_Subscription[] Subscription details in post_id => WC_Subscription form.
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
*/ */
function wcs_get_subscriptions_for_renewal_order( $order ) { function wcs_get_subscriptions_for_renewal_order( $order ) {
@@ -146,7 +147,7 @@ function wcs_get_last_non_early_renewal_order( $subscription ) {
* Checks if manual renewals are required - automatic renewals are disabled. * Checks if manual renewals are required - automatic renewals are disabled.
* *
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v4.0.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v4.0.0
* @return bool Weather manual renewal are required. * @return bool Whether manual renewal is required.
*/ */
function wcs_is_manual_renewal_required() { function wcs_is_manual_renewal_required() {
return class_exists( 'WCS_Manual_Renewal_Manager' ) ? WCS_Manual_Renewal_Manager::is_manual_renewal_required() : false; return class_exists( 'WCS_Manual_Renewal_Manager' ) ? WCS_Manual_Renewal_Manager::is_manual_renewal_required() : false;
@@ -156,7 +157,7 @@ function wcs_is_manual_renewal_required() {
* Checks if manual renewals are enabled. * Checks if manual renewals are enabled.
* *
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v4.0.0 * @since 1.0.0 - Migrated from WooCommerce Subscriptions v4.0.0
* @return bool Weather manual renewal are enabled. * @return bool Whether manual renewal is enabled.
*/ */
function wcs_is_manual_renewal_enabled() { function wcs_is_manual_renewal_enabled() {
return class_exists( 'WCS_Manual_Renewal_Manager' ) ? WCS_Manual_Renewal_Manager::is_manual_renewal_enabled() : false; return class_exists( 'WCS_Manual_Renewal_Manager' ) ? WCS_Manual_Renewal_Manager::is_manual_renewal_enabled() : false;

View File

@@ -4,7 +4,7 @@
* *
* @author Prospress * @author Prospress
* @category WooCommerce Subscriptions/Templates * @category WooCommerce Subscriptions/Templates
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v2.6.4 * @version 7.2.0 - Migrated from WooCommerce Subscriptions v2.6.4
*/ */
if ( ! defined( 'ABSPATH' ) ) { if ( ! defined( 'ABSPATH' ) ) {
@@ -31,7 +31,9 @@ if ( ! defined( 'ABSPATH' ) ) {
<?php foreach ( $subscriptions as $subscription_id => $subscription ) : ?> <?php foreach ( $subscriptions as $subscription_id => $subscription ) : ?>
<tr class="order woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $subscription->get_status() ); ?>"> <tr class="order woocommerce-orders-table__row woocommerce-orders-table__row--status-<?php echo esc_attr( $subscription->get_status() ); ?>">
<td class="subscription-id order-number woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-id woocommerce-orders-table__cell-order-number" data-title="<?php esc_attr_e( 'ID', 'woocommerce-subscriptions' ); ?>"> <td class="subscription-id order-number woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-id woocommerce-orders-table__cell-order-number" data-title="<?php esc_attr_e( 'ID', 'woocommerce-subscriptions' ); ?>">
<a href="<?php echo esc_url( $subscription->get_view_order_url() ); ?>"><?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?></a> <a href="<?php echo esc_url( $subscription->get_view_order_url() ); ?>" aria-label="<?php echo esc_attr( sprintf( __( 'View subscription number %s', 'woocommerce' ), $subscription->get_order_number() ) ) ?>">
<?php echo esc_html( sprintf( _x( '#%s', 'hash before order number', 'woocommerce-subscriptions' ), $subscription->get_order_number() ) ); ?>
</a>
<?php do_action( 'woocommerce_my_subscriptions_after_subscription_id', $subscription ); ?> <?php do_action( 'woocommerce_my_subscriptions_after_subscription_id', $subscription ); ?>
</td> </td>
<td class="subscription-status order-status woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-status woocommerce-orders-table__cell-order-status" data-title="<?php esc_attr_e( 'Status', 'woocommerce-subscriptions' ); ?>"> <td class="subscription-status order-status woocommerce-orders-table__cell woocommerce-orders-table__cell-subscription-status woocommerce-orders-table__cell-order-status" data-title="<?php esc_attr_e( 'Status', 'woocommerce-subscriptions' ); ?>">

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: 7.1.1 * Version: 7.2.0
*/ */

View File

@@ -5,10 +5,10 @@
* 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: 6.3.2 * Version: 6.4.0
* Requires Plugins: woocommerce * Requires Plugins: woocommerce
* *
* WC requires at least: 7.9.0 * WC requires at least: 8.7.1
* WC tested up to: 8.9.0 * WC tested up to: 8.9.0
* Woo: 27147:6115e6d7e297b623a169fdcf5728b224 * Woo: 27147:6115e6d7e297b623a169fdcf5728b224
* *
@@ -78,7 +78,7 @@ class WC_Subscriptions {
public static $plugin_file = __FILE__; public static $plugin_file = __FILE__;
/** @var string */ /** @var string */
public static $version = '6.3.2'; // WRCS: DEFINED_VERSION. public static $version = '6.4.0'; // WRCS: DEFINED_VERSION.
/** @var string */ /** @var string */
public static $wc_minimum_supported_version = '7.7'; public static $wc_minimum_supported_version = '7.7';