diff --git a/src/StoreApi/Routes/V1/Products.php b/src/StoreApi/Routes/V1/Products.php index 2ac7487046c..809b7f83951 100644 --- a/src/StoreApi/Routes/V1/Products.php +++ b/src/StoreApi/Routes/V1/Products.php @@ -275,12 +275,34 @@ public function get_collection_params() { $params['category_operator'] = array( 'description' => __( 'Operator to compare product category terms.', 'woo-gutenberg-products-block' ), 'type' => 'string', - 'enum' => [ 'in', 'not in', 'and' ], + 'enum' => [ 'in', 'not_in', 'and' ], 'default' => 'in', 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg', ); + // If the $_REQUEST contains a taxonomy query, add it to the params and sanitize it. + foreach ( $_REQUEST as $param => $value ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( str_starts_with( $param, '_unstable_tax_' ) && ! str_ends_with( $param, '_operator' ) ) { + $params[ $param ] = array( + 'description' => __( 'Limit result set to products assigned a specific category ID.', 'woo-gutenberg-products-block' ), + 'type' => 'string', + 'sanitize_callback' => 'wp_parse_id_list', + 'validate_callback' => 'rest_validate_request_arg', + ); + } + if ( str_starts_with( $param, '_unstable_tax_' ) && str_ends_with( $param, '_operator' ) ) { + $params[ $param ] = array( + 'description' => __( 'Operator to compare product category terms.', 'woo-gutenberg-products-block' ), + 'type' => 'string', + 'enum' => [ 'in', 'not_in', 'and' ], + 'default' => 'in', + 'sanitize_callback' => 'sanitize_key', + 'validate_callback' => 'rest_validate_request_arg', + ); + } + } + $params['tag'] = array( 'description' => __( 'Limit result set to products assigned a specific tag ID.', 'woo-gutenberg-products-block' ), 'type' => 'string', @@ -291,7 +313,7 @@ public function get_collection_params() { $params['tag_operator'] = array( 'description' => __( 'Operator to compare product tags.', 'woo-gutenberg-products-block' ), 'type' => 'string', - 'enum' => [ 'in', 'not in', 'and' ], + 'enum' => [ 'in', 'not_in', 'and' ], 'default' => 'in', 'sanitize_callback' => 'sanitize_key', 'validate_callback' => 'rest_validate_request_arg', @@ -360,7 +382,7 @@ public function get_collection_params() { 'operator' => array( 'description' => __( 'Operator to compare product attribute terms.', 'woo-gutenberg-products-block' ), 'type' => 'string', - 'enum' => [ 'in', 'not in', 'and' ], + 'enum' => [ 'in', 'not_in', 'and' ], ), ), ), diff --git a/src/StoreApi/Utilities/ProductQuery.php b/src/StoreApi/Utilities/ProductQuery.php index a707e2a277b..34f4d195198 100644 --- a/src/StoreApi/Utilities/ProductQuery.php +++ b/src/StoreApi/Utilities/ProductQuery.php @@ -95,12 +95,24 @@ public function prepare_objects_query( $request ) { 'and' => 'AND', ]; + // Gets all registered product taxonomies and prefixes them with `tax_`. + // This is neeeded to avoid situations where a users registers a new product taxonomy with the same name as default field. + // eg an `sku` taxonomy will be mapped to `tax_sku`. + $all_product_taxonomies = array_map( + function ( $value ) { + return '_unstable_tax_' . $value; + }, + get_taxonomies( array( 'object_type' => array( 'product' ) ), 'names' ) + ); + // Map between taxonomy name and arg key. - $taxonomies = [ + $default_taxonomies = [ 'product_cat' => 'category', 'product_tag' => 'tag', ]; + $taxonomies = array_merge( $all_product_taxonomies, $default_taxonomies ); + // Set tax_query for each passed arg. foreach ( $taxonomies as $taxonomy => $key ) { if ( ! empty( $request[ $key ] ) ) { diff --git a/src/StoreApi/docs/products.md b/src/StoreApi/docs/products.md index 271a555c13e..178e581ff7f 100644 --- a/src/StoreApi/docs/products.md +++ b/src/StoreApi/docs/products.md @@ -2,8 +2,9 @@ The store products API provides public product data so it can be rendered on the client side. -- [List Products](#list-products) -- [Single Product](#single-product) +- [List Products](#list-products) +- [Single Product](#single-product) +- [](#) ## List Products @@ -22,6 +23,7 @@ GET /products?type=simple GET /products?sku=sku-1,sku-2 GET /products?featured=true GET /products?category=t-shirts +GET /products?product-taxonomy=product-taxonomy-term-id GET /products?tag=special-items GET /products?attributes[0][attribute]=pa_color&attributes[0][slug]=red GET /products?on_sale=true @@ -35,34 +37,36 @@ GET /products?return_attribute_counts=pa_size,pa_color GET /products?return_rating_counts=true ``` -| Attribute | Type | Required | Description | -| :------------------- | :------ | :------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| `search` | integer | no | Limit results to those matching a string. | -| `after` | string | no | Limit response to resources created after a given ISO8601 compliant date. | -| `before` | string | no | Limit response to resources created before a given ISO8601 compliant date. | -| `date_column` | string | no | When limiting response using after/before, which date column to compare against. Allowed values: `date`, `date_gmt`, `modified`, `modified_gmt` | -| `exclude` | array | no | Ensure result set excludes specific IDs. | -| `include` | array | no | Limit result set to specific ids. | -| `offset` | integer | no | Offset the result set by a specific number of items. | -| `order` | string | no | Order sort attribute ascending or descending. Allowed values: `asc`, `desc` | -| `orderby` | string | no | Sort collection by object attribute. Allowed values: `date`, `modified`, `id`, `include`, `title`, `slug`, `price`, `popularity`, `rating`, `menu_order`, `comment_count` | -| `parent` | array | no | Limit result set to those of particular parent IDs. | -| `parent_exclude` | array | no | Limit result set to all items except those of a particular parent ID. | -| `type` | string | no | Limit result set to products assigned a specific type. | -| `sku` | string | no | Limit result set to products with specific SKU(s). Use commas to separate. | -| `featured` | boolean | no | Limit result set to featured products. | -| `category` | string | no | Limit result set to products assigned a specific category ID. | -| `category_operator` | string | no | Operator to compare product category terms. Allowed values: `in`, `not_in`, `and` | -| `tag` | string | no | Limit result set to products assigned a specific tag ID. | -| `tag_operator` | string | no | Operator to compare product tags. Allowed values: `in`, `not_in`, `and` | -| `on_sale` | boolean | no | Limit result set to products on sale. | -| `min_price` | string | no | Limit result set to products based on a minimum price, provided using the smallest unit of the currency. | -| `max_price` | string | no | Limit result set to products based on a maximum price, provided using the smallest unit of the currency. | -| `stock_status` | array | no | Limit result set to products with specified stock statuses. Expects an array of strings containing 'instock', 'outofstock' or 'onbackorder'. | -| `attributes` | array | no | Limit result set to specific attribute terms. Expects an array of objects containing `attribute` (taxonomy), `term_id` or `slug`, and optional `operator` for comparison. | -| `attribute_relation` | string | no | The logical relationship between attributes when filtering across multiple at once. | -| `catalog_visibility` | string | no | Determines if hidden or visible catalog products are shown. Allowed values: `any`, `visible`, `catalog`, `search`, `hidden` | -| `rating` | boolean | no | Limit result set to products with a certain average rating. | +| Attribute | Type | Required | Description | +| :------------------------------------------ | :------ | :------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `search` | integer | no | Limit results to those matching a string. | +| `after` | string | no | Limit response to resources created after a given ISO8601 compliant date. | +| `before` | string | no | Limit response to resources created before a given ISO8601 compliant date. | +| `date_column` | string | no | When limiting response using after/before, which date column to compare against. Allowed values: `date`, `date_gmt`, `modified`, `modified_gmt` | +| `exclude` | array | no | Ensure result set excludes specific IDs. | +| `include` | array | no | Limit result set to specific ids. | +| `offset` | integer | no | Offset the result set by a specific number of items. | +| `order` | string | no | Order sort attribute ascending or descending. Allowed values: `asc`, `desc` | +| `orderby` | string | no | Sort collection by object attribute. Allowed values : `date`, `modified`, `id`, `include`, `title`, `slug`, `price`, `popularity`, `rating`, `menu_order`, `comment_count` | +| `parent` | array | no | Limit result set to those of particular parent IDs. | +| `parent_exclude` | array | no | Limit result set to all items except those of a particular parent ID. | +| `type` | string | no | Limit result set to products assigned a specific type. | +| `sku` | string | no | Limit result set to products with specific SKU(s). Use commas to separate. | +| `featured` | boolean | no | Limit result set to featured products. | +| `category` | string | no | Limit result set to products assigned a specific category ID. | +| `category_operator` | string | no | Operator to compare product category terms. Allowed values: `in`, `not_in`, `and` | +| `_unstable_tax_[product-taxonomy]` | string | no | Limit result set to products assigned to the term ID of that custom product taxonomy. `[product-taxonomy]` should be the key of the custom product taxonomy registered. | +| `_unstable_tax_[product-taxonomy]_operator` | string | no | Operator to compare custom product taxonomy terms. Allowed values: `in`, `not_in`, `and` | +| `tag` | string | no | Limit result set to products assigned a specific tag ID. | +| `tag_operator` | string | no | Operator to compare product tags. Allowed values: `in`, `not_in`, `and` | +| `on_sale` | boolean | no | Limit result set to products on sale. | +| `min_price` | string | no | Limit result set to products based on a minimum price, provided using the smallest unit of the currency. | +| `max_price` | string | no | Limit result set to products based on a maximum price, provided using the smallest unit of the currency. | +| `stock_status` | array | no | Limit result set to products with specified stock statuses. Expects an array of strings containing 'instock', 'outofstock' or 'onbackorder'. | +| `attributes` | array | no | Limit result set to specific attribute terms. Expects an array of objects containing `attribute` (taxonomy), `term_id` or `slug`, and optional `operator` for comparison. | +| `attribute_relation` | string | no | The logical relationship between attributes when filtering across multiple at once. | +| `catalog_visibility` | string | no | Determines if hidden or visible catalog products are shown. Allowed values: `any`, `visible`, `catalog`, `search`, `hidden` | +| `rating` | boolean | no | Limit result set to products with a certain average rating. | ```sh curl "https://example-store.com/wp-json/wc/store/v1/products" @@ -186,11 +190,10 @@ curl "https://example-store.com/wp-json/wc/store/v1/products/34" } ``` - ---- +## [We're hiring!](https://woocommerce.com/careers/) Come work with us! 🐞 Found a mistake, or have a suggestion? [Leave feedback about this document here.](https://github.com/woocommerce/woocommerce-gutenberg-products-block/issues/new?assignees=&labels=type%3A+documentation&template=--doc-feedback.md&title=Feedback%20on%20./src/StoreApi/docs/products.md) - +