Commit 0c429e14769 for woocommerce

commit 0c429e1476985ea7a2fc700526c106cf89bbd127
Author: Cole Miller <cole@viztech360.com>
Date:   Fri Nov 6 13:07:18 2026 -0500

    Skip child download scans when parent files are empty (#70668)

    * Skip child download scans when parent files are empty

    * Add changelog entry for empty parent download scans

    * Cover parent downloadability in empty-file regression tests

    * Assert empty parent saves do not prime child post caches

    * Simplify tests

    * Clarify comment

    * Harden test

    * Linting

    ---------

    Co-authored-by: Albert Juhé Lluveras <contact@albertjuhe.com>

diff --git a/plugins/woocommerce/changelog/performance-empty-parent-download-scans b/plugins/woocommerce/changelog/performance-empty-parent-download-scans
new file mode 100644
index 00000000000..a6b14491d8e
--- /dev/null
+++ b/plugins/woocommerce/changelog/performance-empty-parent-download-scans
@@ -0,0 +1,4 @@
+Significance: patch
+Type: performance
+
+Speed up saving variable products that have no parent download files.
diff --git a/plugins/woocommerce/src/Internal/DownloadPermissionsAdjuster.php b/plugins/woocommerce/src/Internal/DownloadPermissionsAdjuster.php
index 4b212c807d5..331694e68df 100644
--- a/plugins/woocommerce/src/Internal/DownloadPermissionsAdjuster.php
+++ b/plugins/woocommerce/src/Internal/DownloadPermissionsAdjuster.php
@@ -44,6 +44,11 @@ class DownloadPermissionsAdjuster {
 			return;
 		}

+		// No parent files means there is nothing to copy onto variations, so skip loading the children.
+		if ( ! $product->get_downloads() ) {
+			return;
+		}
+
 		_prime_post_caches( $children_ids );

 		$are_any_children_downloadable = false;
diff --git a/plugins/woocommerce/tests/php/src/Internal/DownloadPermissionsAdjusterTest.php b/plugins/woocommerce/tests/php/src/Internal/DownloadPermissionsAdjusterTest.php
index 3c050dd79ac..ba2193c963e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/DownloadPermissionsAdjusterTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/DownloadPermissionsAdjusterTest.php
@@ -3,6 +3,8 @@
  * DownloadPermissionsAdjusterTest class file.
  */

+declare( strict_types = 1 );
+
 namespace Automattic\WooCommerce\Tests\Internal;

 use Automattic\WooCommerce\Internal\DownloadPermissionsAdjuster;
@@ -31,17 +33,16 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {
 		// This is needed for "product->set_downloads" to work without actual files.
 		add_filter(
 			'woocommerce_downloadable_file_allowed_mime_types',
-			function() {
+			function () {
 				return array( 'foo' => 'nonsense/foo' );
 			}
 		);
 		add_filter(
 			'woocommerce_downloadable_file_exists',
-			function( $exists, $filename ) {
+			function () {
 				return true;
 			},
-			10,
-			2
+			10
 		);

 		// In these tests, we are not directly concerned with Approved Download Directory functionality.
@@ -92,10 +93,10 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {

 		$this->register_legacy_proxy_function_mocks(
 			array(
-				'as_get_scheduled_actions'  => function( $args, $return_format ) use ( &$as_get_scheduled_actions_invoked ) {
+				'as_get_scheduled_actions'  => function () use ( &$as_get_scheduled_actions_invoked ) {
 					$as_get_scheduled_actions_invoked = true;
 				},
-				'as_schedule_single_action' => function( $timestamp, $hook, $args ) use ( &$as_schedule_single_action_invoked ) {
+				'as_schedule_single_action' => function () use ( &$as_schedule_single_action_invoked ) {
 					$as_schedule_single_action_invoked = true;
 				},
 			)
@@ -108,6 +109,36 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {
 		$this->assertFalse( $as_schedule_single_action_invoked );
 	}

+	/**
+	 * @testdox Does not prime child caches or schedule adjustment when the parent has no download files.
+	 */
+	public function test_parent_without_downloads_does_not_schedule_adjustment() {
+		$product  = $this->create_downloadable_variation_product();
+		$child_id = current( $product->get_children() );
+		$product->set_downloads( array() );
+
+		$as_get_scheduled_actions_invoked  = false;
+		$as_schedule_single_action_invoked = false;
+		$this->register_legacy_proxy_function_mocks(
+			array(
+				'as_get_scheduled_actions'  => function () use ( &$as_get_scheduled_actions_invoked ) {
+					$as_get_scheduled_actions_invoked = true;
+					return array();
+				},
+				'as_schedule_single_action' => function () use ( &$as_schedule_single_action_invoked ) {
+					$as_schedule_single_action_invoked = true;
+				},
+			)
+		);
+
+		clean_post_cache( $child_id );
+		$this->sut->maybe_schedule_adjust_download_permissions( $product );
+
+		$this->assertFalse( $as_get_scheduled_actions_invoked );
+		$this->assertFalse( $as_schedule_single_action_invoked );
+		$this->assertFalse( wp_cache_get( $child_id, 'posts' ) );
+	}
+
 	/**
 	 * @testdox 'maybe_schedule_adjust_download_permissions' does nothing if the an adjustment is already pending.
 	 */
@@ -117,11 +148,11 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {

 		$this->register_legacy_proxy_function_mocks(
 			array(
-				'as_get_scheduled_actions'  => function( $args, $return_format ) use ( &$as_get_scheduled_actions_args ) {
-					$as_get_scheduled_actions_args = $args;
+				'as_get_scheduled_actions'  => function ( $params ) use ( &$as_get_scheduled_actions_args ) {
+					$as_get_scheduled_actions_args = $params;
 					return array( 1 );
 				},
-				'as_schedule_single_action' => function( $timestamp, $hook, $args ) use ( &$as_schedule_single_action_invoked ) {
+				'as_schedule_single_action' => function () use ( &$as_schedule_single_action_invoked ) {
 					$as_schedule_single_action_invoked = true;
 				},
 			)
@@ -148,15 +179,16 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {

 		$this->register_legacy_proxy_function_mocks(
 			array(
-				'as_get_scheduled_actions'  => function( $params, $return_format ) use ( &$as_get_scheduled_actions_args ) {
+				'as_get_scheduled_actions'  => function ( $params ) use ( &$as_get_scheduled_actions_args ) {
 					$as_get_scheduled_actions_args = $params;
 					return array();
 				},
-				'as_schedule_single_action' => function( $timestamp, $hook, $args ) use ( &$as_schedule_single_action_args ) {
+				'as_schedule_single_action' => function ( $timestamp, $hook, $args ) use ( &$as_schedule_single_action_args ) {
 					$as_schedule_single_action_args = array( $timestamp, $hook, $args );
 				},
-				'time'                      => function() {
-					return 0; },
+				'time'                      => function () {
+					return 0;
+				},
 			)
 		);

@@ -389,12 +421,20 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {
 	}

 	/**
-	 * Creates a variable product with a downloadable variation. No downloads are added.
+	 * Creates a variable product with parent downloads and a downloadable variation.
 	 *
 	 * @return \WC_Product A product.
 	 */
 	private function create_downloadable_variation_product() {
 		$product = ProductHelper::create_variation_product();
+		$product->set_downloads(
+			array(
+				array(
+					'name' => 'the_file',
+					'file' => 'the_file.foo',
+				),
+			)
+		);

 		$child = wc_get_product( current( $product->get_children() ) );
 		$child->set_downloadable( true );
@@ -402,5 +442,4 @@ class DownloadPermissionsAdjusterTest extends \WC_Unit_Test_Case {

 		return $product;
 	}
-
 }