Commit 276e66629c7 for woocommerce

commit 276e66629c73f29dcbf9a9fec1218b5e1f011f89
Author: Oleksandr Aratovskyi <79862886+oaratovskyi@users.noreply.github.com>
Date:   Tue Sep 15 21:43:56 2026 +0300

    Add collection parameters filter to REST term endpoints (#68430)

    * feat(rest-api): Add terms collection params filter

    The terms REST controller had no extension point for registering or altering collection parameters.

    Add the taxonomy-specific collection params filter with the resolved taxonomy object while preserving the attribute route guard.

    Refs #38898

    * docs(rest-api): Clarify terms filter query mapping

    The collection parameters filter only changes the registered REST schema, which can make extensions expect query behavior it does not provide.

    Point extension authors to the separate terms query filter that maps request parameters to WP_Term_Query arguments.

    Refs #38898

    * docs(rest-api): Bump terms filter @since to 11.3.0

    The `rest_{$taxonomy}_collection_params` docblock was written when trunk
    was 11.2.0-dev. Since then `release/11.2` has been cut and trunk moved to
    11.3.0-dev, so the filter now ships in 11.3.0 rather than 11.2.0.

    Refs #38898

    Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

    ---------

    Co-authored-by: Brandon Kraft <public@brandonkraft.com>
    Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git a/plugins/woocommerce/changelog/add-38898-rest-terms-collection-params-filter b/plugins/woocommerce/changelog/add-38898-rest-terms-collection-params-filter
new file mode 100644
index 00000000000..bcf476c7f4e
--- /dev/null
+++ b/plugins/woocommerce/changelog/add-38898-rest-terms-collection-params-filter
@@ -0,0 +1,4 @@
+Significance: minor
+Type: add
+
+Add `rest_{$taxonomy}_collection_params` filter to the REST terms controller.
diff --git a/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller.php b/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller.php
index 5e98dbdd082..e3a7aa38c0e 100644
--- a/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller.php
+++ b/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller.php
@@ -792,7 +792,29 @@ abstract class WC_REST_Terms_Controller extends WC_REST_Controller {
 			'validate_callback' => 'rest_validate_request_arg',
 		);

-		return $params;
+		$taxonomy_obj = get_taxonomy( $this->taxonomy );
+
+		// Empty for the attribute terms route, which serves every pa_* taxonomy from one registration.
+		if ( ! $taxonomy_obj ) {
+			return $params;
+		}
+
+		/**
+		 * Filter collection parameters for the terms controller.
+		 *
+		 * The dynamic portion of the hook name, `$this->taxonomy`, refers to the taxonomy slug.
+		 * Shares its name with the WordPress core hook, so a callback added for a taxonomy served by
+		 * both /wp/v2 and /wc/v3 runs for both.
+		 *
+		 * This filter only registers parameters; use `woocommerce_rest_{$taxonomy}_query`
+		 * to map them to `WP_Term_Query` arguments.
+		 *
+		 * @since 11.3.0
+		 *
+		 * @param array       $params   JSON Schema-formatted collection parameters.
+		 * @param WP_Taxonomy $taxonomy Taxonomy object.
+		 */
+		return apply_filters( "rest_{$this->taxonomy}_collection_params", $params, $taxonomy_obj );
 	}

 	/**
diff --git a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
index 716c3e15585..75cc4a66a77 100644
--- a/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
+++ b/plugins/woocommerce/tests/php/includes/rest-api/Controllers/Version3/class-wc-rest-terms-controller-tests.php
@@ -42,4 +42,47 @@ class WC_REST_Terms_Controller_Tests extends WC_Unit_Test_Case {
 		$this->assertEquals( 'taxonomy_1', $value1 );
 		$this->assertEquals( 'taxonomy_2', $value2 );
 	}
+
+	/**
+	 * @testdox 'get_collection_params' passes params and the taxonomy object through the filter.
+	 */
+	public function test_get_collection_params_is_filterable() {
+		$received = null;
+
+		add_filter(
+			'rest_product_cat_collection_params',
+			function ( $params, $taxonomy ) use ( &$received ) {
+				$received         = $taxonomy;
+				$params['custom'] = array( 'type' => 'string' );
+				return $params;
+			},
+			10,
+			2
+		);
+
+		$params = ( new WC_REST_Product_Categories_Controller() )->get_collection_params();
+
+		$this->assertArrayHasKey( 'custom', $params );
+		$this->assertInstanceOf( WP_Taxonomy::class, $received );
+		$this->assertSame( 'product_cat', $received->name );
+	}
+
+	/**
+	 * @testdox 'get_collection_params' does not filter when the controller has no taxonomy.
+	 */
+	public function test_get_collection_params_skips_filter_without_taxonomy() {
+		$fired = false;
+
+		add_filter(
+			'rest__collection_params',
+			function ( $params ) use ( &$fired ) {
+				$fired = true;
+				return $params;
+			}
+		);
+
+		$this->sut->get_collection_params();
+
+		$this->assertFalse( $fired );
+	}
 }