From aeb7cc57a8d550b1b56ddd8f9006f943f39601ec Mon Sep 17 00:00:00 2001 From: Lena Orobei Date: Wed, 31 Jul 2019 17:26:03 -0500 Subject: [PATCH] magento/graphql-ce#438: Adjust adding configurable products to the shopping cart --- .../BuyRequest/SuperAttributeDataProvider.php | 50 +++++++++++++++-- .../etc/schema.graphqls | 9 +--- .../Model/Cart/AddSimpleProductToCart.php | 7 ++- .../AddConfigurableProductToCartTest.php | 53 ++++--------------- 4 files changed, 62 insertions(+), 57 deletions(-) diff --git a/app/code/Magento/ConfigurableProductGraphQl/Model/Cart/BuyRequest/SuperAttributeDataProvider.php b/app/code/Magento/ConfigurableProductGraphQl/Model/Cart/BuyRequest/SuperAttributeDataProvider.php index 3216fb69c0745..d2567c6e8eda1 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/Model/Cart/BuyRequest/SuperAttributeDataProvider.php +++ b/app/code/Magento/ConfigurableProductGraphQl/Model/Cart/BuyRequest/SuperAttributeDataProvider.php @@ -7,8 +7,12 @@ namespace Magento\ConfigurableProductGraphQl\Model\Cart\BuyRequest; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\Stdlib\ArrayManager; use Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestDataProviderInterface; +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\ConfigurableProductGraphQl\Model\Options\Collection as OptionCollection; /** * DataProvider for building super attribute options in buy requests @@ -21,12 +25,29 @@ class SuperAttributeDataProvider implements BuyRequestDataProviderInterface private $arrayManager; /** + * @var ProductRepositoryInterface + */ + private $productRepository; + + /** + * @var OptionCollection + */ + private $optionCollection; + + /** + * SuperAttributeDataProvider constructor. * @param ArrayManager $arrayManager + * @param ProductRepositoryInterface $productRepository + * @param OptionCollection $optionCollection */ public function __construct( - ArrayManager $arrayManager + ArrayManager $arrayManager, + ProductRepositoryInterface $productRepository, + OptionCollection $optionCollection ) { $this->arrayManager = $arrayManager; + $this->productRepository = $productRepository; + $this->optionCollection = $optionCollection; } /** @@ -34,13 +55,32 @@ public function __construct( */ public function execute(array $cartItemData): array { - $superAttributes = $this->arrayManager->get('configurable_attributes', $cartItemData, []); + $parentSku = $this->arrayManager->get('parent_sku', $cartItemData); + if ($parentSku === null) { + return []; + } + $sku = $this->arrayManager->get('data/sku', $cartItemData); - $superAttributesData = []; - foreach ($superAttributes as $superAttribute) { - $superAttributesData[$superAttribute['id']] = $superAttribute['value']; + try { + $parentProduct = $this->productRepository->get($parentSku); + $product = $this->productRepository->get($sku); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__('Could not find specified product.')); } + $this->optionCollection->addProductId((int)$parentProduct->getId()); + $options = $this->optionCollection->getAttributesByProductId((int)$parentProduct->getId()); + + $superAttributesData = []; + foreach ($options as $option) { + $code = $option['attribute_code']; + foreach ($option['values'] as $optionValue) { + if ($optionValue['value_index'] === $product->getData($code)) { + $superAttributesData[$option['attribute_id']] = $optionValue['value_index']; + break; + } + } + } return ['super_attribute' => $superAttributesData]; } } diff --git a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls index a7fb82e402204..bce391dc20474 100644 --- a/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls +++ b/app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls @@ -50,16 +50,11 @@ type AddConfigurableProductsToCartOutput { input ConfigurableProductCartItemInput { data: CartItemInput! - variant_sku: String @deprecated(reason: "Use CartItemInput.sku instead") - configurable_attributes: [ConfigurableCartItemAttributesInput]! + variant_sku: String @deprecated(reason: "Use CartItemInput.sku instead.") + parent_sku: String! @doc(description: "Configurable product SKU.") customizable_options:[CustomizableOptionInput!] } -input ConfigurableCartItemAttributesInput { - id: Int! - value: Int! -} - type ConfigurableCartItem implements CartItemInterface { customizable_options: [SelectedCustomizableOption]! configurable_options: [SelectedConfigurableOption!]! @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\ConfigurableCartItemOptions") diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 6346acfcb9af5..7053e365114d8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -11,7 +11,6 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; -use Magento\Framework\Stdlib\ArrayManager; use Magento\Quote\Model\Quote; use Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder; @@ -87,7 +86,11 @@ public function execute(Quote $cart, array $cartItemData): void */ private function extractSku(array $cartItemData): string { - if (!isset($cartItemData['data']['sku']) || empty($cartItemData['data']['sku'])) { + // Need to keep this for configurable product and backward compatibility. + if (!empty($cartItemData['parent_sku'])) { + return (string)$cartItemData['parent_sku']; + } + if (empty($cartItemData['data']['sku'])) { throw new GraphQlInputException(__('Missed "sku" in cart item data')); } return (string)$cartItemData['data']['sku']; diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php index 9166ad84be90e..0e334999599b4 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/ConfigurableProduct/AddConfigurableProductToCartTest.php @@ -41,15 +41,15 @@ public function testAddConfigurableProductToCart() $quantity = 2; $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $sku = $product['sku']; + $parentSku = $product['sku']; + $sku = 'simple_20'; $attributeId = (int) $product['configurable_options'][0]['attribute_id']; $optionId = $product['configurable_options'][0]['values'][1]['value_index']; $query = $this->getQuery( $maskedQuoteId, + $parentSku, $sku, - $attributeId, - $optionId, $quantity ); @@ -57,7 +57,7 @@ public function testAddConfigurableProductToCart() $cartItem = current($response['addConfigurableProductsToCart']['cart']['items']); self::assertEquals($quantity, $cartItem['quantity']); - self::assertEquals($sku, $cartItem['product']['sku']); + self::assertEquals($parentSku, $cartItem['product']['sku']); self::assertArrayHasKey('configurable_options', $cartItem); $option = current($cartItem['configurable_options']); @@ -67,32 +67,6 @@ public function testAddConfigurableProductToCart() self::assertArrayHasKey('value_label', $option); } - /** - * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable.php - * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php - * @expectedException \Exception - * @expectedExceptionMessage You need to choose options for your item - */ - public function testAddProductWithInvalidOptions() - { - $searchResponse = $this->graphQlQuery($this->getFetchProductQuery('configurable')); - $product = current($searchResponse['products']['items']); - - $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $sku = $product['sku']; - $attributeId = (int) $product['configurable_options'][0]['attribute_id']; - - $query = $this->getQuery( - $maskedQuoteId, - $sku, - $attributeId, - 9999, - 1 - ); - - $this->graphQlMutation($query); - } - /** * @magentoApiDataFixture Magento/ConfigurableProduct/_files/product_configurable_sku.php * @magentoApiDataFixture Magento/Checkout/_files/active_quote.php @@ -105,15 +79,13 @@ public function testAddProductIfQuantityIsNotAvailable() $product = current($searchResponse['products']['items']); $maskedQuoteId = $this->getMaskedQuoteIdByReservedOrderId->execute('test_order_1'); - $sku = $product['sku']; - $attributeId = (int) $product['configurable_options'][0]['attribute_id']; - $optionId = $product['configurable_options'][0]['values'][1]['value_index']; + $parentSku = $product['sku']; + $sku = 'simple_20'; $query = $this->getQuery( $maskedQuoteId, + $parentSku, $sku, - $attributeId, - $optionId, 2000 ); @@ -122,13 +94,12 @@ public function testAddProductIfQuantityIsNotAvailable() /** * @param string $maskedQuoteId + * @param string $parentSku * @param string $sku - * @param int $optionId - * @param int $value * @param int $quantity * @return string */ - private function getQuery(string $maskedQuoteId, string $sku, int $optionId, int $value, int $quantity): string + private function getQuery(string $maskedQuoteId, string $parentSku, string $sku, int $quantity): string { return <<