Skip to content
This repository was archived by the owner on Dec 19, 2019. It is now read-only.

Commit 7990b83

Browse files
author
Valeriy Nayda
committed
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
1 parent e901431 commit 7990b83

25 files changed

+655
-704
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Cart;
9+
10+
use Magento\Framework\Exception\NoSuchEntityException;
11+
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
14+
use Magento\Framework\Message\AbstractMessage;
15+
use Magento\Quote\Api\CartRepositoryInterface;
16+
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
17+
use Magento\Quote\Model\Quote;
18+
use Magento\QuoteGraphQl\Model\Authorization\IsCartMutationAllowedForCurrentUser;
19+
20+
/**
21+
* Add products to cart
22+
*/
23+
class AddProductsToCart
24+
{
25+
/**
26+
* @var MaskedQuoteIdToQuoteIdInterface
27+
*/
28+
private $maskedQuoteIdToQuoteId;
29+
30+
/**
31+
* @var CartRepositoryInterface
32+
*/
33+
private $cartRepository;
34+
35+
/**
36+
* @var IsCartMutationAllowedForCurrentUser
37+
*/
38+
private $isCartMutationAllowedForCurrentUser;
39+
40+
/**
41+
* @var AddSimpleProductToCart
42+
*/
43+
private $addProductToCart;
44+
45+
/**
46+
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
47+
* @param CartRepositoryInterface $cartRepository
48+
* @param IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser
49+
* @param AddSimpleProductToCart $addProductToCart
50+
*/
51+
public function __construct(
52+
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
53+
CartRepositoryInterface $cartRepository,
54+
IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser,
55+
AddSimpleProductToCart $addProductToCart
56+
) {
57+
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
58+
$this->cartRepository = $cartRepository;
59+
$this->isCartMutationAllowedForCurrentUser = $isCartMutationAllowedForCurrentUser;
60+
$this->addProductToCart = $addProductToCart;
61+
}
62+
63+
/**
64+
* Add products to cart
65+
*
66+
* @param string $cartHash
67+
* @param array $cartItems
68+
* @return Quote
69+
* @throws GraphQlInputException
70+
*/
71+
public function execute(string $cartHash, array $cartItems): Quote
72+
{
73+
$cart = $this->getCart($cartHash);
74+
75+
foreach ($cartItems as $cartItemData) {
76+
$this->addProductToCart->execute($cart, $cartItemData);
77+
}
78+
79+
if ($cart->getData('has_error')) {
80+
throw new GraphQlInputException(
81+
__('Shopping cart error: %message', ['message' => $this->getCartErrors($cart)])
82+
);
83+
}
84+
85+
$this->cartRepository->save($cart);
86+
return $cart;
87+
}
88+
89+
/**
90+
* @param string $cartHash
91+
* @return Quote
92+
* @throws GraphQlNoSuchEntityException
93+
* @throws GraphQlAuthorizationException
94+
*/
95+
private function getCart(string $cartHash): Quote
96+
{
97+
try {
98+
$cartId = $this->maskedQuoteIdToQuoteId->execute($cartHash);
99+
$cart = $this->cartRepository->get($cartId);
100+
} catch (NoSuchEntityException $e) {
101+
throw new GraphQlNoSuchEntityException(
102+
__('Could not find a cart with ID "%masked_cart_id"', ['masked_cart_id' => $cartHash])
103+
);
104+
}
105+
106+
if (false === $this->isCartMutationAllowedForCurrentUser->execute($cartId)) {
107+
throw new GraphQlAuthorizationException(
108+
__(
109+
'The current user cannot perform operations on cart "%masked_cart_id"',
110+
['masked_cart_id' => $cartHash]
111+
)
112+
);
113+
}
114+
115+
/** @var Quote $cart */
116+
return $cart;
117+
}
118+
119+
/**
120+
* Collecting cart errors
121+
*
122+
* @param Quote $cart
123+
* @return string
124+
*/
125+
private function getCartErrors(Quote $cart): string
126+
{
127+
$errorMessages = [];
128+
129+
/** @var AbstractMessage $error */
130+
foreach ($cart->getErrors() as $error) {
131+
$errorMessages[] = $error->getText();
132+
}
133+
134+
return implode(PHP_EOL, $errorMessages);
135+
}
136+
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Cart;
9+
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Framework\DataObject;
12+
use Magento\Framework\DataObjectFactory;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
15+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
16+
use Magento\Framework\Stdlib\ArrayManager;
17+
use Magento\Quote\Model\Quote;
18+
19+
/**
20+
* Add simple product to cart
21+
*
22+
* TODO: should be replaced for different types resolver
23+
*/
24+
class AddSimpleProductToCart
25+
{
26+
/**
27+
* @var ArrayManager
28+
*/
29+
private $arrayManager;
30+
31+
/**
32+
* @var DataObjectFactory
33+
*/
34+
private $dataObjectFactory;
35+
36+
/**
37+
* @var ProductRepositoryInterface
38+
*/
39+
private $productRepository;
40+
41+
/**
42+
* @param ArrayManager $arrayManager
43+
* @param DataObjectFactory $dataObjectFactory
44+
* @param ProductRepositoryInterface $productRepository
45+
*/
46+
public function __construct(
47+
ArrayManager $arrayManager,
48+
DataObjectFactory $dataObjectFactory,
49+
ProductRepositoryInterface $productRepository
50+
) {
51+
$this->arrayManager = $arrayManager;
52+
$this->dataObjectFactory = $dataObjectFactory;
53+
$this->productRepository = $productRepository;
54+
}
55+
56+
/**
57+
* Add simple product to cart
58+
*
59+
* @param Quote $cart
60+
* @param array $cartItemData
61+
* @return void
62+
* @throws GraphQlNoSuchEntityException
63+
* @throws GraphQlInputException
64+
*/
65+
public function execute(Quote $cart, array $cartItemData): void
66+
{
67+
$sku = $this->extractSku($cartItemData);
68+
$qty = $this->extractQty($cartItemData);
69+
$customizableOptions = $this->extractCustomizableOptions($cartItemData);
70+
71+
try {
72+
$product = $this->productRepository->get($sku);
73+
} catch (NoSuchEntityException $e) {
74+
throw new GraphQlNoSuchEntityException(__('Could not find a product with SKU "%sku"', ['sku' => $sku]));
75+
}
76+
77+
$result = $cart->addProduct($product, $this->createBuyRequest($qty, $customizableOptions));
78+
79+
if (is_string($result)) {
80+
throw new GraphQlInputException(__($result));
81+
}
82+
}
83+
84+
/**
85+
* Extract SKU from cart item data
86+
*
87+
* @param array $cartItemData
88+
* @return string
89+
* @throws GraphQlInputException
90+
*/
91+
private function extractSku(array $cartItemData): string
92+
{
93+
$sku = $this->arrayManager->get('data/sku', $cartItemData);
94+
if (!isset($sku)) {
95+
throw new GraphQlInputException( __('Missing key "sku" in cart item data'));
96+
}
97+
return (string)$sku;
98+
}
99+
100+
/**
101+
* Extract Qty from cart item data
102+
*
103+
* @param array $cartItemData
104+
* @return float
105+
* @throws GraphQlInputException
106+
*/
107+
private function extractQty(array $cartItemData): float
108+
{
109+
$qty = $this->arrayManager->get('data/qty', $cartItemData);
110+
if (!isset($qty)) {
111+
throw new GraphQlInputException( __('Missing key "qty" in cart item data'));
112+
}
113+
return (float)$qty;
114+
}
115+
116+
/**
117+
* Extract Customizable Options from cart item data
118+
*
119+
* @param array $cartItemData
120+
* @return array
121+
*/
122+
private function extractCustomizableOptions(array $cartItemData): array
123+
{
124+
$customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []);
125+
126+
$customizableOptionsData = [];
127+
foreach ($customizableOptions as $customizableOption) {
128+
$customizableOptionsData[$customizableOption['id']] = $customizableOption['value'];
129+
}
130+
return $customizableOptionsData;
131+
}
132+
133+
/**
134+
* Format GraphQl input data to a shape that buy request has
135+
*
136+
* @param float $qty
137+
* @param array $customOptions
138+
* @return DataObject
139+
*/
140+
private function createBuyRequest(float $qty, array $customOptions): DataObject
141+
{
142+
return $this->dataObjectFactory->create([
143+
'data' => [
144+
'qty' => $qty,
145+
'options' => $customOptions,
146+
],
147+
]);
148+
}
149+
}

0 commit comments

Comments
 (0)