From 678fa6bff0c0c2614f4e2314bcef305a1bd3d6b5 Mon Sep 17 00:00:00 2001 From: Paulo Arromba <17236129+wavvves@users.noreply.github.com> Date: Wed, 13 Jul 2022 15:02:49 +0100 Subject: [PATCH] Add: Cross-sells for the Store API Cart response. (https://github.com/woocommerce/woocommerce-blocks/pull/6635) * Added Cross-sells object and schema for the API Cart response. * Cross-sells are now WC_Product objects that pass through the visibility filter. * Removed redundant check. * Updated function doc comment. * Cleaned up imports. * Cross-sells item schema (extension of ProductSchema) was removed, and replaced by ProductSchema itself. Cross-sells are direct product representation, and extending this goes out of scope for the task at hand. * Unit testing for cart response containing cross-sell products. --- .../src/StoreApi/SchemaController.php | 1 - .../src/StoreApi/Schemas/V1/CartSchema.php | 22 ++++++++++++++++++ .../tests/php/StoreApi/Routes/Cart.php | 23 ++++++++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/plugins/woocommerce-blocks/src/StoreApi/SchemaController.php b/plugins/woocommerce-blocks/src/StoreApi/SchemaController.php index cc0833f7c94..ecaab22799c 100644 --- a/plugins/woocommerce-blocks/src/StoreApi/SchemaController.php +++ b/plugins/woocommerce-blocks/src/StoreApi/SchemaController.php @@ -38,7 +38,6 @@ class SchemaController { Schemas\V1\BillingAddressSchema::IDENTIFIER => Schemas\V1\BillingAddressSchema::class, Schemas\V1\ShippingAddressSchema::IDENTIFIER => Schemas\V1\ShippingAddressSchema::class, Schemas\V1\CartShippingRateSchema::IDENTIFIER => Schemas\V1\CartShippingRateSchema::class, - Schemas\V1\CartShippingRateSchema::IDENTIFIER => Schemas\V1\CartShippingRateSchema::class, Schemas\V1\CartCouponSchema::IDENTIFIER => Schemas\V1\CartCouponSchema::class, Schemas\V1\CartFeeSchema::IDENTIFIER => Schemas\V1\CartFeeSchema::class, Schemas\V1\CartItemSchema::IDENTIFIER => Schemas\V1\CartItemSchema::class, diff --git a/plugins/woocommerce-blocks/src/StoreApi/Schemas/V1/CartSchema.php b/plugins/woocommerce-blocks/src/StoreApi/Schemas/V1/CartSchema.php index ff0727a7f22..3fbcdf479dd 100644 --- a/plugins/woocommerce-blocks/src/StoreApi/Schemas/V1/CartSchema.php +++ b/plugins/woocommerce-blocks/src/StoreApi/Schemas/V1/CartSchema.php @@ -40,6 +40,13 @@ class CartSchema extends AbstractSchema { */ public $coupon_schema; + /** + * Product item schema instance representing cross-sell items. + * + * @var ProductSchema + */ + public $cross_sells_item_schema; + /** * Fee schema instance. * @@ -84,6 +91,7 @@ class CartSchema extends AbstractSchema { public function __construct( ExtendSchema $extend, SchemaController $controller ) { parent::__construct( $extend, $controller ); $this->item_schema = $this->controller->get( CartItemSchema::IDENTIFIER ); + $this->cross_sells_item_schema = $this->controller->get( ProductSchema::IDENTIFIER ); $this->coupon_schema = $this->controller->get( CartCouponSchema::IDENTIFIER ); $this->fee_schema = $this->controller->get( CartFeeSchema::IDENTIFIER ); $this->shipping_rate_schema = $this->controller->get( CartShippingRateSchema::IDENTIFIER ); @@ -155,6 +163,16 @@ class CartSchema extends AbstractSchema { 'context' => [ 'view', 'edit' ], 'readonly' => true, ], + 'cross_sells' => [ + 'description' => __( 'List of cross-sells items related to cart items.', 'woo-gutenberg-products-block' ), + 'type' => 'array', + 'context' => [ 'view', 'edit' ], + 'readonly' => true, + 'items' => [ + 'type' => 'object', + 'properties' => $this->force_schema_readonly( $this->cross_sells_item_schema->get_properties() ), + ], + ], 'needs_payment' => [ 'description' => __( 'True if the cart needs payment. False for carts with only free products and no shipping costs.', 'woo-gutenberg-products-block' ), 'type' => 'boolean', @@ -323,6 +341,9 @@ class CartSchema extends AbstractSchema { // Get shipping packages to return in the response from the cart. $shipping_packages = $has_calculated_shipping ? $controller->get_shipping_packages() : []; + // Get visible cross sells products. + $cross_sells = array_filter( array_map( 'wc_get_product', $cart->get_cross_sells() ), 'wc_products_array_filter_visible' ); + return [ 'coupons' => $this->get_item_responses_from_schema( $this->coupon_schema, $cart->get_applied_coupons() ), 'shipping_rates' => $this->get_item_responses_from_schema( $this->shipping_rate_schema, $shipping_packages ), @@ -331,6 +352,7 @@ class CartSchema extends AbstractSchema { 'items' => $this->get_item_responses_from_schema( $this->item_schema, $cart->get_cart() ), 'items_count' => $cart->get_cart_contents_count(), 'items_weight' => wc_get_weight( $cart->get_cart_contents_weight(), 'g' ), + 'cross_sells' => $this->get_item_responses_from_schema( $this->cross_sells_item_schema, $cross_sells ), 'needs_payment' => $cart->needs_payment(), 'needs_shipping' => $cart->needs_shipping(), 'has_calculated_shipping' => $has_calculated_shipping, diff --git a/plugins/woocommerce-blocks/tests/php/StoreApi/Routes/Cart.php b/plugins/woocommerce-blocks/tests/php/StoreApi/Routes/Cart.php index 276ce6be1f0..025fe113d88 100644 --- a/plugins/woocommerce-blocks/tests/php/StoreApi/Routes/Cart.php +++ b/plugins/woocommerce-blocks/tests/php/StoreApi/Routes/Cart.php @@ -5,7 +5,6 @@ namespace Automattic\WooCommerce\Blocks\Tests\StoreApi\Routes; -use Automattic\WooCommerce\Blocks\Tests\StoreApi\Routes\ControllerTestCase; use Automattic\WooCommerce\Blocks\Tests\Helpers\FixtureData; use Automattic\WooCommerce\Blocks\Tests\Helpers\ValidateSchema; @@ -40,8 +39,21 @@ class Cart extends ControllerTestCase { 'weight' => 10, ) ), + + $fixtures->get_simple_product( + array( + 'name' => 'Test Product 3', + 'stock_status' => 'instock', + 'regular_price' => 10, + 'weight' => 10, + ) + ), ); + // Add product #3 as a cross-sell for product #1. + $this->products[0]->set_cross_sell_ids( array( $this->products[2]->get_id() ) ); + $this->products[0]->save(); + $this->coupon = $fixtures->get_coupon( array( 'code' => 'test_coupon', @@ -53,7 +65,7 @@ class Cart extends ControllerTestCase { wc_empty_cart(); $this->keys = array(); $this->keys[] = wc()->cart->add_to_cart( $this->products[0]->get_id(), 2 ); - $this->keys[] = wc()->cart->add_to_cart( $this->products[1]->get_id(), 1 ); + $this->keys[] = wc()->cart->add_to_cart( $this->products[1]->get_id() ); wc()->cart->apply_coupon( $this->coupon->get_code() ); // Draft order. @@ -78,6 +90,11 @@ class Cart extends ControllerTestCase { 'items' => function( $value ) { return count( $value ) === 2; }, + 'cross_sells' => array( + array( + 'id' => $this->products[2]->get_id(), + ), + ), 'totals' => array( 'currency_code' => 'USD', 'currency_minor_unit' => 2, @@ -475,6 +492,7 @@ class Cart extends ControllerTestCase { $this->assertArrayHasKey( 'needs_shipping', $data ); $this->assertArrayHasKey( 'items_weight', $data ); $this->assertArrayHasKey( 'totals', $data ); + $this->assertArrayHasKey( 'cross_sells', $data ); } /** @@ -483,7 +501,6 @@ class Cart extends ControllerTestCase { public function test_get_item_schema() { $routes = new \Automattic\WooCommerce\StoreApi\RoutesController( new \Automattic\WooCommerce\StoreApi\SchemaController( $this->mock_extend ) ); $controller = $routes->get( 'cart', 'v1' ); - $schema = $controller->get_item_schema(); $cart = wc()->cart; $response = $controller->prepare_item_for_response( $cart, new \WP_REST_Request() ); $schema = $controller->get_item_schema();