diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItem.php b/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItem.php new file mode 100644 index 0000000000000..bc98eb93b55cc --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItem.php @@ -0,0 +1,98 @@ +dataObjectFactory = $dataObjectFactory; + } + + /** + * Update cart item + * + * @param Quote $cart + * @param int $cartItemId + * @param float $qty + * @param null $customizableOptionsData + * @return void + * @throws GraphQlInputException + */ + public function execute(Quote $cart, int $cartItemId, float $qty, array $customizableOptionsData): void + { + $customizableOptions = []; + foreach ($customizableOptionsData as $customizableOption) { + $customizableOptions[$customizableOption['id']] = $customizableOption['value']; + } + + try { + $result = $cart->updateItem( + $cartItemId, + $this->createBuyRequest($qty, $customizableOptions) + ); + } catch (LocalizedException $e) { + throw new GraphQlInputException( + __( + 'Could not update cart item: %message', + ['message' => $e->getMessage()] + ) + ); + } + + if (is_string($result)) { + throw new GraphQlInputException(__( + 'Could not update cart item: %message', + ['message' => $result] + )); + } + + if ($result->getHasError()) { + throw new GraphQlInputException(__( + 'Could not update cart item: %message', + ['message' => $result->getMessage()] + )); + } + } + + /** + * Format GraphQl input data to a shape that buy request has + * + * @param float $qty + * @param array $customOptions + * @return DataObject + */ + private function createBuyRequest(float $qty, array $customOptions): DataObject + { + return $this->dataObjectFactory->create([ + 'data' => [ + 'qty' => $qty, + 'options' => $customOptions, + ], + ]); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php index 78a07506556c0..ed1cb7a9dab50 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -15,14 +15,26 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartItemRepositoryInterface; +use Magento\Quote\Api\CartRepositoryInterface; use Magento\Quote\Model\Quote; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; +use Magento\QuoteGraphQl\Model\Cart\UpdateCartItem; /** * @inheritdoc */ class UpdateCartItems implements ResolverInterface { + /** + * @var CartRepositoryInterface + */ + private $quoteRepository; + + /** + * @var UpdateCartItem + */ + private $updateCartItem; + /** * @var GetCartForUser */ @@ -36,13 +48,19 @@ class UpdateCartItems implements ResolverInterface /** * @param GetCartForUser $getCartForUser * @param CartItemRepositoryInterface $cartItemRepository + * @param UpdateCartItem $updateCartItem + * @param CartRepositoryInterface $quoteRepository */ public function __construct( GetCartForUser $getCartForUser, - CartItemRepositoryInterface $cartItemRepository + CartItemRepositoryInterface $cartItemRepository, + UpdateCartItem $updateCartItem, + CartRepositoryInterface $quoteRepository ) { $this->getCartForUser = $getCartForUser; $this->cartItemRepository = $cartItemRepository; + $this->updateCartItem = $updateCartItem; + $this->quoteRepository = $quoteRepository; } /** @@ -93,26 +111,47 @@ private function processCartItems(Quote $cart, array $items): void 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']; + $itemId = (int)$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); + $customizableOptions = $item['customizable_options'] ?? null; + + if ($customizableOptions === null) { // Update only item's qty + $this->updateItemQty($itemId, $cart, $qty); + } else { // Update customizable options (and QTY if changed) + $this->updateCartItem->execute($cart, $itemId, $qty, $customizableOptions); + $this->quoteRepository->save($cart); + } } } } + + /** + * Updates item qty for the specified cart + * + * @param int $itemId + * @param Quote $cart + * @param float $qty + * @throws GraphQlNoSuchEntityException + * @throws NoSuchEntityException + * @throws GraphQlNoSuchEntityException + */ + private function updateItemQty(int $itemId, Quote $cart, float $qty) + { + $cartItem = $cart->getItemById($itemId); + if ($cartItem === false) { + throw new GraphQlNoSuchEntityException( + __('Could not find cart item with id: %1.', $itemId) + ); + } + $cartItem->setQty($qty); + $this->cartItemRepository->save($cartItem); + } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index a9784e97c8952..afbb8ceb03b39 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -67,7 +67,8 @@ input UpdateCartItemsInput { input CartItemQuantityInput { cart_item_id: Int! - quantity: Float! + quantity: Float + customizable_options: [CustomizableOptionInput!] } input RemoveItemFromCartInput {