Skip to content

Commit 8d900eb

Browse files
ENGCOM-4453: [Cart Operations] Update Cart Items Mutation #377
- Merge Pull Request magento/graphql-ce#377 from pmclain/graphql-ce:feature/update-cart-items - Merged commits: 1. 37eacee 2. dd42a46 3. 19cc640 4. faacfe0 5. c9d6491 6. 3522857 7. 09a91f3
2 parents c427332 + 09a91f3 commit 8d900eb

File tree

10 files changed

+862
-22
lines changed

10 files changed

+862
-22
lines changed

app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,12 @@ public function __construct(
5050
*/
5151
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
5252
{
53-
if (!isset($args['input']['cart_id'])) {
53+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
5454
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
5555
}
5656
$maskedCartId = $args['input']['cart_id'];
5757

58-
if (!isset($args['input']['coupon_code'])) {
58+
if (!isset($args['input']['coupon_code']) || empty($args['input']['coupon_code'])) {
5959
throw new GraphQlInputException(__('Required parameter "coupon_code" is missing'));
6060
}
6161
$couponCode = $args['input']['coupon_code'];

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function __construct(
3737
*/
3838
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
3939
{
40-
if (!isset($args['cart_id'])) {
40+
if (!isset($args['cart_id']) || empty($args['cart_id'])) {
4141
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
4242
}
4343
$maskedCartId = $args['cart_id'];

app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function __construct(
5050
*/
5151
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
5252
{
53-
if (!isset($args['input']['cart_id'])) {
53+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
5454
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
5555
}
5656
$maskedCartId = $args['input']['cart_id'];

app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
1515
use Magento\Framework\GraphQl\Query\ResolverInterface;
1616
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17-
use Magento\Quote\Api\GuestCartItemRepositoryInterface;
17+
use Magento\Quote\Api\CartItemRepositoryInterface;
1818
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
1919

2020
/**
@@ -23,46 +23,46 @@
2323
class RemoveItemFromCart implements ResolverInterface
2424
{
2525
/**
26-
* @var GuestCartItemRepositoryInterface
26+
* @var GetCartForUser
2727
*/
28-
private $guestCartItemRepository;
28+
private $getCartForUser;
2929

3030
/**
31-
* @var GetCartForUser
31+
* @var CartItemRepositoryInterface
3232
*/
33-
private $getCartForUser;
33+
private $cartItemRepository;
3434

3535
/**
36-
* @param GuestCartItemRepositoryInterface $guestCartItemRepository
3736
* @param GetCartForUser $getCartForUser
37+
* @param CartItemRepositoryInterface $cartItemRepository
3838
*/
3939
public function __construct(
40-
GuestCartItemRepositoryInterface $guestCartItemRepository,
41-
GetCartForUser $getCartForUser
40+
GetCartForUser $getCartForUser,
41+
CartItemRepositoryInterface $cartItemRepository
4242
) {
43-
$this->guestCartItemRepository = $guestCartItemRepository;
4443
$this->getCartForUser = $getCartForUser;
44+
$this->cartItemRepository = $cartItemRepository;
4545
}
4646

4747
/**
4848
* @inheritdoc
4949
*/
5050
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
5151
{
52-
if (!isset($args['input']['cart_id'])) {
53-
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
52+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
53+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing.'));
5454
}
5555
$maskedCartId = $args['input']['cart_id'];
5656

57-
if (!isset($args['input']['cart_item_id'])) {
58-
throw new GraphQlInputException(__('Required parameter "cart_item_id" is missing'));
57+
if (!isset($args['input']['cart_item_id']) || empty($args['input']['cart_item_id'])) {
58+
throw new GraphQlInputException(__('Required parameter "cart_item_id" is missing.'));
5959
}
6060
$itemId = $args['input']['cart_item_id'];
6161

6262
$cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId());
6363

6464
try {
65-
$this->guestCartItemRepository->deleteById($maskedCartId, $itemId);
65+
$this->cartItemRepository->deleteById((int)$cart->getId(), $itemId);
6666
} catch (NoSuchEntityException $e) {
6767
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
6868
} catch (LocalizedException $e) {
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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\Resolver;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
15+
use Magento\Framework\GraphQl\Query\ResolverInterface;
16+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
17+
use Magento\Quote\Api\CartItemRepositoryInterface;
18+
use Magento\Quote\Model\Quote;
19+
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
20+
21+
/**
22+
* @inheritdoc
23+
*/
24+
class UpdateCartItems implements ResolverInterface
25+
{
26+
/**
27+
* @var GetCartForUser
28+
*/
29+
private $getCartForUser;
30+
31+
/**
32+
* @var CartItemRepositoryInterface
33+
*/
34+
private $cartItemRepository;
35+
36+
/**
37+
* @param GetCartForUser $getCartForUser
38+
* @param CartItemRepositoryInterface $cartItemRepository
39+
*/
40+
public function __construct(
41+
GetCartForUser $getCartForUser,
42+
CartItemRepositoryInterface $cartItemRepository
43+
) {
44+
$this->getCartForUser = $getCartForUser;
45+
$this->cartItemRepository = $cartItemRepository;
46+
}
47+
48+
/**
49+
* @inheritdoc
50+
*/
51+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
52+
{
53+
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
54+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing.'));
55+
}
56+
$maskedCartId = $args['input']['cart_id'];
57+
58+
if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items'])
59+
|| !is_array($args['input']['cart_items'])
60+
) {
61+
throw new GraphQlInputException(__('Required parameter "cart_items" is missing.'));
62+
}
63+
$cartItems = $args['input']['cart_items'];
64+
65+
$cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId());
66+
67+
try {
68+
$this->processCartItems($cart, $cartItems);
69+
} catch (NoSuchEntityException $e) {
70+
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
71+
} catch (LocalizedException $e) {
72+
throw new GraphQlInputException(__($e->getMessage()), $e);
73+
}
74+
75+
return [
76+
'cart' => [
77+
'model' => $cart,
78+
],
79+
];
80+
}
81+
82+
/**
83+
* Process cart items
84+
*
85+
* @param Quote $cart
86+
* @param array $items
87+
* @throws GraphQlInputException
88+
* @throws LocalizedException
89+
*/
90+
private function processCartItems(Quote $cart, array $items): void
91+
{
92+
foreach ($items as $item) {
93+
if (!isset($item['cart_item_id']) || empty($item['cart_item_id'])) {
94+
throw new GraphQlInputException(__('Required parameter "cart_item_id" for "cart_items" is missing.'));
95+
}
96+
$itemId = $item['cart_item_id'];
97+
98+
if (!isset($item['quantity'])) {
99+
throw new GraphQlInputException(__('Required parameter "quantity" for "cart_items" is missing.'));
100+
}
101+
$qty = (float)$item['quantity'];
102+
103+
$cartItem = $cart->getItemById($itemId);
104+
if ($cartItem === false) {
105+
throw new GraphQlNoSuchEntityException(
106+
__('Could not find cart item with id: %1.', $item['cart_item_id'])
107+
);
108+
}
109+
110+
if ($qty <= 0.0) {
111+
$this->cartItemRepository->deleteById((int)$cart->getId(), $itemId);
112+
} else {
113+
$cartItem->setQty($qty);
114+
$this->cartItemRepository->save($cartItem);
115+
}
116+
}
117+
}
118+
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type Mutation {
1111
addVirtualProductsToCart(input: AddVirtualProductsToCartInput): AddVirtualProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart")
1212
applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart")
1313
removeCouponFromCart(input: RemoveCouponFromCartInput): RemoveCouponFromCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveCouponFromCart")
14+
updateCartItems(input: UpdateCartItemsInput): UpdateCartItemsOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\UpdateCartItems")
1415
removeItemFromCart(input: RemoveItemFromCartInput): RemoveItemFromCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveItemFromCart")
1516
setShippingAddressesOnCart(input: SetShippingAddressesOnCartInput): SetShippingAddressesOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingAddressesOnCart")
1617
setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart")
@@ -53,6 +54,11 @@ input ApplyCouponToCartInput {
5354
coupon_code: String!
5455
}
5556

57+
input UpdateCartItemsInput {
58+
cart_id: String!
59+
cart_items: [CartItemQuantityInput!]!
60+
}
61+
5662
input RemoveItemFromCartInput {
5763
cart_id: String!
5864
cart_item_id: Int!
@@ -230,6 +236,10 @@ type AddVirtualProductsToCartOutput {
230236
cart: Cart!
231237
}
232238

239+
type UpdateCartItemsOutput {
240+
cart: Cart!
241+
}
242+
233243
type RemoveItemFromCartOutput {
234244
cart: Cart!
235245
}

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,20 +75,24 @@ public function testRemoveItemFromCart()
7575

7676
/**
7777
* @magentoApiDataFixture Magento/Customer/_files/customer.php
78+
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php
7879
* @expectedException \Exception
7980
* @expectedExceptionMessage Could not find a cart with ID "non_existent_masked_id"
8081
*/
8182
public function testRemoveItemFromNonExistentCart()
8283
{
83-
$query = $this->prepareMutationQuery('non_existent_masked_id', 1);
84+
$quote = $this->quoteFactory->create();
85+
$this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
86+
$itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId();
8487

88+
$query = $this->prepareMutationQuery('non_existent_masked_id', $itemId);
8589
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
8690
}
8791

8892
/**
8993
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
9094
*/
91-
public function testRemoveNotExistentItem()
95+
public function testRemoveNonExistentItem()
9296
{
9397
$quote = $this->quoteFactory->create();
9498
$this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
@@ -183,6 +187,50 @@ public function testRemoveItemFromAnotherCustomerCart()
183187
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
184188
}
185189

190+
/**
191+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
192+
* @param string $input
193+
* @param string $message
194+
* @dataProvider dataProviderUpdateWithMissedRequiredParameters
195+
*/
196+
public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
197+
{
198+
$query = <<<QUERY
199+
mutation {
200+
removeItemFromCart(
201+
input: {
202+
{$input}
203+
}
204+
) {
205+
cart {
206+
items {
207+
qty
208+
}
209+
}
210+
}
211+
}
212+
QUERY;
213+
$this->expectExceptionMessage($message);
214+
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
215+
}
216+
217+
/**
218+
* @return array
219+
*/
220+
public function dataProviderUpdateWithMissedRequiredParameters(): array
221+
{
222+
return [
223+
'missed_cart_id' => [
224+
'cart_item_id: 1',
225+
'Required parameter "cart_id" is missing.'
226+
],
227+
'missed_cart_item_id' => [
228+
'cart_id: "test"',
229+
'Required parameter "cart_item_id" is missing.'
230+
],
231+
];
232+
}
233+
186234
/**
187235
* @param string $maskedQuoteId
188236
* @param int $itemId

0 commit comments

Comments
 (0)