From e5c5f41eb2495e5287fb338d7a7a805574e8c012 Mon Sep 17 00:00:00 2001 From: Valerii Naida Date: Thu, 28 Feb 2019 16:50:41 -0600 Subject: [PATCH] GraphQL-37: [Cart Operations] Manage Cart Items -- Refactoring --- .../Model/Customer/CheckCustomerAccount.php | 12 +- .../Model/Cart/AssignBillingAddressToCart.php | 59 ++++ .../Cart/AssignShippingAddressToCart.php | 57 ++++ .../Model/Cart/ExtractDataFromCart.php | 68 ----- .../Model/Cart/GetCustomerAddress.php | 9 +- .../Model/Cart/QuoteAddressFactory.php | 67 +++++ .../Model/Cart/SetBillingAddressOnCart.php | 53 ++-- .../Model/Cart/SetShippingAddressOnCart.php | 44 ++- .../SetShippingAddressesOnCartInterface.php | 6 + .../Resolver/AddSimpleProductsToCart.php | 44 +-- .../Model/Resolver/AppliedCoupon.php | 34 +++ .../Model/Resolver/ApplyCouponToCart.php | 7 +- .../QuoteGraphQl/Model/Resolver/Cart.php | 17 +- .../QuoteGraphQl/Model/Resolver/CartItems.php | 48 +++ .../Model/Resolver/RemoveCouponFromCart.php | 7 +- ...mCartOutput.php => RemoveItemFromCart.php} | 41 +-- .../Resolver/SetBillingAddressOnCart.php | 26 +- .../Model/Resolver/SetPaymentMethodOnCart.php | 32 +- .../Resolver/SetShippingAddressesOnCart.php | 40 +-- .../Resolver/SetShippingMethodsOnCart.php | 7 +- .../Magento/QuoteGraphQl/etc/schema.graphqls | 21 +- .../Quote/AddSimpleProductToCartTest.php | 6 +- .../Magento/GraphQl/Quote/CouponTest.php | 4 +- .../GraphQl/Quote/Customer/GetCartTest.php | 3 - .../Quote/Customer/RemoveItemFromCartTest.php | 222 ++++++++++++++ .../Customer/SetPaymentMethodOnCartTest.php | 15 +- .../Quote/GetAvailableShippingMethodsTest.php | 2 - .../GraphQl/Quote/Guest/GetCartTest.php | 3 - .../Quote/Guest/RemoveItemFromCartTest.php | 166 ++++++++++ .../Guest/SetPaymentMethodOnCartTest.php | 5 - .../GraphQl/Quote/RemoveItemFromCartTest.php | 283 ------------------ 31 files changed, 817 insertions(+), 591 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php rename app/code/Magento/QuoteGraphQl/Model/Resolver/{RemoveItemFromCartOutput.php => RemoveItemFromCart.php} (69%) create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/RemoveItemFromCartTest.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/RemoveItemFromCartTest.php delete mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/RemoveItemFromCartTest.php diff --git a/app/code/Magento/CustomerGraphQl/Model/Customer/CheckCustomerAccount.php b/app/code/Magento/CustomerGraphQl/Model/Customer/CheckCustomerAccount.php index 030fc47d19e8..b2f524c877fd 100644 --- a/app/code/Magento/CustomerGraphQl/Model/Customer/CheckCustomerAccount.php +++ b/app/code/Magento/CustomerGraphQl/Model/Customer/CheckCustomerAccount.php @@ -11,9 +11,11 @@ use Magento\Customer\Api\AccountManagementInterface; use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Model\AuthenticationInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; /** @@ -58,6 +60,7 @@ public function __construct( * @param int|null $customerType * @return void * @throws GraphQlAuthorizationException + * @throws GraphQlInputException * @throws GraphQlNoSuchEntityException * @throws GraphQlAuthenticationException */ @@ -74,13 +77,20 @@ public function execute(?int $customerId, ?int $customerType): void __('Customer with id "%customer_id" does not exist.', ['customer_id' => $customerId]), $e ); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); } if (true === $this->authentication->isLocked($customerId)) { throw new GraphQlAuthenticationException(__('The account is locked.')); } - $confirmationStatus = $this->accountManagement->getConfirmationStatus($customerId); + try { + $confirmationStatus = $this->accountManagement->getConfirmationStatus($customerId); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); + } + if ($confirmationStatus === AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED) { throw new GraphQlAuthenticationException(__("This account isn't confirmed. Verify and try again.")); } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php new file mode 100644 index 000000000000..370501e9c6e8 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php @@ -0,0 +1,59 @@ +billingAddressManagement = $billingAddressManagement; + } + + /** + * Assign billing address to cart + * + * @param CartInterface $cart + * @param QuoteAddress $billingAddress + * @param bool $useForShipping + * @throws GraphQlInputException + * @throws GraphQlNoSuchEntityException + */ + public function execute( + CartInterface $cart, + QuoteAddress $billingAddress, + bool $useForShipping + ): void { + try { + $this->billingAddressManagement->assign($cart->getId(), $billingAddress, $useForShipping); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage())); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); + } + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php new file mode 100644 index 000000000000..47f90edb04be --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php @@ -0,0 +1,57 @@ +shippingAddressManagement = $shippingAddressManagement; + } + + /** + * Assign shipping address to cart + * + * @param CartInterface $cart + * @param QuoteAddress $shippingAddress + * @throws GraphQlInputException + * @throws GraphQlNoSuchEntityException + */ + public function execute( + CartInterface $cart, + QuoteAddress $shippingAddress + ): void { + try { + $this->shippingAddressManagement->assign($cart->getId(), $shippingAddress); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage())); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); + } + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php deleted file mode 100644 index 62ffdbd4b194..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php +++ /dev/null @@ -1,68 +0,0 @@ -quoteIdToMaskedQuoteId = $quoteIdToMaskedQuoteId; - } - - /** - * Extract data from cart - * - * @param Quote $cart - * @return array - * @throws NoSuchEntityException - */ - public function execute(Quote $cart): array - { - $items = []; - - /** - * @var QuoteItem $cartItem - */ - foreach ($cart->getAllItems() as $cartItem) { - $productData = $cartItem->getProduct()->getData(); - $productData['model'] = $cartItem->getProduct(); - - $items[] = [ - 'id' => $cartItem->getItemId(), - 'qty' => $cartItem->getQty(), - 'product' => $productData, - 'model' => $cartItem, - ]; - } - - $appliedCoupon = $cart->getCouponCode(); - - return [ - 'cart_id' => $this->quoteIdToMaskedQuoteId->execute((int)$cart->getId()), - 'items' => $items, - 'applied_coupon' => $appliedCoupon ? ['code' => $appliedCoupon] : null - ]; - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php index d3de86702b96..93c888a1d0bd 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php @@ -12,6 +12,7 @@ use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; /** @@ -33,14 +34,14 @@ public function __construct(AddressRepositoryInterface $addressRepository) } /** - * Get customer address. Throws exception if customer is not owner of address + * Get customer address * * @param int $addressId * @param int $customerId * @return AddressInterface - * @throws GraphQlAuthorizationException + * @throws GraphQlInputException * @throws GraphQlNoSuchEntityException - * @throws LocalizedException + * @throws GraphQlAuthorizationException */ public function execute(int $addressId, int $customerId): AddressInterface { @@ -50,6 +51,8 @@ public function execute(int $addressId, int $customerId): AddressInterface throw new GraphQlNoSuchEntityException( __('Could not find a address with ID "%address_id"', ['address_id' => $addressId]) ); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); } if ((int)$customerAddress->getCustomerId() !== $customerId) { diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php new file mode 100644 index 000000000000..7dfea0836e8d --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -0,0 +1,67 @@ +quoteAddressFactory = $quoteAddressFactory; + } + + /** + * Create QuoteAddress based on input data + * + * @param array $addressInput + * @return QuoteAddress + */ + public function createBasedOnInputData(array $addressInput): QuoteAddress + { + $addressInput['country_id'] = $addressInput['country_code'] ?? ''; + + $quoteAddress = $this->quoteAddressFactory->create(); + $quoteAddress->addData($addressInput); + return $quoteAddress; + } + + /** + * Create QuoteAddress based on CustomerAddress + * + * @param CustomerAddress $customerAddress + * @return QuoteAddress + * @throws GraphQlInputException + */ + public function createBasedOnCustomerAddress(CustomerAddress $customerAddress): QuoteAddress + { + $quoteAddress = $this->quoteAddressFactory->create(); + try { + $quoteAddress->importCustomerAddressData($customerAddress); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); + } + return $quoteAddress; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 02aec5b6fbaf..04b7bfcfe0e6 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -8,12 +8,12 @@ namespace Magento\QuoteGraphQl\Model\Cart; use Magento\CustomerGraphQl\Model\Customer\CheckCustomerAccount; +use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Model\Quote\Address; -use Magento\Quote\Api\BillingAddressManagementInterface; -use Magento\Customer\Api\AddressRepositoryInterface; /** * Set billing address for a specified shopping cart @@ -21,14 +21,9 @@ class SetBillingAddressOnCart { /** - * @var BillingAddressManagementInterface + * @var QuoteAddressFactory */ - private $billingAddressManagement; - - /** - * @var Address - */ - private $addressModel; + private $quoteAddressFactory; /** * @var CheckCustomerAccount @@ -41,24 +36,26 @@ class SetBillingAddressOnCart private $getCustomerAddress; /** - * @param BillingAddressManagementInterface $billingAddressManagement - * @param AddressRepositoryInterface $addressRepository - * @param Address $addressModel + * @var AssignBillingAddressToCart + */ + private $assignBillingAddressToCart; + + /** + * @param QuoteAddressFactory $quoteAddressFactory * @param CheckCustomerAccount $checkCustomerAccount * @param GetCustomerAddress $getCustomerAddress + * @param AssignBillingAddressToCart $assignBillingAddressToCart */ public function __construct( - BillingAddressManagementInterface $billingAddressManagement, - AddressRepositoryInterface $addressRepository, - Address $addressModel, + QuoteAddressFactory $quoteAddressFactory, CheckCustomerAccount $checkCustomerAccount, - GetCustomerAddress $getCustomerAddress + GetCustomerAddress $getCustomerAddress, + AssignBillingAddressToCart $assignBillingAddressToCart ) { - $this->billingAddressManagement = $billingAddressManagement; - $this->addressRepository = $addressRepository; - $this->addressModel = $addressModel; + $this->quoteAddressFactory = $quoteAddressFactory; $this->checkCustomerAccount = $checkCustomerAccount; $this->getCustomerAddress = $getCustomerAddress; + $this->assignBillingAddressToCart = $assignBillingAddressToCart; } /** @@ -69,38 +66,44 @@ public function __construct( * @param array $billingAddress * @return void * @throws GraphQlInputException + * @throws GraphQlAuthenticationException + * @throws GraphQlAuthorizationException + * @throws GraphQlNoSuchEntityException */ public function execute(ContextInterface $context, CartInterface $cart, array $billingAddress): void { $customerAddressId = $billingAddress['customer_address_id'] ?? null; $addressInput = $billingAddress['address'] ?? null; - $useForShipping = $billingAddress['use_for_shipping'] ?? false; + $useForShipping = isset($billingAddress['use_for_shipping']) + ? (bool)$billingAddress['use_for_shipping'] : false; if (null === $customerAddressId && null === $addressInput) { throw new GraphQlInputException( __('The billing address must contain either "customer_address_id" or "address".') ); } + if ($customerAddressId && $addressInput) { throw new GraphQlInputException( __('The billing address cannot contain "customer_address_id" and "address" at the same time.') ); } + $addresses = $cart->getAllShippingAddresses(); if ($useForShipping && count($addresses) > 1) { throw new GraphQlInputException( __('Using the "use_for_shipping" option with multishipping is not possible.') ); } + if (null === $customerAddressId) { - $addressInput['country_id'] = $addressInput['country_code'] ?? ''; - $billingAddress = $this->addressModel->addData($addressInput); + $billingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInput); } else { $this->checkCustomerAccount->execute($context->getUserId(), $context->getUserType()); $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$context->getUserId()); - $billingAddress = $this->addressModel->importCustomerAddressData($customerAddress); + $billingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress($customerAddress); } - $this->billingAddressManagement->assign($cart->getId(), $billingAddress, $useForShipping); + $this->assignBillingAddressToCart->execute($cart, $billingAddress, $useForShipping); } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php index fc8eff4cfc13..1a1442485349 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php @@ -11,8 +11,6 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Model\Quote\Address; -use Magento\Quote\Model\ShippingAddressManagementInterface; /** * Set single shipping address for a specified shopping cart @@ -20,14 +18,9 @@ class SetShippingAddressOnCart implements SetShippingAddressesOnCartInterface { /** - * @var ShippingAddressManagementInterface + * @var QuoteAddressFactory */ - private $shippingAddressManagement; - - /** - * @var Address - */ - private $addressModel; + private $quoteAddressFactory; /** * @var CheckCustomerAccount @@ -40,30 +33,30 @@ class SetShippingAddressOnCart implements SetShippingAddressesOnCartInterface private $getCustomerAddress; /** - * @param ShippingAddressManagementInterface $shippingAddressManagement - * @param Address $addressModel + * @var AssignShippingAddressToCart + */ + private $assignShippingAddressToCart; + + /** + * @param QuoteAddressFactory $quoteAddressFactory * @param CheckCustomerAccount $checkCustomerAccount * @param GetCustomerAddress $getCustomerAddress + * @param AssignShippingAddressToCart $assignShippingAddressToCart */ public function __construct( - ShippingAddressManagementInterface $shippingAddressManagement, - Address $addressModel, + QuoteAddressFactory $quoteAddressFactory, CheckCustomerAccount $checkCustomerAccount, - GetCustomerAddress $getCustomerAddress + GetCustomerAddress $getCustomerAddress, + AssignShippingAddressToCart $assignShippingAddressToCart ) { - $this->shippingAddressManagement = $shippingAddressManagement; - $this->addressModel = $addressModel; + $this->quoteAddressFactory = $quoteAddressFactory; $this->checkCustomerAccount = $checkCustomerAccount; $this->getCustomerAddress = $getCustomerAddress; + $this->assignShippingAddressToCart = $assignShippingAddressToCart; } /** * @inheritdoc - * - * @param ContextInterface $context - * @param CartInterface $cart - * @param array $shippingAddresses - * @throws GraphQlInputException */ public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddresses): void { @@ -81,20 +74,21 @@ public function execute(ContextInterface $context, CartInterface $cart, array $s __('The shipping address must contain either "customer_address_id" or "address".') ); } + if ($customerAddressId && $addressInput) { throw new GraphQlInputException( __('The shipping address cannot contain "customer_address_id" and "address" at the same time.') ); } + if (null === $customerAddressId) { - $addressInput['country_id'] = $addressInput['country_code'] ?? ''; - $shippingAddress = $this->addressModel->addData($addressInput); + $shippingAddress = $this->quoteAddressFactory->createBasedOnInputData($addressInput); } else { $this->checkCustomerAccount->execute($context->getUserId(), $context->getUserType()); $customerAddress = $this->getCustomerAddress->execute((int)$customerAddressId, (int)$context->getUserId()); - $shippingAddress = $this->addressModel->importCustomerAddressData($customerAddress); + $shippingAddress = $this->quoteAddressFactory->createBasedOnCustomerAddress($customerAddress); } - $this->shippingAddressManagement->assign($cart->getId(), $shippingAddress); + $this->assignShippingAddressToCart->execute($cart, $shippingAddress); } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php index c5da3db75add..81da47933e81 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php @@ -7,7 +7,10 @@ namespace Magento\QuoteGraphQl\Model\Cart; +use Magento\Framework\GraphQl\Exception\GraphQlAuthenticationException; +use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; use Magento\Framework\GraphQl\Query\Resolver\ContextInterface; use Magento\Quote\Api\Data\CartInterface; @@ -27,6 +30,9 @@ interface SetShippingAddressesOnCartInterface * @param array $shippingAddresses * @return void * @throws GraphQlInputException + * @throws GraphQlAuthorizationException + * @throws GraphQlAuthenticationException + * @throws GraphQlNoSuchEntityException */ public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddresses): void; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php index f4335b262c85..82ffd0970d67 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -11,9 +11,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\Stdlib\ArrayManager; use Magento\QuoteGraphQl\Model\Cart\AddProductsToCart; -use Magento\QuoteGraphQl\Model\Cart\ExtractDataFromCart; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; /** @@ -22,11 +20,6 @@ */ class AddSimpleProductsToCart implements ResolverInterface { - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var GetCartForUser */ @@ -38,26 +31,15 @@ class AddSimpleProductsToCart implements ResolverInterface private $addProductsToCart; /** - * @var ExtractDataFromCart - */ - private $extractDataFromCart; - - /** - * @param ArrayManager $arrayManager * @param GetCartForUser $getCartForUser * @param AddProductsToCart $addProductsToCart - * @param ExtractDataFromCart $extractDataFromCart */ public function __construct( - ArrayManager $arrayManager, GetCartForUser $getCartForUser, - AddProductsToCart $addProductsToCart, - ExtractDataFromCart $extractDataFromCart + AddProductsToCart $addProductsToCart ) { - $this->arrayManager = $arrayManager; $this->getCartForUser = $getCartForUser; $this->addProductsToCart = $addProductsToCart; - $this->extractDataFromCart = $extractDataFromCart; } /** @@ -65,25 +47,25 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $cartHash = $this->arrayManager->get('input/cart_id', $args); - $cartItems = $this->arrayManager->get('input/cartItems', $args); - - if (!isset($cartHash)) { - throw new GraphQlInputException(__('Missing key "cart_id" in cart data')); + 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($cartItems) || !is_array($cartItems) || empty($cartItems)) { - throw new GraphQlInputException(__('Missing key "cartItems" in cart data')); + if (!isset($args['input']['cartItems']) || empty($args['input']['cartItems']) + || !is_array($args['input']['cartItems']) + ) { + throw new GraphQlInputException(__('Required parameter "cartItems" is missing')); } + $cartItems = $args['input']['cartItems']; - $currentUserId = $context->getUserId(); - $cart = $this->getCartForUser->execute((string)$cartHash, $currentUserId); - + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $this->addProductsToCart->execute($cart, $cartItems); - $cartData = $this->extractDataFromCart->execute($cart); return [ - 'cart' => $cartData, + 'cart' => [ + 'model' => $cart, + ], ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php new file mode 100644 index 000000000000..ca69b763929b --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AppliedCoupon.php @@ -0,0 +1,34 @@ +getCouponCode(); + + return $appliedCoupon ? ['code' => $appliedCoupon] : null; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php index ec59416d4937..a334e7482ca4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php @@ -80,9 +80,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new LocalizedException(__($exception->getMessage())); } - $data['cart']['applied_coupon'] = [ - 'code' => $couponCode, + return [ + 'cart' => [ + 'model' => $cart, + ], ]; - return $data; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php index 1849ba080386..2df31841366a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart.php @@ -12,18 +12,12 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; -use Magento\QuoteGraphQl\Model\Cart\ExtractDataFromCart; /** * @inheritdoc */ class Cart implements ResolverInterface { - /** - * @var ExtractDataFromCart - */ - private $extractDataFromCart; - /** * @var GetCartForUser */ @@ -31,14 +25,11 @@ class Cart implements ResolverInterface /** * @param GetCartForUser $getCartForUser - * @param ExtractDataFromCart $extractDataFromCart */ public function __construct( - GetCartForUser $getCartForUser, - ExtractDataFromCart $extractDataFromCart + GetCartForUser $getCartForUser ) { $this->getCartForUser = $getCartForUser; - $this->extractDataFromCart = $extractDataFromCart; } /** @@ -54,8 +45,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $currentUserId = $context->getUserId(); $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId); - $data = $this->extractDataFromCart->execute($cart); - $data['model'] = $cart; - return $data; + return [ + 'model' => $cart, + ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php new file mode 100644 index 000000000000..da6619d15a48 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItems.php @@ -0,0 +1,48 @@ +getAllItems() as $cartItem) { + /** + * @var QuoteItem $cartItem + */ + $productData = $cartItem->getProduct()->getData(); + $productData['model'] = $cartItem->getProduct(); + + $itemsData[] = [ + 'id' => $cartItem->getItemId(), + 'qty' => $cartItem->getQty(), + 'product' => $productData, + 'model' => $cartItem, + ]; + } + return $itemsData; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php index c21d869ddac7..730c927c32a0 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php @@ -67,9 +67,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value throw new LocalizedException(__($exception->getMessage())); } - $data['cart']['applied_coupon'] = [ - 'code' => '', + return [ + 'cart' => [ + 'model' => $cart, + ], ]; - return $data; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCartOutput.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php similarity index 69% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCartOutput.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php index 658f670fd682..1838f17369ff 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCartOutput.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php @@ -7,6 +7,7 @@ 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; @@ -14,13 +15,12 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\GuestCartItemRepositoryInterface; -use Magento\Quote\Api\GuestCartRepositoryInterface; -use Magento\QuoteGraphQl\Model\Cart\ExtractDataFromCart; +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; /** * @inheritdoc */ -class RemoveItemFromCartOutput implements ResolverInterface +class RemoveItemFromCart implements ResolverInterface { /** * @var GuestCartItemRepositoryInterface @@ -28,46 +28,51 @@ class RemoveItemFromCartOutput implements ResolverInterface private $guestCartItemRepository; /** - * @var GuestCartRepositoryInterface + * @var GetCartForUser */ - private $guestCartRepository; + private $getCartForUser; /** - * @var ExtractDataFromCart + * @param GuestCartItemRepositoryInterface $guestCartItemRepository + * @param GetCartForUser $getCartForUser */ - private $extractDataFromCart; - public function __construct( GuestCartItemRepositoryInterface $guestCartItemRepository, - GuestCartRepositoryInterface $guestCartRepository, - ExtractDataFromCart $extractDataFromCart + GetCartForUser $getCartForUser ) { $this->guestCartItemRepository = $guestCartItemRepository; - $this->guestCartRepository = $guestCartRepository; - $this->extractDataFromCart = $extractDataFromCart; + $this->getCartForUser = $getCartForUser; } + /** + * @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')); } + $maskedCartId = $args['input']['cart_id']; + if (!isset($args['input']['cart_item_id'])) { throw new GraphQlInputException(__('Required parameter "cart_item_id" is missing')); } - $maskedCartId = $args['input']['cart_id']; $itemId = $args['input']['cart_item_id']; + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + try { $this->guestCartItemRepository->deleteById($maskedCartId, $itemId); } catch (NoSuchEntityException $e) { throw new GraphQlNoSuchEntityException(__($e->getMessage())); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage())); } - $cart = $this->guestCartRepository->get($maskedCartId); - - $cartData = $this->extractDataFromCart->execute($cart); - - return ['cart' => array_merge(['cart_id' => $maskedCartId], $cartData)]; + return [ + 'cart' => [ + 'model' => $cart, + ], + ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php index 01a35f4b4152..f7c9a4b0697b 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetBillingAddressOnCart.php @@ -11,13 +11,10 @@ use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\Stdlib\ArrayManager; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; use Magento\QuoteGraphQl\Model\Cart\SetBillingAddressOnCart as SetBillingAddressOnCartModel; /** - * Class SetBillingAddressOnCart - * * Mutation resolver for setting billing address for shopping cart */ class SetBillingAddressOnCart implements ResolverInterface @@ -27,11 +24,6 @@ class SetBillingAddressOnCart implements ResolverInterface */ private $getCartForUser; - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var SetBillingAddressOnCartModel */ @@ -39,16 +31,13 @@ class SetBillingAddressOnCart implements ResolverInterface /** * @param GetCartForUser $getCartForUser - * @param ArrayManager $arrayManager * @param SetBillingAddressOnCartModel $setBillingAddressOnCart */ public function __construct( GetCartForUser $getCartForUser, - ArrayManager $arrayManager, SetBillingAddressOnCartModel $setBillingAddressOnCart ) { $this->getCartForUser = $getCartForUser; - $this->arrayManager = $arrayManager; $this->setBillingAddressOnCart = $setBillingAddressOnCart; } @@ -57,26 +46,23 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $billingAddress = $this->arrayManager->get('input/billing_address', $args); - $maskedCartId = $this->arrayManager->get('input/cart_id', $args); - - if (!$maskedCartId) { + if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) { throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); } - if (!$billingAddress) { + $maskedCartId = $args['input']['cart_id']; + + if (!isset($args['input']['billing_address']) || empty($args['input']['billing_address'])) { throw new GraphQlInputException(__('Required parameter "billing_address" is missing')); } + $billingAddress = $args['input']['billing_address']; - $maskedCartId = $args['input']['cart_id']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); - $this->setBillingAddressOnCart->execute($context, $cart, $billingAddress); return [ 'cart' => [ - 'cart_id' => $maskedCartId, 'model' => $cart, - ] + ], ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index 78a841a9cb61..ffd1bf37f477 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -8,11 +8,12 @@ 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\Framework\Stdlib\ArrayManager; use Magento\Quote\Api\Data\PaymentInterface; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; use Magento\Quote\Api\Data\PaymentInterfaceFactory; @@ -28,11 +29,6 @@ class SetPaymentMethodOnCart implements ResolverInterface */ private $getCartForUser; - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var PaymentMethodManagementInterface */ @@ -45,18 +41,15 @@ class SetPaymentMethodOnCart implements ResolverInterface /** * @param GetCartForUser $getCartForUser - * @param ArrayManager $arrayManager * @param PaymentMethodManagementInterface $paymentMethodManagement * @param PaymentInterfaceFactory $paymentFactory */ public function __construct( GetCartForUser $getCartForUser, - ArrayManager $arrayManager, PaymentMethodManagementInterface $paymentMethodManagement, PaymentInterfaceFactory $paymentFactory ) { $this->getCartForUser = $getCartForUser; - $this->arrayManager = $arrayManager; $this->paymentMethodManagement = $paymentMethodManagement; $this->paymentFactory = $paymentFactory; } @@ -66,22 +59,20 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $maskedCartId = (string)$this->arrayManager->get('input/cart_id', $args); - if (!$maskedCartId) { + 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']; - $paymentMethod = $this->arrayManager->get('input/payment_method', $args); - if (!$paymentMethod) { + if (!isset($args['input']['payment_method']['code']) || empty($args['input']['payment_method']['code'])) { throw new GraphQlInputException(__('Required parameter "payment_method" is missing')); } + $paymentMethodCode = $args['input']['payment_method']['code']; - $paymentMethodCode = (string) $this->arrayManager->get('input/payment_method/code', $args); - if (!$paymentMethodCode) { - throw new GraphQlInputException(__('Required parameter payment "code" is missing')); - } - - $poNumber = $this->arrayManager->get('input/payment_method/purchase_order_number', $args); + $poNumber = isset($args['input']['payment_method']['purchase_order_number']) + && empty($args['input']['payment_method']['purchase_order_number']) + ? $args['input']['payment_method']['purchase_order_number'] + : null; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); $payment = $this->paymentFactory->create([ @@ -94,13 +85,14 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value try { $this->paymentMethodManagement->set($cart->getId(), $payment); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage())); } catch (LocalizedException $e) { throw new GraphQlInputException(__($e->getMessage())); } return [ 'cart' => [ - 'cart_id' => $maskedCartId, 'model' => $cart, ], ]; diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php index a55e2971e0ef..c3e1d371fe6a 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingAddressesOnCart.php @@ -7,58 +7,37 @@ namespace Magento\QuoteGraphQl\Model\Resolver; -use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\Stdlib\ArrayManager; -use Magento\Quote\Model\ShippingAddressManagementInterface; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; use Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCartInterface; /** - * Class SetShippingAddressesOnCart - * * Mutation resolver for setting shipping addresses for shopping cart */ class SetShippingAddressesOnCart implements ResolverInterface { - /** - * @var ShippingAddressManagementInterface - */ - private $shippingAddressManagement; - /** * @var GetCartForUser */ private $getCartForUser; - /** - * @var ArrayManager - */ - private $arrayManager; - /** * @var SetShippingAddressesOnCartInterface */ private $setShippingAddressesOnCart; /** - * @param ShippingAddressManagementInterface $shippingAddressManagement * @param GetCartForUser $getCartForUser - * @param ArrayManager $arrayManager * @param SetShippingAddressesOnCartInterface $setShippingAddressesOnCart */ public function __construct( - ShippingAddressManagementInterface $shippingAddressManagement, GetCartForUser $getCartForUser, - ArrayManager $arrayManager, SetShippingAddressesOnCartInterface $setShippingAddressesOnCart ) { - $this->shippingAddressManagement = $shippingAddressManagement; $this->getCartForUser = $getCartForUser; - $this->arrayManager = $arrayManager; $this->setShippingAddressesOnCart = $setShippingAddressesOnCart; } @@ -67,30 +46,23 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $shippingAddresses = $this->arrayManager->get('input/shipping_addresses', $args); - $maskedCartId = (string)$this->arrayManager->get('input/cart_id', $args); - - if (!$maskedCartId) { + 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 (!$shippingAddresses) { + if (!isset($args['input']['shipping_addresses']) || empty($args['input']['shipping_addresses'])) { throw new GraphQlInputException(__('Required parameter "shipping_addresses" is missing')); } + $shippingAddresses = $args['input']['shipping_addresses']; $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); - - try { - $this->setShippingAddressesOnCart->execute($context, $cart, $shippingAddresses); - } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); - } + $this->setShippingAddressesOnCart->execute($context, $cart, $shippingAddresses); return [ 'cart' => [ - 'cart_id' => $maskedCartId, 'model' => $cart, - ] + ], ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php index 67947e928796..3950434301a8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php @@ -16,8 +16,6 @@ use Magento\QuoteGraphQl\Model\Cart\SetShippingMethodOnCart; /** - * Class SetShippingMethodsOnCart - * * Mutation resolver for setting shipping methods for shopping cart */ class SetShippingMethodsOnCart implements ResolverInterface @@ -91,9 +89,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return [ 'cart' => [ - 'cart_id' => $maskedCartId, - 'model' => $cart - ] + 'model' => $cart, + ], ]; } } diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 93d5842a4b14..e4ced2351572 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -11,7 +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") - removeItemFromCart(input: RemoveItemFromCartInput): RemoveItemFromCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveItemFromCartOutput") + 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") setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart") @@ -53,6 +53,11 @@ input ApplyCouponToCartInput { coupon_code: String! } +input RemoveItemFromCartInput { + cart_id: String! + cart_item_id: Int! +} + input SetShippingAddressesOnCartInput { cart_id: String! shipping_addresses: [ShippingAddressInput!]! @@ -139,12 +144,11 @@ type ApplyCouponToCartOutput { } type Cart { - cart_id: String - items: [CartItemInterface] - applied_coupon: AppliedCoupon + items: [CartItemInterface] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CartItems") + applied_coupon: AppliedCoupon @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\AppliedCoupon") shipping_addresses: [CartAddress]! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddresses") billing_address: CartAddress! @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\BillingAddress") - available_payment_methods : [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") + available_payment_methods: [AvailablePaymentMethod] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AvailablePaymentMethods") @doc(description: "Available payment methods") selected_payment_method: SelectedPaymentMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SelectedPaymentMethod") } @@ -168,7 +172,7 @@ type CartAddress { } type CartItemQuantity { - cart_item_id: String! + cart_item_id: Int! quantity: Float! } @@ -237,11 +241,6 @@ type AddVirtualProductsToCartOutput { cart: Cart! } -input RemoveItemFromCartInput { - cart_id: String! - cart_item_id: String! -} - type RemoveItemFromCartOutput { cart: Cart! } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php index 4cbc614e1b8d..d5bdb942e9b2 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/AddSimpleProductToCartTest.php @@ -63,7 +63,7 @@ public function testAddProductIfQuantityIsNotAvailable() mutation { addSimpleProductsToCart( input: { - cart_id: "{$maskedQuoteId}", + cart_id: "{$maskedQuoteId}" cartItems: [ { data: { @@ -75,7 +75,9 @@ public function testAddProductIfQuantityIsNotAvailable() } ) { cart { - cart_id + items { + qty + } } } } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php index 1f8ad06a9f8e..54fdc3ac0f36 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/CouponTest.php @@ -58,7 +58,7 @@ public function testApplyCouponToGuestCartWithItems() $query = $this->prepareAddCouponRequestQuery($maskedQuoteId, $couponCode); $response = $this->graphQlQuery($query); - self::assertArrayHasKey("applyCouponToCart", $response); + self::assertArrayHasKey('applyCouponToCart', $response); self::assertEquals($couponCode, $response['applyCouponToCart']['cart']['applied_coupon']['code']); } @@ -154,7 +154,7 @@ public function testRemoveCoupon() $response = $this->graphQlQuery($query); self::assertArrayHasKey('removeCouponFromCart', $response); - self::assertSame('', $response['removeCouponFromCart']['cart']['applied_coupon']['code']); + self::assertNull($response['removeCouponFromCart']['cart']['applied_coupon']['code']); } /** diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php index 8c1fcce7fb55..85a3fc8620c6 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/GetCartTest.php @@ -59,8 +59,6 @@ public function testGetCart() $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); self::assertArrayHasKey('cart', $response); - self::assertEquals($maskedQuoteId, $response['cart']['cart_id']); - self::assertArrayHasKey('items', $response['cart']); self::assertCount(2, $response['cart']['items']); @@ -126,7 +124,6 @@ private function getCartQuery( return <<quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + $this->productRepository = $objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + */ + public function testRemoveItemFromCart() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); + + $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); + $response = $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + + $this->assertArrayHasKey('removeItemFromCart', $response); + $this->assertArrayHasKey('cart', $response['removeItemFromCart']); + $this->assertCount(0, $response['removeItemFromCart']['cart']['items']); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/customer.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); + + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + */ + public function testRemoveNotExistentItem() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_1', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $notExistentItemId = 999; + + $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); + + $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testRemoveItemIfItemIsNotBelongToCart() + { + $firstQuote = $this->quoteFactory->create(); + $this->quoteResource->load($firstQuote, 'test_order_1', 'reserved_order_id'); + $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId()); + + $secondQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $secondQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + $secondQuote->setCustomerId(1); + $this->quoteResource->save($secondQuote); + $secondQuoteItemId = (int)$secondQuote + ->getItemByProduct($this->productRepository->get('virtual-product')) + ->getId(); + + $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); + + $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testRemoveItemFromGuestCart() + { + $guestQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $guestQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + $guestQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$guestQuote->getId()); + $guestQuoteItemId = (int)$guestQuote + ->getItemByProduct($this->productRepository->get('virtual-product')) + ->getId(); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$guestQuoteMaskedId\"" + ); + + $query = $this->prepareMutationQuery($guestQuoteMaskedId, $guestQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @magentoApiDataFixture Magento/Customer/_files/three_customers.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testRemoveItemFromAnotherCustomerCart() + { + $anotherCustomerQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $anotherCustomerQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + $anotherCustomerQuote->setCustomerId(2); + $this->quoteResource->save($anotherCustomerQuote); + + $anotherCustomerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$anotherCustomerQuote->getId()); + $anotherCustomerQuoteItemId = (int)$anotherCustomerQuote + ->getItemByProduct($this->productRepository->get('virtual-product')) + ->getId(); + + $this->expectExceptionMessage( + "The current user cannot perform operations on cart \"$anotherCustomerQuoteMaskedId\"" + ); + + $query = $this->prepareMutationQuery($anotherCustomerQuoteMaskedId, $anotherCustomerQuoteItemId); + $this->graphQlQuery($query, [], '', $this->getHeaderMap()); + } + + /** + * @param string $maskedQuoteId + * @param int $itemId + * @return string + */ + private function prepareMutationQuery(string $maskedQuoteId, int $itemId): string + { + return <<customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php index 8856b2ab44c2..315cbc86b2de 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetPaymentMethodOnCartTest.php @@ -65,7 +65,6 @@ public function testSetPaymentWithVirtualProduct() self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); - self::assertEquals($maskedQuoteId, $response['setPaymentMethodOnCart']['cart']['cart_id']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } @@ -83,7 +82,6 @@ public function testSetPaymentWithSimpleProduct() self::assertArrayHasKey('setPaymentMethodOnCart', $response); self::assertArrayHasKey('cart', $response['setPaymentMethodOnCart']); - self::assertEquals($maskedQuoteId, $response['setPaymentMethodOnCart']['cart']['cart_id']); self::assertArrayHasKey('selected_payment_method', $response['setPaymentMethodOnCart']['cart']); self::assertEquals($methodCode, $response['setPaymentMethodOnCart']['cart']['selected_payment_method']['code']); } @@ -154,8 +152,6 @@ public function testSetPaymentMethodIfCustomerIsNotOwnerOfCart() } /** - * Generates query for setting the specified shipping method on cart - * * @param string $maskedQuoteId * @param string $methodCode * @return string @@ -166,16 +162,13 @@ private function prepareMutationQuery( ) : string { return <<getCustomerAuthHeaders('customer@example.com', 'password') ); self::assertArrayHasKey('cart', $response); - self::assertEquals($maskedQuoteId, $response['cart']['cart_id']); self::assertArrayHasKey('shipping_addresses', $response['cart']); self::assertCount(1, $response['cart']['shipping_addresses']); self::assertArrayHasKey('available_shipping_methods', $response['cart']['shipping_addresses'][0]); diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php index 42b5cbd06b9f..b1d5e475c793 100644 --- a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/GetCartTest.php @@ -59,8 +59,6 @@ public function testGetCart() $response = $this->graphQlQuery($query); self::assertArrayHasKey('cart', $response); - self::assertEquals($maskedQuoteId, $response['cart']['cart_id']); - self::assertArrayHasKey('items', $response['cart']); self::assertCount(2, $response['cart']['items']); @@ -109,7 +107,6 @@ private function getCartQuery( return <<quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->productRepository = $objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + */ + public function testRemoveItemFromCart() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $itemId = (int)$quote->getItemByProduct($this->productRepository->get('simple'))->getId(); + + $query = $this->prepareMutationQuery($maskedQuoteId, $itemId); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('removeItemFromCart', $response); + $this->assertArrayHasKey('cart', $response['removeItemFromCart']); + $this->assertCount(0, $response['removeItemFromCart']['cart']['items']); + } + + /** + * @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); + + $this->graphQlQuery($query); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + */ + public function testRemoveNotExistentItem() + { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$quote->getId()); + $notExistentItemId = 999; + + $this->expectExceptionMessage("Cart doesn't contain the {$notExistentItemId} item."); + + $query = $this->prepareMutationQuery($maskedQuoteId, $notExistentItemId); + $this->graphQlQuery($query); + } + + /** + * Test mutation is only able to remove quote item belonging to the requested cart + * + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php + */ + public function testRemoveItemIfItemIsNotBelongToCart() + { + $firstQuote = $this->quoteFactory->create(); + $this->quoteResource->load($firstQuote, 'test_order_with_simple_product_without_address', 'reserved_order_id'); + $firstQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$firstQuote->getId()); + + $secondQuote = $this->quoteFactory->create(); + $this->quoteResource->load( + $secondQuote, + 'test_order_with_virtual_product_without_address', + 'reserved_order_id' + ); + $secondQuoteItemId = (int)$secondQuote + ->getItemByProduct($this->productRepository->get('virtual-product')) + ->getId(); + + $this->expectExceptionMessage("Cart doesn't contain the {$secondQuoteItemId} item."); + + $query = $this->prepareMutationQuery($firstQuoteMaskedId, $secondQuoteItemId); + $this->graphQlQuery($query); + } + + /** + * Test mutation is only able to remove quote item belonging to the requested cart + * + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php + */ + public function testRemoveItemFromCustomerCart() + { + $customerQuote = $this->quoteFactory->create(); + $this->quoteResource->load($customerQuote, 'test_order_1', 'reserved_order_id'); + $customerQuoteMaskedId = $this->quoteIdToMaskedId->execute((int)$customerQuote->getId()); + $customerQuoteItemId = (int)$customerQuote->getItemByProduct($this->productRepository->get('simple'))->getId(); + + $this->expectExceptionMessage("The current user cannot perform operations on cart \"$customerQuoteMaskedId\""); + + $query = $this->prepareMutationQuery($customerQuoteMaskedId, $customerQuoteItemId); + $this->graphQlQuery($query); + } + + /** + * @param string $maskedQuoteId + * @param int $itemId + * @return string + */ + private function prepareMutationQuery(string $maskedQuoteId, int $itemId): string + { + return <<objectManager = Bootstrap::getObjectManager(); - $this->quoteResource = $this->objectManager->create(QuoteResource::class); - $this->quote = $this->objectManager->create(Quote::class); - $this->quoteIdToMaskedId = $this->objectManager->create(QuoteIdToMaskedQuoteIdInterface::class); - $this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class); - $this->guestCartRepository = $this->objectManager->create(GuestCartRepositoryInterface::class); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - */ - public function testGuestRemoveItemFromCart() - { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $itemId = $this->quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - - $query = <<graphQlQuery($query); - - $this->assertArrayHasKey('removeItemFromCart', $response); - $this->assertArrayHasKey('cart', $response['removeItemFromCart']); - - $responseCart = $response['removeItemFromCart']['cart']; - - $this->assertCount(0, $responseCart['items']); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/Customer/_files/customer.php - */ - public function testRemoveItemFromCart() - { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $itemId = $this->quote->getItemByProduct($this->productRepository->get('simple'))->getId(); - - $this->quote->setCustomerId(1); - $this->quoteResource->save($this->quote); - - $headerMap = $this->getHeaderMap(); - - $query = <<graphQlQuery($query, [], '', $headerMap); - - $this->assertArrayHasKey('removeItemFromCart', $response); - $this->assertArrayHasKey('cart', $response['removeItemFromCart']); - - $responseCart = $response['removeItemFromCart']['cart']; - - $this->assertCount(0, $responseCart['items']); - } - - public function testRemoveItemFromCartNoSuchCartIdException() - { - $maskedCartId = 'nada'; - - $this->expectExceptionMessage('No such entity with cartId'); - - $query = <<graphQlQuery($query); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - */ - public function testRemoveItemFromCartNoSuchCartItem() - { - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $itemId = 'nononono'; - - $this->expectExceptionMessage(sprintf('Cart doesn\'t contain the %s item.', $itemId)); - - $query = <<graphQlQuery($query); - } - - /** - * Test mutation is only able to remove quote item belonging to the requested cart - * - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_virtual_product_saved.php - * @expectedException \Exception - * @expectedExceptionMessage Could not find cart item with id - */ - public function testRemoveItemFromDifferentQuote() - { - /** @var Quote $secondQuote */ - $secondQuote = $this->objectManager->create(Quote::class); - $this->quoteResource->load( - $secondQuote, - 'test_order_with_virtual_product_without_address', - 'reserved_order_id' - ); - $secondQuoteItem = $secondQuote->getItemByProduct($this->productRepository->get('virtual-product')); - - $this->quoteResource->load( - $this->quote, - 'test_order_with_simple_product_without_address', - 'reserved_order_id' - ); - $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); - $itemId = $secondQuoteItem->getItemId(); - - $this->expectExceptionMessage(sprintf('Cart doesn\'t contain the %s item.', $itemId)); - - $query = <<graphQlQuery($query); - } - - /** - * @param string $username - * @return array - */ - private function getHeaderMap(string $username = 'customer@example.com'): array - { - $password = 'password'; - /** @var CustomerTokenServiceInterface $customerTokenService */ - $customerTokenService = ObjectManager::getInstance() - ->get(CustomerTokenServiceInterface::class); - $customerToken = $customerTokenService->createCustomerAccessToken($username, $password); - $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; - return $headerMap; - } -}