Updates to 7.6.0

This commit is contained in:
WooCommerce
2025-06-12 10:18:59 +00:00
parent 924e4d86bd
commit c0994caaed
15 changed files with 617 additions and 8260 deletions

View File

@@ -1,5 +1,14 @@
*** WooCommerce Subscriptions Changelog ***
2025-06-11 - version 7.6.0
* Update: Allow updating billing info on existing subscriptions when customer changes account details.
* Fix: Use floats instead of integers for tax calculation in subscription switching when prices include tax.
* Fix: Enhance checks in email templates upgrade script for WooCommerce Subscriptions core 8.3.0.
* Dev: Refactor argument processing in run-tests.sh to add a direct check for the -w flag.
* Fix: Undefined array key `new`
* Fix: Ensure subscription exists before updating its last order date.
* Fix: Prevent fatal error when the line items no longer exist in the database.
2025-05-20 - version 7.5.0
* Update: Add pagination to the related orders list in the My Account > View Subscription page.
* Fix: Infinite loop when trying to load subscription related orders meta after cache busting.

View File

@@ -673,6 +673,10 @@ class WCS_Admin_Meta_Boxes {
foreach ( $item_data['line_subtotal'] as $line_item_id => $new_line_subtotal ) {
$line_item = WC_Order_Factory::get_order_item( $line_item_id );
if ( ! $line_item ) {
continue;
}
// If this item's subtracted tax data hasn't been repaired, do that now.
if ( $line_item->meta_exists( '_subtracted_base_location_tax' ) ) {
WC_Subscriptions_Upgrader::repair_subtracted_base_taxes( $line_item->get_id() );

View File

@@ -23,10 +23,13 @@ class WC_Subscriptions_Addresses {
add_action( 'template_redirect', array( __CLASS__, 'maybe_restrict_edit_address_endpoint' ) );
add_action( 'woocommerce_after_edit_address_form_billing', __CLASS__ . '::maybe_add_edit_address_checkbox', 10 );
add_action( 'woocommerce_after_edit_address_form_shipping', __CLASS__ . '::maybe_add_edit_address_checkbox', 10 );
add_action( 'woocommerce_edit_account_form_fields', __CLASS__ . '::maybe_add_edit_addresses_checkbox' );
add_action( 'woocommerce_after_edit_address_form_billing', __CLASS__ . '::maybe_add_edit_address_checkbox' );
add_action( 'woocommerce_after_edit_address_form_shipping', __CLASS__ . '::maybe_add_edit_address_checkbox' );
add_action( 'woocommerce_customer_save_address', __CLASS__ . '::maybe_update_subscription_addresses', 10, 2 );
add_action( 'woocommerce_save_account_details', __CLASS__ . '::maybe_update_subscription_addresses_contact' );
add_filter( 'woocommerce_address_to_edit', __CLASS__ . '::maybe_populate_subscription_addresses', 10 );
@@ -111,7 +114,8 @@ class WC_Subscriptions_Addresses {
if ( isset( $wp->query_vars['edit-address'] ) ) {
$address_type = esc_attr( $wp->query_vars['edit-address'] );
} else {
$address_type = ( ! isset( $_GET['address'] ) ) ? esc_attr( $_GET['address'] ) : '';
// No need to check nonce or sanitize address below as it'll be passed via wcs_get_address_type_to_display
$address_type = ( isset( $_GET['address'] ) ) ? esc_attr( wp_unslash( $_GET['address'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
}
// translators: $1: address type (Shipping Address / Billing Address), $2: opening <strong> tag, $3: closing </strong> tag
@@ -123,7 +127,14 @@ class WC_Subscriptions_Addresses {
'type' => 'checkbox',
'class' => array( 'form-row-wide' ),
'label' => $label,
'default' => apply_filters( 'wcs_update_all_subscriptions_addresses_checked', false ),
/**
* Filters whether the update all subscriptions addresses checkbox should be checked by default.
*
* @param bool $checked Whether the checkbox should be checked by default.
* @since 2.3.7 Introduced.
* @since 7.5.0 Default changed to true.
*/
'default' => apply_filters( 'wcs_update_all_subscriptions_addresses_checked', true ),
)
);
}
@@ -133,6 +144,99 @@ class WC_Subscriptions_Addresses {
}
}
/**
* Outputs the necessary markup on the "My Account" > "Edit Account" page for editing contact info (Name, Email)
* to check if the customer wants to update the contact info in Billing addresses for all of their active subscriptions.
*
* @since 7.5.0
*/
public static function maybe_add_edit_addresses_checkbox() {
global $wp;
// Escape early because we're not on the edit account page.
if ( ! isset( $wp->query_vars['edit-account'] ) ) {
return;
}
// No need to render UI if user doesn't have subscriptions
if ( ! wcs_user_has_subscription() ) {
return;
}
// translators: $1: address type (Billing Address), $2: opening <strong> tag, $3: closing </strong> tag
$label = sprintf( esc_html__( 'Update the %1$s contact used for %2$sall%3$s future renewals of my active subscriptions', 'woocommerce-subscriptions' ), wcs_get_address_type_to_display( 'billing' ), '<strong>', '</strong>' );
woocommerce_form_field(
'update_all_subscriptions_billing_contact',
array(
'type' => 'checkbox',
'class' => array( 'form-row-wide' ),
'label' => $label,
'default' => true, // Default to checked, intentionally not passed through the filter.
)
);
// Note, there is no need to add one more nonce here, we'll rely on existing save-account-details-nonce.
}
/**
* When user's contact info is successfully updated, check if the subscriber
* has also requested to update the contact info in addresses on existing subscriptions and if so, go ahead and update
* the addresses on the initial order for each subscription.
*
* @param int $user_id The ID of a user who own's the subscription (and address)
* @since 7.5.0
*/
public static function maybe_update_subscription_addresses_contact( $user_id ) {
// Verify nonce will take care of validation, and wc_get_var will check if the value is set.
$nonce = isset( $_POST['save-account-details-nonce'] ) ? wp_unslash( $_POST['save-account-details-nonce'] ) : ( isset( $_POST['_wpnonce'] ) ? wp_unslash( $_POST['_wpnonce'] ) : '' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$nonce = wc_get_var( $nonce, '' );
if ( ! wp_verify_nonce( $nonce, 'save_account_details' ) ) {
return;
}
// Verify that the current user is updating their own account
$current_user_id = get_current_user_id();
if ( $current_user_id <= 0 || $current_user_id !== $user_id ) {
return;
}
// Check if user has subscriptions and if they've checked the update checkbox
if ( ! wcs_user_has_subscription( $current_user_id ) || ! isset( $_POST['update_all_subscriptions_billing_contact'] ) || wc_notice_count( 'error' ) > 0 ) {
return;
}
// Get user data directly from the user object instead of POST data
$user = get_userdata( $user_id );
if ( ! $user ) {
return;
}
// Get the contact information from the user object
$contact_info = array(
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->user_email,
);
// Only proceed if we have contact information to update
if ( empty( $contact_info['first_name'] ) && empty( $contact_info['last_name'] ) && empty( $contact_info['email'] ) ) {
return;
}
// Get all active subscriptions for the user
$users_subscriptions = wcs_get_users_subscriptions( $user_id );
// Update the billing contact info for each active subscription
foreach ( $users_subscriptions as $subscription ) {
if ( $subscription->has_status( array( 'active', 'on-hold' ) ) ) {
// Update the billing address with the new contact information
wcs_set_order_address( $subscription, $contact_info, 'billing' );
$subscription->save();
}
}
}
/**
* When a subscriber's billing or shipping address is successfully updated, check if the subscriber
* has also requested to update the addresses on existing subscriptions and if so, go ahead and update
@@ -147,7 +251,7 @@ class WC_Subscriptions_Addresses {
return;
}
$address_type = ( 'billing' == $address_type || 'shipping' == $address_type ) ? $address_type : '';
$address_type = ( 'billing' === $address_type || 'shipping' === $address_type ) ? $address_type : '';
$address_fields = WC()->countries->get_address_fields( esc_attr( $_POST[ $address_type . '_country' ] ), $address_type . '_' );
$address = array();

View File

@@ -2504,6 +2504,9 @@ class WC_Subscriptions_Order {
foreach ( $subscription_ids as $subscription_id ) {
$subscription = wcs_get_subscription( $subscription_id );
if ( ! $subscription ) {
continue;
}
self::update_subscription_last_order_date_created( $subscription, $exclude_statuses );
}
@@ -2524,6 +2527,9 @@ class WC_Subscriptions_Order {
}
$subscription = wcs_get_subscription( $object_id );
if ( ! $subscription ) {
return;
}
self::update_subscription_last_order_date_created( $subscription );
}

View File

@@ -1082,6 +1082,8 @@ class WC_Subscriptions_Product {
// Only set the meta value when the object has a meta value to workaround ambiguous default return values
if ( $product->meta_exists( $prefixed_key ) ) {
$meta_value = $product->get_meta( $prefixed_key, true );
} elseif ( $product->meta_exists( $meta_key ) ) {
$meta_value = $product->get_meta( $meta_key, true );
}
} elseif ( isset( $product->{$meta_key} ) ) { // WC < 3.0
$meta_value = $product->{$meta_key};

View File

@@ -87,7 +87,7 @@ class WCS_Limiter {
} else { // When mixed checkout is enabled
foreach ( WC()->cart->cart_contents as $cart_item ) {
// If the variable product is limited, it can't be purchased if it is the same variation
if ( $product->get_parent_id() == wcs_get_objects_property( $cart_item['data'], 'parent_id' ) && $product->get_id() != $cart_item['data']->get_id() ) {
if ( $product->get_parent_id() === $cart_item['data']->get_parent_id() && $product->get_id() !== $cart_item['data']->get_id() ) {
$purchasable = false;
break;
}

View File

@@ -33,6 +33,8 @@ class WCS_Object_Data_Cache_Manager_Many_To_One extends WCS_Object_Data_Cache_Ma
*/
protected function trigger_update_cache_hook_from_change( $object, $key, $change ) {
$previous_value = ! empty( $change['previous'] ) ? $change['previous'] : '';
$this->trigger_update_cache_hook( $change['type'], $object->get_id(), $key, $change['new'], $previous_value );
// When a meta is being deleted, the `new` key is not set.
$new = ! empty( $change['new'] ) ? $change['new'] : '';
$this->trigger_update_cache_hook( $change['type'], $object->get_id(), $key, $new, $previous_value );
}
}

View File

@@ -39,9 +39,10 @@ class WCS_Upgrade_8_3_0 {
WCS_Upgrade_Logger::add( '8.3.0 - Updating subscription email settings.' );
foreach ( $settings_names as $settings_name ) {
$option = get_option( $settings_name );
// Cast to array helps us to avoid issues with further checks or leave the option unchanged if its format is modified by other plugins.
$option = (array) get_option( $settings_name );
if ( ! $option || ( empty( $option['subject'] && empty( $option['heading'] ) ) ) ) {
if ( empty( $option['subject'] ) && empty( $option['heading'] ) ) {
WCS_Upgrade_Logger::add( sprintf( 'Subscription email settings not found: %s.', $settings_name ) );
continue;
}

View File

@@ -2235,10 +2235,10 @@ class WC_Subscriptions_Switcher {
if ( $order_item && ! is_bool( $order_item ) ) {
$found_item = true;
$item_total = (int) $order_item->get_total();
$item_total = (float) $order_item->get_total();
if ( $order->get_prices_include_tax( 'edit' ) ) {
$item_total += (int) $order_item->get_total_tax();
$item_total += (float) $order_item->get_total_tax();
}
// Remove any signup fees if necessary.

11
languages/README.md Normal file
View File

@@ -0,0 +1,11 @@
# Languages
## Generating POT
The generated POT template file is not included in this repository. It gets generated when building the project:
```
npm run build
```
After the build completes, you'll find a `woocommerce-subscriptions.pot` strings file in this directory.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'woocommerce/woocommerce-subscriptions',
'pretty_version' => 'dev-release/7.5.0',
'version' => 'dev-release/7.5.0',
'reference' => '8a1aa156addc46303ccd0cf815f732235a8c2acf',
'pretty_version' => 'dev-release/7.6.0',
'version' => 'dev-release/7.6.0',
'reference' => 'd10def0fd6301975f28b30ae7009dc41139e063f',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -20,9 +20,9 @@
'dev_requirement' => false,
),
'woocommerce/woocommerce-subscriptions' => array(
'pretty_version' => 'dev-release/7.5.0',
'version' => 'dev-release/7.5.0',
'reference' => '8a1aa156addc46303ccd0cf815f732235a8c2acf',
'pretty_version' => 'dev-release/7.6.0',
'version' => 'dev-release/7.6.0',
'reference' => 'd10def0fd6301975f28b30ae7009dc41139e063f',
'type' => 'wordpress-plugin',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),

View File

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