diff --git a/plugins/woocommerce-blocks/assets/js/components/product-control/index.js b/plugins/woocommerce-blocks/assets/js/components/product-control/index.js index 2617993fd36..9f436f56be5 100644 --- a/plugins/woocommerce-blocks/assets/js/components/product-control/index.js +++ b/plugins/woocommerce-blocks/assets/js/components/product-control/index.js @@ -26,6 +26,7 @@ class ProductControl extends Component { apiFetch( { path: addQueryArgs( '/wc-pb/v3/products', { per_page: -1, + catalog_visibility: 'visible', status: 'publish', } ), } ) diff --git a/plugins/woocommerce-blocks/assets/js/components/products-control/index.js b/plugins/woocommerce-blocks/assets/js/components/products-control/index.js index 9505974eec1..7cb4a05efd8 100644 --- a/plugins/woocommerce-blocks/assets/js/components/products-control/index.js +++ b/plugins/woocommerce-blocks/assets/js/components/products-control/index.js @@ -24,7 +24,11 @@ class ProductsControl extends Component { componentDidMount() { apiFetch( { - path: addQueryArgs( '/wc-pb/v3/products', { per_page: -1, status: 'publish' } ), + path: addQueryArgs( '/wc-pb/v3/products', { + per_page: -1, + catalog_visibility: 'visible', + status: 'publish', + } ), } ) .then( ( list ) => { this.setState( { list, loading: false } ); diff --git a/plugins/woocommerce-blocks/assets/js/utils/get-query.js b/plugins/woocommerce-blocks/assets/js/utils/get-query.js index f3f15cdbf0e..dce821cb302 100644 --- a/plugins/woocommerce-blocks/assets/js/utils/get-query.js +++ b/plugins/woocommerce-blocks/assets/js/utils/get-query.js @@ -13,6 +13,7 @@ export default function getQuery( blockAttributes, name ) { const query = { status: 'publish', per_page: rows * columns, + catalog_visibility: 'visible', }; if ( categories && categories.length ) { diff --git a/plugins/woocommerce-blocks/assets/js/utils/test/get-query.js b/plugins/woocommerce-blocks/assets/js/utils/test/get-query.js index 6b3d3a34d70..f2753e92a8f 100644 --- a/plugins/woocommerce-blocks/assets/js/utils/test/get-query.js +++ b/plugins/woocommerce-blocks/assets/js/utils/test/get-query.js @@ -81,6 +81,7 @@ describe( 'getQuery', () => { test( 'should return a general query with no category', () => { const query = getQuery( attributes ); expect( query ).toEqual( { + catalog_visibility: 'visible', orderby: 'date', per_page: 12, status: 'publish', @@ -91,6 +92,7 @@ describe( 'getQuery', () => { attributes.categories = []; const query = getQuery( attributes ); expect( query ).toEqual( { + catalog_visibility: 'visible', orderby: 'date', per_page: 12, status: 'publish', @@ -101,6 +103,7 @@ describe( 'getQuery', () => { attributes.categories = [ 1 ]; const query = getQuery( attributes ); expect( query ).toEqual( { + catalog_visibility: 'visible', category: '1', orderby: 'date', per_page: 12, @@ -112,6 +115,7 @@ describe( 'getQuery', () => { attributes.categories = [ 1, 2 ]; const query = getQuery( attributes ); expect( query ).toEqual( { + catalog_visibility: 'visible', category: '1,2', orderby: 'date', per_page: 12, diff --git a/plugins/woocommerce-blocks/includes/class-wgpb-products-controller.php b/plugins/woocommerce-blocks/includes/class-wgpb-products-controller.php index 8241ff1d686..38427f2a42b 100644 --- a/plugins/woocommerce-blocks/includes/class-wgpb-products-controller.php +++ b/plugins/woocommerce-blocks/includes/class-wgpb-products-controller.php @@ -230,10 +230,11 @@ class WGPB_Products_Controller extends WC_REST_Products_Controller { protected function prepare_objects_query( $request ) { $args = parent::prepare_objects_query( $request ); - $orderby = $request->get_param( 'orderby' ); - $order = $request->get_param( 'order' ); - $cat_operator = $request->get_param( 'cat_operator' ); - $attr_operator = $request->get_param( 'attr_operator' ); + $orderby = $request->get_param( 'orderby' ); + $order = $request->get_param( 'order' ); + $cat_operator = $request->get_param( 'cat_operator' ); + $attr_operator = $request->get_param( 'attr_operator' ); + $catalog_visibility = $request->get_param( 'catalog_visibility' ); $ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order ); $args['orderby'] = $ordering_args['orderby']; @@ -259,6 +260,18 @@ class WGPB_Products_Controller extends WC_REST_Products_Controller { } } + if ( in_array( $catalog_visibility, array_keys( wc_get_product_visibility_options() ), true ) ) { + $exclude_from_catalog = 'search' === $catalog_visibility ? '' : 'exclude-from-catalog'; + $exclude_from_search = 'catalog' === $catalog_visibility ? '' : 'exclude-from-search'; + + $args['tax_query'][] = array( + 'taxonomy' => 'product_visibility', + 'field' => 'name', + 'terms' => array( $exclude_from_catalog, $exclude_from_search ), + 'operator' => 'hidden' === $catalog_visibility ? 'AND' : 'NOT IN', + ); + } + return $args; } @@ -295,22 +308,29 @@ class WGPB_Products_Controller extends WC_REST_Products_Controller { * @return array */ public function get_collection_params() { - $params = parent::get_collection_params(); - $params['orderby']['enum'] = array_merge( $params['orderby']['enum'], array( 'price', 'popularity', 'rating', 'menu_order' ) ); - $params['cat_operator'] = array( + $params = parent::get_collection_params(); + $params['orderby']['enum'] = array_merge( $params['orderby']['enum'], array( 'price', 'popularity', 'rating', 'menu_order' ) ); + $params['cat_operator'] = array( 'description' => __( 'Operator to compare product category terms.', 'woo-gutenberg-products-block' ), 'type' => 'string', 'enum' => array( 'IN', 'NOT IN', 'AND' ), 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg', ); - $params['attr_operator'] = array( + $params['attr_operator'] = array( 'description' => __( 'Operator to compare product attribute terms.', 'woo-gutenberg-products-block' ), 'type' => 'string', 'enum' => array( 'IN', 'NOT IN', 'AND' ), 'sanitize_callback' => 'sanitize_text_field', 'validate_callback' => 'rest_validate_request_arg', ); + $params['catalog_visibility'] = array( + 'description' => __( 'Determines if hidden or visible catalog products are shown.', 'woo-gutenberg-products-block' ), + 'type' => 'string', + 'enum' => array( 'visible', 'catalog', 'search', 'hidden' ), + 'sanitize_callback' => 'sanitize_text_field', + 'validate_callback' => 'rest_validate_request_arg', + ); return $params; } diff --git a/plugins/woocommerce-blocks/tests/api/products-extra.php b/plugins/woocommerce-blocks/tests/api/products-extra.php index e915bc4079c..d77900840b8 100644 --- a/plugins/woocommerce-blocks/tests/api/products-extra.php +++ b/plugins/woocommerce-blocks/tests/api/products-extra.php @@ -134,4 +134,86 @@ class WC_Tests_API_Products_Controller extends WC_REST_Unit_Test_Case { $this->assertEquals( '10', $products[0]['price'] ); $this->assertEquals( '15', $products[1]['price'] ); } + + /** + * Test product_visibility queries. + * + * @since 1.3.1 + */ + public function test_product_visibility() { + wp_set_current_user( $this->user ); + $visible_product = WC_Helper_Product::create_simple_product(); + $visible_product->set_name( 'Visible Product' ); + $visible_product->set_catalog_visibility( 'visible' ); + $visible_product->save(); + + $catalog_product = WC_Helper_Product::create_simple_product(); + $catalog_product->set_name( 'Catalog Product' ); + $catalog_product->set_catalog_visibility( 'catalog' ); + $catalog_product->save(); + + $search_product = WC_Helper_Product::create_simple_product(); + $search_product->set_name( 'Search Product' ); + $search_product->set_catalog_visibility( 'search' ); + $search_product->save(); + + $hidden_product = WC_Helper_Product::create_simple_product(); + $hidden_product->set_name( 'Hidden Product' ); + $hidden_product->set_catalog_visibility( 'hidden' ); + $hidden_product->save(); + + $query_params = array( + 'catalog_visibility' => 'visible', + ); + $request = new WP_REST_REQUEST( 'GET', '/wc-pb/v3/products' ); + $request->set_query_params( $query_params ); + $response = $this->server->dispatch( $request ); + $products = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 1, count( $products ) ); + $this->assertEquals( 'Visible Product', $products[0]['name'] ); + + $query_params = array( + 'catalog_visibility' => 'catalog', + 'orderby' => 'id', + 'order' => 'asc', + ); + $request = new WP_REST_REQUEST( 'GET', '/wc-pb/v3/products' ); + $request->set_query_params( $query_params ); + $response = $this->server->dispatch( $request ); + $products = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 2, count( $products ) ); + $this->assertEquals( 'Visible Product', $products[0]['name'] ); + $this->assertEquals( 'Catalog Product', $products[1]['name'] ); + + $query_params = array( + 'catalog_visibility' => 'search', + 'orderby' => 'id', + 'order' => 'asc', + ); + $request = new WP_REST_REQUEST( 'GET', '/wc-pb/v3/products' ); + $request->set_query_params( $query_params ); + $response = $this->server->dispatch( $request ); + $products = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 2, count( $products ) ); + $this->assertEquals( 'Visible Product', $products[0]['name'] ); + $this->assertEquals( 'Search Product', $products[1]['name'] ); + + $query_params = array( + 'catalog_visibility' => 'hidden', + ); + $request = new WP_REST_REQUEST( 'GET', '/wc-pb/v3/products' ); + $request->set_query_params( $query_params ); + $response = $this->server->dispatch( $request ); + $products = $response->get_data(); + + $this->assertEquals( 200, $response->get_status() ); + $this->assertEquals( 1, count( $products ) ); + $this->assertEquals( 'Hidden Product', $products[0]['name'] ); + } }