Commit c18c60faa5c for woocommerce
commit c18c60faa5cd64796b4ed23da64eacadfcb518b4
Author: Tom Cafferkey <tjcafferkey@gmail.com>
Date: Thu Nov 5 11:18:32 2026 +0000
Fix download permissions for linked orders (#70367)
* Retain permissions
* Add changefile(s) from automation for the following project(s): woocommerce
* Remove stale user functions PHPStan baseline entries
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/70367-fix-download-permissions-account-linking b/plugins/woocommerce/changelog/70367-fix-download-permissions-account-linking
new file mode 100644
index 00000000000..a0a2adb2862
--- /dev/null
+++ b/plugins/woocommerce/changelog/70367-fix-download-permissions-account-linking
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Preserve download permissions when linking guest orders to customer accounts.
diff --git a/plugins/woocommerce/includes/wc-user-functions.php b/plugins/woocommerce/includes/wc-user-functions.php
index dc414372b00..4c8bffe0584 100644
--- a/plugins/woocommerce/includes/wc-user-functions.php
+++ b/plugins/woocommerce/includes/wc-user-functions.php
@@ -352,12 +352,6 @@ function wc_update_new_customer_past_orders( $customer_id ) {
$order->set_customer_id( $customer->ID );
$order->save();
- if ( $order->has_downloadable_item() ) {
- $data_store = WC_Data_Store::load( 'customer-download' );
- $data_store->delete_by_order_id( $order->get_id() );
- wc_downloadable_product_permissions( $order->get_id(), true );
- }
-
do_action( 'woocommerce_update_new_customer_past_order', $order_id, $customer );
if ( $order->get_status() === OrderInternalStatus::COMPLETED ) {
diff --git a/plugins/woocommerce/phpstan-baseline.neon b/plugins/woocommerce/phpstan-baseline.neon
index 40a0333d191..cb7eeeca08b 100644
--- a/plugins/woocommerce/phpstan-baseline.neon
+++ b/plugins/woocommerce/phpstan-baseline.neon
@@ -35181,12 +35181,6 @@ parameters:
count: 1
path: includes/wc-user-functions.php
- -
- message: '#^Call to an undefined method WC_Data_Store\:\:delete_by_order_id\(\)\.$#'
- identifier: method.notFound
- count: 1
- path: includes/wc-user-functions.php
-
-
message: '#^Call to an undefined method WC_Data_Store\:\:get_downloads_for_customer\(\)\.$#'
identifier: method.notFound
@@ -35199,12 +35193,6 @@ parameters:
count: 1
path: includes/wc-user-functions.php
- -
- message: '#^Call to an undefined method WC_Order\|WC_Order_Refund\:\:has_downloadable_item\(\)\.$#'
- identifier: method.notFound
- count: 1
- path: includes/wc-user-functions.php
-
-
message: '#^Call to an undefined method WC_Order\|WC_Order_Refund\:\:is_download_permitted\(\)\.$#'
identifier: method.notFound
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/customer/functions.php b/plugins/woocommerce/tests/legacy/unit-tests/customer/functions.php
index ae33244281f..361d3a53d6c 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/customer/functions.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/customer/functions.php
@@ -198,6 +198,64 @@ class WC_Tests_Customer_Functions extends WC_Unit_Test_Case {
$this->assertEquals( 0, $linked );
}
+ /**
+ * Linking a guest order must not recreate or reset download permissions.
+ */
+ public function test_linking_guest_order_preserves_download_permissions() {
+ $customer_id = wc_create_new_customer( 'downloads@example.com', 'downloadcustomer', 'testpassword' );
+ $files = array();
+ foreach ( array( 'revoked', 'exhausted', 'valid' ) as $file_id ) {
+ $file = new WC_Product_Download();
+ $file->set_id( $file_id );
+ $file->set_file( 'https://example.com/' . $file_id . '.pdf' );
+ $files[] = $file;
+ }
+ $product = new WC_Product_Simple();
+ $product->set_downloadable( true );
+ $product->set_download_limit( 2 );
+ $product->set_download_expiry( 30 );
+ $product->set_downloads( $files );
+ $product->save();
+
+ $order = new WC_Order();
+ $order->set_billing_email( 'downloads@example.com' );
+ $order->add_product( $product );
+ $order->set_status( OrderStatus::COMPLETED );
+ $order->save();
+ wc_downloadable_product_permissions( $order->get_id() );
+
+ $store = WC_Data_Store::load( 'customer-download' );
+ $permissions = $store->get_downloads( array( 'order_id' => $order->get_id() ) );
+ $this->assertCount( 3, $permissions );
+ $by_file = array();
+ foreach ( $permissions as $permission ) {
+ $by_file[ $permission->get_download_id() ] = $permission;
+ }
+ $by_file['revoked']->delete();
+ $by_file['exhausted']->set_downloads_remaining( 0 );
+ $by_file['exhausted']->set_download_count( 2 );
+ $by_file['exhausted']->save();
+ $expiry = $by_file['valid']->get_access_expires()->getTimestamp();
+
+ $this->assertSame( 1, wc_update_new_customer_past_orders( $customer_id ) );
+ $permissions = $store->get_downloads( array( 'order_id' => $order->get_id() ) );
+ $this->assertCount( 2, $permissions );
+ foreach ( $permissions as $permission ) {
+ $this->assertArrayHasKey( $permission->get_download_id(), $by_file );
+ $this->assertSame( $by_file[ $permission->get_download_id() ]->get_id(), $permission->get_id() );
+ $this->assertEquals( $customer_id, $permission->get_user_id() );
+ if ( 'exhausted' === $permission->get_download_id() ) {
+ $this->assertEquals( 0, $permission->get_downloads_remaining() );
+ $this->assertEquals( 2, $permission->get_download_count() );
+ } else {
+ $this->assertSame( 'valid', $permission->get_download_id() );
+ $this->assertEquals( 2, $permission->get_downloads_remaining() );
+ $this->assertSame( $expiry, $permission->get_access_expires()->getTimestamp() );
+ }
+ }
+ $this->assertCount( 1, wc_get_customer_available_downloads( $customer_id ) );
+ }
+
/**
* Test wc_update_new_customer_past_orders with invalid or changed email.
*