Skip to content

Commit

Permalink
ENGCOM-4453: [Cart Operations] Update Cart Items Mutation #377
Browse files Browse the repository at this point in the history
 - 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
  • Loading branch information
magento-engcom-team committed Mar 6, 2019
2 parents c427332 + 09a91f3 commit 8d900eb
Show file tree
Hide file tree
Showing 10 changed files with 862 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ public function __construct(
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id'])) {
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
}
$maskedCartId = $args['input']['cart_id'];

if (!isset($args['input']['coupon_code'])) {
if (!isset($args['input']['coupon_code']) || empty($args['input']['coupon_code'])) {
throw new GraphQlInputException(__('Required parameter "coupon_code" is missing'));
}
$couponCode = $args['input']['coupon_code'];
Expand Down
2 changes: 1 addition & 1 deletion app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function __construct(
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['cart_id'])) {
if (!isset($args['cart_id']) || empty($args['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
}
$maskedCartId = $args['cart_id'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function __construct(
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id'])) {
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
}
$maskedCartId = $args['input']['cart_id'];
Expand Down
28 changes: 14 additions & 14 deletions app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\GuestCartItemRepositoryInterface;
use Magento\Quote\Api\CartItemRepositoryInterface;
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;

/**
Expand All @@ -23,46 +23,46 @@
class RemoveItemFromCart implements ResolverInterface
{
/**
* @var GuestCartItemRepositoryInterface
* @var GetCartForUser
*/
private $guestCartItemRepository;
private $getCartForUser;

/**
* @var GetCartForUser
* @var CartItemRepositoryInterface
*/
private $getCartForUser;
private $cartItemRepository;

/**
* @param GuestCartItemRepositoryInterface $guestCartItemRepository
* @param GetCartForUser $getCartForUser
* @param CartItemRepositoryInterface $cartItemRepository
*/
public function __construct(
GuestCartItemRepositoryInterface $guestCartItemRepository,
GetCartForUser $getCartForUser
GetCartForUser $getCartForUser,
CartItemRepositoryInterface $cartItemRepository
) {
$this->guestCartItemRepository = $guestCartItemRepository;
$this->getCartForUser = $getCartForUser;
$this->cartItemRepository = $cartItemRepository;
}

/**
* @inheritdoc
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing.'));
}
$maskedCartId = $args['input']['cart_id'];

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

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

try {
$this->guestCartItemRepository->deleteById($maskedCartId, $itemId);
$this->cartItemRepository->deleteById((int)$cart->getId(), $itemId);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
} catch (LocalizedException $e) {
Expand Down
118 changes: 118 additions & 0 deletions app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\CartItemRepositoryInterface;
use Magento\Quote\Model\Quote;
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;

/**
* @inheritdoc
*/
class UpdateCartItems implements ResolverInterface
{
/**
* @var GetCartForUser
*/
private $getCartForUser;

/**
* @var CartItemRepositoryInterface
*/
private $cartItemRepository;

/**
* @param GetCartForUser $getCartForUser
* @param CartItemRepositoryInterface $cartItemRepository
*/
public function __construct(
GetCartForUser $getCartForUser,
CartItemRepositoryInterface $cartItemRepository
) {
$this->getCartForUser = $getCartForUser;
$this->cartItemRepository = $cartItemRepository;
}

/**
* @inheritdoc
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_id" is missing.'));
}
$maskedCartId = $args['input']['cart_id'];

if (!isset($args['input']['cart_items']) || empty($args['input']['cart_items'])
|| !is_array($args['input']['cart_items'])
) {
throw new GraphQlInputException(__('Required parameter "cart_items" is missing.'));
}
$cartItems = $args['input']['cart_items'];

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

try {
$this->processCartItems($cart, $cartItems);
} catch (NoSuchEntityException $e) {
throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e);
} catch (LocalizedException $e) {
throw new GraphQlInputException(__($e->getMessage()), $e);
}

return [
'cart' => [
'model' => $cart,
],
];
}

/**
* Process cart items
*
* @param Quote $cart
* @param array $items
* @throws GraphQlInputException
* @throws LocalizedException
*/
private function processCartItems(Quote $cart, array $items): void
{
foreach ($items as $item) {
if (!isset($item['cart_item_id']) || empty($item['cart_item_id'])) {
throw new GraphQlInputException(__('Required parameter "cart_item_id" for "cart_items" is missing.'));
}
$itemId = $item['cart_item_id'];

if (!isset($item['quantity'])) {
throw new GraphQlInputException(__('Required parameter "quantity" for "cart_items" is missing.'));
}
$qty = (float)$item['quantity'];

$cartItem = $cart->getItemById($itemId);
if ($cartItem === false) {
throw new GraphQlNoSuchEntityException(
__('Could not find cart item with id: %1.', $item['cart_item_id'])
);
}

if ($qty <= 0.0) {
$this->cartItemRepository->deleteById((int)$cart->getId(), $itemId);
} else {
$cartItem->setQty($qty);
$this->cartItemRepository->save($cartItem);
}
}
}
}
10 changes: 10 additions & 0 deletions app/code/Magento/QuoteGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type Mutation {
addVirtualProductsToCart(input: AddVirtualProductsToCartInput): AddVirtualProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart")
applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart")
removeCouponFromCart(input: RemoveCouponFromCartInput): RemoveCouponFromCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveCouponFromCart")
updateCartItems(input: UpdateCartItemsInput): UpdateCartItemsOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\UpdateCartItems")
removeItemFromCart(input: RemoveItemFromCartInput): RemoveItemFromCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveItemFromCart")
setShippingAddressesOnCart(input: SetShippingAddressesOnCartInput): SetShippingAddressesOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingAddressesOnCart")
setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart")
Expand Down Expand Up @@ -53,6 +54,11 @@ input ApplyCouponToCartInput {
coupon_code: String!
}

input UpdateCartItemsInput {
cart_id: String!
cart_items: [CartItemQuantityInput!]!
}

input RemoveItemFromCartInput {
cart_id: String!
cart_item_id: Int!
Expand Down Expand Up @@ -230,6 +236,10 @@ type AddVirtualProductsToCartOutput {
cart: Cart!
}

type UpdateCartItemsOutput {
cart: Cart!
}

type RemoveItemFromCartOutput {
cart: Cart!
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,20 +75,24 @@ public function testRemoveItemFromCart()

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

$query = $this->prepareMutationQuery('non_existent_masked_id', $itemId);
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}

/**
* @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php
*/
public function testRemoveNotExistentItem()
public function testRemoveNonExistentItem()
{
$quote = $this->quoteFactory->create();
$this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id');
Expand Down Expand Up @@ -183,6 +187,50 @@ public function testRemoveItemFromAnotherCustomerCart()
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}

/**
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @param string $input
* @param string $message
* @dataProvider dataProviderUpdateWithMissedRequiredParameters
*/
public function testUpdateWithMissedItemRequiredParameters(string $input, string $message)
{
$query = <<<QUERY
mutation {
removeItemFromCart(
input: {
{$input}
}
) {
cart {
items {
qty
}
}
}
}
QUERY;
$this->expectExceptionMessage($message);
$this->graphQlQuery($query, [], '', $this->getHeaderMap());
}

/**
* @return array
*/
public function dataProviderUpdateWithMissedRequiredParameters(): array
{
return [
'missed_cart_id' => [
'cart_item_id: 1',
'Required parameter "cart_id" is missing.'
],
'missed_cart_item_id' => [
'cart_id: "test"',
'Required parameter "cart_item_id" is missing.'
],
];
}

/**
* @param string $maskedQuoteId
* @param int $itemId
Expand Down
Loading

0 comments on commit 8d900eb

Please sign in to comment.