Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.

Commit cfd065e

Browse files
committed
Add Configurable Product to Cart Resolver
Allows adding configurable products to cart in the same manner as the current Magento storefront. Fixes #438
1 parent b7dd416 commit cfd065e

File tree

8 files changed

+309
-40
lines changed

8 files changed

+309
-40
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProductGraphQl\Model\Cart\BuyRequest;
9+
10+
use Magento\Framework\Stdlib\ArrayManager;
11+
use Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestDataProviderInterface;
12+
13+
class SuperAttributeDataProvider implements BuyRequestDataProviderInterface
14+
{
15+
/**
16+
* @var ArrayManager
17+
*/
18+
private $arrayManager;
19+
20+
/**
21+
* @param ArrayManager $arrayManager
22+
*/
23+
public function __construct(
24+
ArrayManager $arrayManager
25+
) {
26+
$this->arrayManager = $arrayManager;
27+
}
28+
29+
/**
30+
* @inheritdoc
31+
*/
32+
public function execute(array $cartItemData): array
33+
{
34+
$superAttributes = $this->arrayManager->get('configurable_attributes', $cartItemData, []);
35+
36+
$superAttributesData = [];
37+
foreach ($superAttributes as $superAttribute) {
38+
$superAttributesData[$superAttribute['id']] = $superAttribute['value'];
39+
}
40+
41+
return ['super_attribute' => $superAttributesData];
42+
}
43+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProductGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
12+
use Magento\Framework\GraphQl\Query\ResolverInterface;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\QuoteGraphQl\Model\Cart\AddProductsToCart;
15+
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
16+
17+
/**
18+
* Add configurable products to cart GraphQl resolver
19+
* {@inheritdoc}
20+
*/
21+
class AddConfigurableProductsToCart implements ResolverInterface
22+
{
23+
/**
24+
* @var GetCartForUser
25+
*/
26+
private $getCartForUser;
27+
28+
/**
29+
* @var AddProductsToCart
30+
*/
31+
private $addProductsToCart;
32+
33+
/**
34+
* @param GetCartForUser $getCartForUser
35+
* @param AddProductsToCart $addProductsToCart
36+
*/
37+
public function __construct(
38+
GetCartForUser $getCartForUser,
39+
AddProductsToCart $addProductsToCart
40+
) {
41+
$this->getCartForUser = $getCartForUser;
42+
$this->addProductsToCart = $addProductsToCart;
43+
}
44+
45+
/**
46+
* @inheritdoc
47+
*/
48+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
49+
{
50+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
51+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
52+
}
53+
$maskedCartId = $args['input']['cart_id'];
54+
55+
if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items'])
56+
|| !is_array($args['input']['cart_items'])
57+
) {
58+
throw new GraphQlInputException(__('Required parameter "cart_items" is missing'));
59+
}
60+
$cartItems = $args['input']['cart_items'];
61+
62+
$cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId());
63+
$this->addProductsToCart->execute($cart, $cartItems);
64+
65+
return [
66+
'cart' => [
67+
'model' => $cart,
68+
],
69+
];
70+
}
71+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProductGraphQl\Model\Resolver;
9+
10+
use Magento\Catalog\Helper\Product\Configuration;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\Framework\GraphQl\Query\ResolverInterface;
15+
use Magento\Quote\Model\Quote\Item;
16+
17+
/**
18+
* @inheritdoc
19+
*/
20+
class ConfigurableCartItemOptions implements ResolverInterface
21+
{
22+
private $configurationHelper;
23+
24+
public function __construct(
25+
Configuration $configurationHelper
26+
) {
27+
$this->configurationHelper = $configurationHelper;
28+
}
29+
30+
/**
31+
* Fetch and format configurable variants.
32+
*
33+
* {@inheritdoc}
34+
*/
35+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
36+
{
37+
if (!isset($value['model'])) {
38+
throw new LocalizedException(__('"model" value should be specified'));
39+
}
40+
/** @var Item $cartItem */
41+
$cartItem = $value['model'];
42+
43+
$result = [];
44+
foreach ($this->configurationHelper->getOptions($cartItem) as $option) {
45+
$result[] = [
46+
'id' => $option['option_id'],
47+
'option_label' => $option['label'],
48+
'value_id' => $option['option_value'],
49+
'value_label' => $option['value'],
50+
];
51+
}
52+
53+
return $result;
54+
}
55+
}

app/code/Magento/ConfigurableProductGraphQl/etc/graphql/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,11 @@
2222
</argument>
2323
</arguments>
2424
</type>
25+
<type name="Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder">
26+
<arguments>
27+
<argument name="providers" xsi:type="array">
28+
<item name="super_attribute" xsi:type="object">Magento\ConfigurableProductGraphQl\Model\Cart\BuyRequest\SuperAttributeDataProvider</item>
29+
</argument>
30+
</arguments>
31+
</type>
2532
</config>

app/code/Magento/ConfigurableProductGraphQl/etc/schema.graphqls

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright © Magento, Inc. All rights reserved.
22
# See COPYING.txt for license details.
33
type Mutation {
4-
addConfigurableProductsToCart(input: AddConfigurableProductsToCartInput): AddConfigurableProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart")
4+
addConfigurableProductsToCart(input: AddConfigurableProductsToCartInput): AddConfigurableProductsToCartOutput @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\AddConfigurableProductsToCart")
55
}
66

77
type ConfigurableProduct implements ProductInterface, PhysicalProductInterface, CustomizableProductInterface @doc(description: "ConfigurableProduct defines basic features of a configurable product and its simple product variants") {
@@ -50,13 +50,18 @@ type AddConfigurableProductsToCartOutput {
5050

5151
input ConfigurableProductCartItemInput {
5252
data: CartItemInput!
53-
variant_sku: String!
53+
configurable_attributes: [ConfigurableCartItemAttributesInput]!
5454
customizable_options:[CustomizableOptionInput!]
5555
}
5656

57+
input ConfigurableCartItemAttributesInput {
58+
id: Int!
59+
value: Int!
60+
}
61+
5762
type ConfigurableCartItem implements CartItemInterface {
5863
customizable_options: [SelectedCustomizableOption]!
59-
configurable_options: [SelectedConfigurableOption!]!
64+
configurable_options: [SelectedConfigurableOption!]! @resolver(class: "Magento\\ConfigurableProductGraphQl\\Model\\Resolver\\ConfigurableCartItemOptions")
6065
}
6166

6267
type SelectedConfigurableOption {

app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/DefaultDataProvider.php renamed to app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/QuantityDataProvider.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
1111
use Magento\Framework\Stdlib\ArrayManager;
1212

13-
class DefaultDataProvider implements BuyRequestDataProviderInterface
13+
class QuantityDataProvider implements BuyRequestDataProviderInterface
1414
{
1515
/**
1616
* @var ArrayManager
@@ -31,11 +31,19 @@ public function __construct(
3131
*/
3232
public function execute(array $cartItemData): array
3333
{
34-
$qty = $this->arrayManager->get('data/quantity', $cartItemData);
35-
if (!isset($qty)) {
34+
$quantity = $this->arrayManager->get('data/quantity', $cartItemData);
35+
if (!isset($quantity)) {
3636
throw new GraphQlInputException(__('Missing key "quantity" in cart item data'));
3737
}
3838

39-
return ['qty' => (float)$qty];
39+
$quantity = (float) $quantity;
40+
41+
if ($quantity <= 0) {
42+
throw new GraphQlInputException(
43+
__('Please enter a number greater than 0 in this field.')
44+
);
45+
}
46+
47+
return ['qty' => $quantity];
4048
}
4149
}

app/code/Magento/QuoteGraphQl/etc/graphql/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<type name="Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder">
1414
<arguments>
1515
<argument name="providers" xsi:type="array">
16-
<item name="default" xsi:type="object">Magento\QuoteGraphQl\Model\Cart\BuyRequest\DefaultDataProvider</item>
16+
<item name="quantity" xsi:type="object">Magento\QuoteGraphQl\Model\Cart\BuyRequest\QuantityDataProvider</item>
1717
<item name="customizable_options" xsi:type="object">Magento\QuoteGraphQl\Model\Cart\BuyRequest\CustomizableOptionsDataProvider</item>
1818
</argument>
1919
</arguments>

0 commit comments

Comments
 (0)