Commit 27aaa6ec142 for woocommerce
commit 27aaa6ec14201da78fbc18c1b7f1ee5a56a8f222
Author: Tom Cafferkey <tjcafferkey@gmail.com>
Date: Tue Jul 7 14:33:15 2026 +0100
Fix duplicate order download permissions (#66237)
* Fix duplicate order download permissions
* Add changefile(s) from automation for the following project(s): woocommerce
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/66237-fix-order-download-permission-duplicates b/plugins/woocommerce/changelog/66237-fix-order-download-permission-duplicates
new file mode 100644
index 00000000000..2846bbfb3f3
--- /dev/null
+++ b/plugins/woocommerce/changelog/66237-fix-order-download-permission-duplicates
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent duplicate order download permissions when granting access to a product again.
\ No newline at end of file
diff --git a/plugins/woocommerce/client/legacy/js/admin/meta-boxes-order.js b/plugins/woocommerce/client/legacy/js/admin/meta-boxes-order.js
index b69e8d7af3d..187e7163230 100644
--- a/plugins/woocommerce/client/legacy/js/admin/meta-boxes-order.js
+++ b/plugins/woocommerce/client/legacy/js/admin/meta-boxes-order.js
@@ -1518,9 +1518,26 @@ jQuery( function ( $ ) {
};
$.post( woocommerce_admin_meta_boxes.ajax_url, data, function( response ) {
-
if ( response && -1 !== parseInt( response ) ) {
- $( '.order_download_permissions .wc-metaboxes' ).append( response );
+ var existingDownloads = {};
+ var $newPermissions = $( response ).filter( '.wc-metabox' );
+
+ $( '.order_download_permissions .revoke_access' ).each( function() {
+ existingDownloads[ $( this ).attr( 'rel' ) ] = true;
+ } );
+
+ $newPermissions = $newPermissions.filter( function() {
+ var downloadKey = $( this ).find( '.revoke_access' ).attr( 'rel' );
+
+ if ( existingDownloads[ downloadKey ] ) {
+ return false;
+ }
+
+ existingDownloads[ downloadKey ] = true;
+ return true;
+ } );
+
+ $( '.order_download_permissions .wc-metaboxes' ).append( $newPermissions );
} else {
window.alert( woocommerce_admin_meta_boxes.i18n_download_permission_fail );
}
diff --git a/plugins/woocommerce/includes/class-wc-ajax.php b/plugins/woocommerce/includes/class-wc-ajax.php
index 599c9d2a7ce..138cb54a75d 100644
--- a/plugins/woocommerce/includes/class-wc-ajax.php
+++ b/plugins/woocommerce/includes/class-wc-ajax.php
@@ -1037,6 +1037,18 @@ class WC_AJAX {
$data = array();
$items = $order->get_items();
+ /**
+ * Customer download data store.
+ *
+ * @var WC_Customer_Download_Data_Store $data_store
+ */
+ $data_store = WC_Data_Store::load( 'customer-download' );
+ $existing_download_access = array();
+
+ foreach ( $data_store->get_downloads( array( 'order_id' => $order_id ) ) as $download ) {
+ $existing_download_access[ $download->get_product_id() . '|' . $download->get_download_id() ] = true;
+ }
+
// Check against order items first.
foreach ( $items as $item ) {
$product = $item->get_product();
@@ -1065,8 +1077,15 @@ class WC_AJAX {
if ( ! empty( $download_data['files'] ) ) {
foreach ( $download_data['files'] as $download_id => $file ) {
+ $download_access_key = $product_id . '|' . $download_id;
+
+ if ( isset( $existing_download_access[ $download_access_key ] ) ) {
+ continue;
+ }
+
$inserted_id = wc_downloadable_file_permission( $download_id, $product->get_id(), $order, $download_data['quantity'], $download_data['order_item'] );
if ( $inserted_id ) {
+ $existing_download_access[ $download_access_key ] = true;
$download = new WC_Customer_Download( $inserted_id );
++$loop;
++$file_counter;