Skip to content

Commit 49354ad

Browse files
authored
ENGCOM-5349: GraphQl-622: No possibility to update customizable_options in updateCartItems mutation #626
2 parents c7c66ad + 42c3639 commit 49354ad

File tree

10 files changed

+628
-109
lines changed

10 files changed

+628
-109
lines changed

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

Lines changed: 8 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
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;
@@ -21,25 +19,25 @@
2119
class AddSimpleProductToCart
2220
{
2321
/**
24-
* @var DataObjectFactory
22+
* @var CreateBuyRequest
2523
*/
26-
private $dataObjectFactory;
24+
private $createBuyRequest;
2725

2826
/**
2927
* @var ProductRepositoryInterface
3028
*/
3129
private $productRepository;
3230

3331
/**
34-
* @param DataObjectFactory $dataObjectFactory
3532
* @param ProductRepositoryInterface $productRepository
33+
* @param CreateBuyRequest $createBuyRequest
3634
*/
3735
public function __construct(
38-
DataObjectFactory $dataObjectFactory,
39-
ProductRepositoryInterface $productRepository
36+
ProductRepositoryInterface $productRepository,
37+
CreateBuyRequest $createBuyRequest
4038
) {
41-
$this->dataObjectFactory = $dataObjectFactory;
4239
$this->productRepository = $productRepository;
40+
$this->createBuyRequest = $createBuyRequest;
4341
}
4442

4543
/**
@@ -56,7 +54,7 @@ public function execute(Quote $cart, array $cartItemData): void
5654
{
5755
$sku = $this->extractSku($cartItemData);
5856
$quantity = $this->extractQuantity($cartItemData);
59-
$customizableOptions = $this->extractCustomizableOptions($cartItemData);
57+
$customizableOptions = $cartItemData['customizable_options'] ?? [];
6058

6159
try {
6260
$product = $this->productRepository->get($sku);
@@ -65,7 +63,7 @@ public function execute(Quote $cart, array $cartItemData): void
6563
}
6664

6765
try {
68-
$result = $cart->addProduct($product, $this->createBuyRequest($quantity, $customizableOptions));
66+
$result = $cart->addProduct($product, $this->createBuyRequest->execute($quantity, $customizableOptions));
6967
} catch (\Exception $e) {
7068
throw new GraphQlInputException(
7169
__(
@@ -116,60 +114,4 @@ private function extractQuantity(array $cartItemData): float
116114
}
117115
return $quantity;
118116
}
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-
}
175117
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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;
9+
10+
use Magento\Framework\DataObject;
11+
use Magento\Framework\DataObjectFactory;
12+
13+
/**
14+
* Creates buy request that can be used for working with cart items
15+
*/
16+
class CreateBuyRequest
17+
{
18+
/**
19+
* @var DataObjectFactory
20+
*/
21+
private $dataObjectFactory;
22+
23+
/**
24+
* @param DataObjectFactory $dataObjectFactory
25+
*/
26+
public function __construct(
27+
DataObjectFactory $dataObjectFactory
28+
) {
29+
$this->dataObjectFactory = $dataObjectFactory;
30+
}
31+
32+
/**
33+
* Returns buy request for working with cart items
34+
*
35+
* @param float $qty
36+
* @param array $customizableOptionsData
37+
* @return DataObject
38+
*/
39+
public function execute(float $qty, array $customizableOptionsData): DataObject
40+
{
41+
$customizableOptions = [];
42+
foreach ($customizableOptionsData as $customizableOption) {
43+
if (isset($customizableOption['value_string'])) {
44+
$customizableOptions[$customizableOption['id']] = $this->convertCustomOptionValue(
45+
$customizableOption['value_string']
46+
);
47+
}
48+
}
49+
50+
return $this->dataObjectFactory->create(
51+
[
52+
'data' => [
53+
'qty' => $qty,
54+
'options' => $customizableOptions,
55+
],
56+
]
57+
);
58+
}
59+
60+
/**
61+
* Convert custom options value
62+
*
63+
* @param string $value
64+
* @return string|array
65+
*/
66+
private function convertCustomOptionValue(string $value)
67+
{
68+
$value = trim($value);
69+
if (substr($value, 0, 1) === "[" &&
70+
substr($value, strlen($value) - 1, 1) === "]") {
71+
return explode(',', substr($value, 1, -1));
72+
}
73+
return $value;
74+
}
75+
}
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
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;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
14+
use Magento\Quote\Api\CartItemRepositoryInterface;
15+
use Magento\Quote\Api\CartRepositoryInterface;
16+
use Magento\Quote\Model\Quote;
17+
use Magento\Quote\Model\Quote\Item;
18+
19+
/**
20+
* Update cart item
21+
*/
22+
class UpdateCartItem
23+
{
24+
/**
25+
* @var CreateBuyRequest
26+
*/
27+
private $createBuyRequest;
28+
29+
/**
30+
* @var CartRepositoryInterface
31+
*/
32+
private $quoteRepository;
33+
34+
/**
35+
* @var CartItemRepositoryInterface
36+
*/
37+
private $cartItemRepository;
38+
39+
/**
40+
* @param CartItemRepositoryInterface $cartItemRepository
41+
* @param CartRepositoryInterface $quoteRepository
42+
* @param CreateBuyRequest $createBuyRequest
43+
*/
44+
public function __construct(
45+
CartItemRepositoryInterface $cartItemRepository,
46+
CartRepositoryInterface $quoteRepository,
47+
CreateBuyRequest $createBuyRequest
48+
) {
49+
$this->cartItemRepository = $cartItemRepository;
50+
$this->quoteRepository = $quoteRepository;
51+
$this->createBuyRequest = $createBuyRequest;
52+
}
53+
54+
/**
55+
* Update cart item
56+
*
57+
* @param Quote $cart
58+
* @param int $cartItemId
59+
* @param float $quantity
60+
* @param array $customizableOptionsData
61+
* @return void
62+
* @throws GraphQlInputException
63+
* @throws GraphQlNoSuchEntityException
64+
* @throws NoSuchEntityException
65+
*/
66+
public function execute(Quote $cart, int $cartItemId, float $quantity, array $customizableOptionsData): void
67+
{
68+
if (count($customizableOptionsData) === 0) { // Update only item's qty
69+
$this->updateItemQuantity($cartItemId, $cart, $quantity);
70+
71+
return;
72+
}
73+
74+
try {
75+
$result = $cart->updateItem(
76+
$cartItemId,
77+
$this->createBuyRequest->execute($quantity, $customizableOptionsData)
78+
);
79+
} catch (LocalizedException $e) {
80+
throw new GraphQlInputException(
81+
__(
82+
'Could not update cart item: %message',
83+
['message' => $e->getMessage()]
84+
)
85+
);
86+
}
87+
88+
if ($result->getHasError()) {
89+
throw new GraphQlInputException(
90+
__(
91+
'Could not update cart item: %message',
92+
['message' => $result->getMessage()]
93+
)
94+
);
95+
}
96+
97+
$this->quoteRepository->save($cart);
98+
}
99+
100+
/**
101+
* Updates item qty for the specified cart
102+
*
103+
* @param int $itemId
104+
* @param Quote $cart
105+
* @param float $quantity
106+
* @throws GraphQlNoSuchEntityException
107+
* @throws NoSuchEntityException
108+
* @throws GraphQlNoSuchEntityException
109+
*/
110+
private function updateItemQuantity(int $itemId, Quote $cart, float $quantity)
111+
{
112+
$cartItem = $cart->getItemById($itemId);
113+
if ($cartItem === false) {
114+
throw new GraphQlNoSuchEntityException(
115+
__('Could not find cart item with id: %1.', $itemId)
116+
);
117+
}
118+
$cartItem->setQty($quantity);
119+
$this->validateCartItem($cartItem);
120+
$this->cartItemRepository->save($cartItem);
121+
}
122+
123+
/**
124+
* Validate cart item
125+
*
126+
* @param Item $cartItem
127+
* @return void
128+
* @throws GraphQlInputException
129+
*/
130+
private function validateCartItem(Item $cartItem): void
131+
{
132+
if ($cartItem->getHasError()) {
133+
$errors = [];
134+
foreach ($cartItem->getMessage(false) as $message) {
135+
$errors[] = $message;
136+
}
137+
if (!empty($errors)) {
138+
throw new GraphQlInputException(
139+
__(
140+
'Could not update the product with SKU %sku: %message',
141+
['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))]
142+
)
143+
);
144+
}
145+
}
146+
}
147+
}

0 commit comments

Comments
 (0)