Skip to content

Commit e396420

Browse files
committed
Separate buy request creation into extensible builder
This allows product type graphql modules a method for managing how inputs are mapped when buy requests are created.
1 parent 19fcb92 commit e396420

File tree

6 files changed

+183
-89
lines changed

6 files changed

+183
-89
lines changed

app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php

Lines changed: 17 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,46 @@
88
namespace Magento\QuoteGraphQl\Model\Cart;
99

1010
use Magento\Catalog\Api\ProductRepositoryInterface;
11-
use Magento\Framework\DataObject;
12-
use Magento\Framework\DataObjectFactory;
1311
use Magento\Framework\Exception\NoSuchEntityException;
1412
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
1513
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
14+
use Magento\Framework\Stdlib\ArrayManager;
1615
use Magento\Quote\Model\Quote;
16+
use Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder;
1717

1818
/**
1919
* Add simple product to cart
2020
*/
2121
class AddSimpleProductToCart
2222
{
2323
/**
24-
* @var DataObjectFactory
24+
* @var ArrayManager
2525
*/
26-
private $dataObjectFactory;
26+
private $arrayManager;
2727

2828
/**
2929
* @var ProductRepositoryInterface
3030
*/
3131
private $productRepository;
3232

3333
/**
34-
* @param DataObjectFactory $dataObjectFactory
34+
* @var BuyRequestBuilder
35+
*/
36+
private $buyRequestBuilder;
37+
38+
/**
39+
* @param ArrayManager $arrayManager
3540
* @param ProductRepositoryInterface $productRepository
41+
* @param BuyRequestBuilder $buyRequestBuilder
3642
*/
3743
public function __construct(
38-
DataObjectFactory $dataObjectFactory,
39-
ProductRepositoryInterface $productRepository
44+
ArrayManager $arrayManager,
45+
ProductRepositoryInterface $productRepository,
46+
BuyRequestBuilder $buyRequestBuilder
4047
) {
41-
$this->dataObjectFactory = $dataObjectFactory;
48+
$this->arrayManager = $arrayManager;
4249
$this->productRepository = $productRepository;
50+
$this->buyRequestBuilder = $buyRequestBuilder;
4351
}
4452

4553
/**
@@ -55,8 +63,6 @@ public function __construct(
5563
public function execute(Quote $cart, array $cartItemData): void
5664
{
5765
$sku = $this->extractSku($cartItemData);
58-
$quantity = $this->extractQuantity($cartItemData);
59-
$customizableOptions = $this->extractCustomizableOptions($cartItemData);
6066

6167
try {
6268
$product = $this->productRepository->get($sku);
@@ -65,7 +71,7 @@ public function execute(Quote $cart, array $cartItemData): void
6571
}
6672

6773
try {
68-
$result = $cart->addProduct($product, $this->createBuyRequest($quantity, $customizableOptions));
74+
$result = $cart->addProduct($product, $this->buyRequestBuilder->build($cartItemData));
6975
} catch (\Exception $e) {
7076
throw new GraphQlInputException(
7177
__(
@@ -94,82 +100,4 @@ private function extractSku(array $cartItemData): string
94100
}
95101
return (string)$cartItemData['data']['sku'];
96102
}
97-
98-
/**
99-
* Extract quantity from cart item data
100-
*
101-
* @param array $cartItemData
102-
* @return float
103-
* @throws GraphQlInputException
104-
*/
105-
private function extractQuantity(array $cartItemData): float
106-
{
107-
if (!isset($cartItemData['data']['quantity'])) {
108-
throw new GraphQlInputException(__('Missed "qty" in cart item data'));
109-
}
110-
$quantity = (float)$cartItemData['data']['quantity'];
111-
112-
if ($quantity <= 0) {
113-
throw new GraphQlInputException(
114-
__('Please enter a number greater than 0 in this field.')
115-
);
116-
}
117-
return $quantity;
118-
}
119-
120-
/**
121-
* Extract Customizable Options from cart item data
122-
*
123-
* @param array $cartItemData
124-
* @return array
125-
*/
126-
private function extractCustomizableOptions(array $cartItemData): array
127-
{
128-
if (!isset($cartItemData['customizable_options']) || empty($cartItemData['customizable_options'])) {
129-
return [];
130-
}
131-
132-
$customizableOptionsData = [];
133-
foreach ($cartItemData['customizable_options'] as $customizableOption) {
134-
if (isset($customizableOption['value_string'])) {
135-
$customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue(
136-
$customizableOption['value_string']
137-
);
138-
}
139-
}
140-
return $customizableOptionsData;
141-
}
142-
143-
/**
144-
* Format GraphQl input data to a shape that buy request has
145-
*
146-
* @param float $quantity
147-
* @param array $customOptions
148-
* @return DataObject
149-
*/
150-
private function createBuyRequest(float $quantity, array $customOptions): DataObject
151-
{
152-
return $this->dataObjectFactory->create([
153-
'data' => [
154-
'qty' => $quantity,
155-
'options' => $customOptions,
156-
],
157-
]);
158-
}
159-
160-
/**
161-
* Convert custom options vakue
162-
*
163-
* @param string $value
164-
* @return string|array
165-
*/
166-
private function convertCustomOptionValue(string $value)
167-
{
168-
$value = trim($value);
169-
if (substr($value, 0, 1) === "[" &&
170-
substr($value, strlen($value) - 1, 1) === "]") {
171-
return explode(',', substr($value, 1, -1));
172-
}
173-
return $value;
174-
}
175103
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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\QuoteGraphQl\Model\Cart\BuyRequest;
9+
10+
use Magento\Framework\DataObject;
11+
use Magento\Framework\DataObjectFactory;
12+
13+
class BuyRequestBuilder
14+
{
15+
/**
16+
* @var BuyRequestDataProviderInterface[]
17+
*/
18+
private $providers;
19+
20+
/**
21+
* @var DataObjectFactory
22+
*/
23+
private $dataObjectFactory;
24+
25+
public function __construct(
26+
DataObjectFactory $dataObjectFactory,
27+
array $providers = []
28+
) {
29+
$this->dataObjectFactory = $dataObjectFactory;
30+
$this->providers = $providers;
31+
}
32+
33+
public function build(array $cartItemData): DataObject
34+
{
35+
$requestData = [];
36+
foreach ($this->providers as $provider) {
37+
$requestData = array_merge($requestData, $provider->execute($cartItemData));
38+
}
39+
40+
return $this->dataObjectFactory->create(['data' => $requestData]);
41+
}
42+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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\QuoteGraphQl\Model\Cart\BuyRequest;
9+
10+
interface BuyRequestDataProviderInterface
11+
{
12+
public function execute(array $cartItemData): array;
13+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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\QuoteGraphQl\Model\Cart\BuyRequest;
9+
10+
use Magento\Framework\Stdlib\ArrayManager;
11+
12+
class CustomizableOptionsDataProvider implements BuyRequestDataProviderInterface
13+
{
14+
/**
15+
* @var ArrayManager
16+
*/
17+
private $arrayManager;
18+
19+
/**
20+
* @param ArrayManager $arrayManager
21+
*/
22+
public function __construct(
23+
ArrayManager $arrayManager
24+
) {
25+
$this->arrayManager = $arrayManager;
26+
}
27+
28+
/**
29+
* @inheritdoc
30+
*/
31+
public function execute(array $cartItemData): array
32+
{
33+
$customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []);
34+
35+
$customizableOptionsData = [];
36+
foreach ($customizableOptions as $customizableOption) {
37+
if (isset($customizableOption['value_string'])) {
38+
$customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue(
39+
$customizableOption['value_string']
40+
);
41+
}
42+
}
43+
44+
return ['options' => $customizableOptionsData];
45+
}
46+
47+
/**
48+
* Convert custom options value
49+
*
50+
* @param string $value
51+
* @return string|array
52+
*/
53+
private function convertCustomOptionValue(string $value)
54+
{
55+
$value = trim($value);
56+
if (substr($value, 0, 1) === "[" &&
57+
substr($value, strlen($value) - 1, 1) === "]") {
58+
return explode(',', substr($value, 1, -1));
59+
}
60+
return $value;
61+
}
62+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\QuoteGraphQl\Model\Cart\BuyRequest;
9+
10+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
use Magento\Framework\Stdlib\ArrayManager;
12+
13+
class DefaultDataProvider 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+
$qty = $this->arrayManager->get('data/quantity', $cartItemData);
35+
if (!isset($qty)) {
36+
throw new GraphQlInputException(__('Missing key "quantity" in cart item data'));
37+
}
38+
39+
return ['qty' => (float)$qty];
40+
}
41+
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,12 @@
1010
type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/>
1111
<preference for="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface"
1212
type="Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCart"/>
13+
<type name="Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder">
14+
<arguments>
15+
<argument name="providers" xsi:type="array">
16+
<item name="default" xsi:type="object">Magento\QuoteGraphQl\Model\Cart\BuyRequest\DefaultDataProvider</item>
17+
<item name="customizable_options" xsi:type="object">Magento\QuoteGraphQl\Model\Cart\BuyRequest\CustomizableOptionsDataProvider</item>
18+
</argument>
19+
</arguments>
20+
</type>
1321
</config>

0 commit comments

Comments
 (0)