-
Notifications
You must be signed in to change notification settings - Fork 9.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Merge Pull Request magento/graphql-ce#170 from magento/graphql-ce:141-add-simple-product-to-cart - Merged commits: 1. eea5cdd 2. 50a928c 3. 5105989 4. 1734dfc 5. 7e7e82c 6. 01404a0 7. 1064854 8. 34e0106 9. e8011a8 10. 436dee7 11. 4942c6f 12. e901431 13. 7990b83 14. ada51dc 15. 484c65c 16. 6b7300a 17. c21a016 18. d39230e 19. d43164b 20. fa5940a 21. c78b993 22. 7e3c023
- Loading branch information
Showing
21 changed files
with
1,120 additions
and
10 deletions.
There are no files selected for viewing
67 changes: 67 additions & 0 deletions
67
app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\CatalogGraphQl\Model\Product\Option; | ||
|
||
use Magento\Catalog\Model\Product\Option\Type\Date as ProductDateOptionType; | ||
use Magento\Framework\Exception\LocalizedException; | ||
use Magento\Framework\Stdlib\DateTime; | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
class DateType extends ProductDateOptionType | ||
{ | ||
/** | ||
* Make valid string as a value of date option type for GraphQl queries | ||
* | ||
* @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) | ||
* @return ProductDateOptionType | ||
*/ | ||
public function validateUserValue($values) | ||
{ | ||
if ($this->_dateExists() || $this->_timeExists()) { | ||
return parent::validateUserValue($this->formatValues($values)); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** | ||
* Format date value from string to date array | ||
* | ||
* @param [] $values | ||
* @return [] | ||
* @throws LocalizedException | ||
*/ | ||
private function formatValues($values) | ||
{ | ||
if (isset($values[$this->getOption()->getId()])) { | ||
$value = $values[$this->getOption()->getId()]; | ||
$dateTime = \DateTime::createFromFormat(DateTime::DATETIME_PHP_FORMAT, $value); | ||
$values[$this->getOption()->getId()] = [ | ||
'date' => $value, | ||
'year' => $dateTime->format('Y'), | ||
'month' => $dateTime->format('m'), | ||
'day' => $dateTime->format('d'), | ||
'hour' => $dateTime->format('H'), | ||
'minute' => $dateTime->format('i'), | ||
'day_part' => $dateTime->format('a'), | ||
]; | ||
} | ||
|
||
return $values; | ||
} | ||
|
||
/** | ||
* @inheritdoc | ||
*/ | ||
public function useCalendar() | ||
{ | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\QuoteGraphQl\Model\Cart; | ||
|
||
use Magento\Framework\Exception\NoSuchEntityException; | ||
use Magento\Framework\GraphQl\Exception\GraphQlAuthorizationException; | ||
use Magento\Framework\GraphQl\Exception\GraphQlInputException; | ||
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; | ||
use Magento\Framework\Message\AbstractMessage; | ||
use Magento\Quote\Api\CartRepositoryInterface; | ||
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; | ||
use Magento\Quote\Model\Quote; | ||
use Magento\QuoteGraphQl\Model\Authorization\IsCartMutationAllowedForCurrentUser; | ||
|
||
/** | ||
* Add products to cart | ||
*/ | ||
class AddProductsToCart | ||
{ | ||
/** | ||
* @var MaskedQuoteIdToQuoteIdInterface | ||
*/ | ||
private $maskedQuoteIdToQuoteId; | ||
|
||
/** | ||
* @var CartRepositoryInterface | ||
*/ | ||
private $cartRepository; | ||
|
||
/** | ||
* @var IsCartMutationAllowedForCurrentUser | ||
*/ | ||
private $isCartMutationAllowedForCurrentUser; | ||
|
||
/** | ||
* @var AddSimpleProductToCart | ||
*/ | ||
private $addProductToCart; | ||
|
||
/** | ||
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId | ||
* @param CartRepositoryInterface $cartRepository | ||
* @param IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser | ||
* @param AddSimpleProductToCart $addProductToCart | ||
*/ | ||
public function __construct( | ||
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, | ||
CartRepositoryInterface $cartRepository, | ||
IsCartMutationAllowedForCurrentUser $isCartMutationAllowedForCurrentUser, | ||
AddSimpleProductToCart $addProductToCart | ||
) { | ||
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; | ||
$this->cartRepository = $cartRepository; | ||
$this->isCartMutationAllowedForCurrentUser = $isCartMutationAllowedForCurrentUser; | ||
$this->addProductToCart = $addProductToCart; | ||
} | ||
|
||
/** | ||
* Add products to cart | ||
* | ||
* @param string $cartHash | ||
* @param array $cartItems | ||
* @return Quote | ||
* @throws GraphQlInputException | ||
*/ | ||
public function execute(string $cartHash, array $cartItems): Quote | ||
{ | ||
$cart = $this->getCart($cartHash); | ||
|
||
foreach ($cartItems as $cartItemData) { | ||
$this->addProductToCart->execute($cart, $cartItemData); | ||
} | ||
|
||
if ($cart->getData('has_error')) { | ||
throw new GraphQlInputException( | ||
__('Shopping cart error: %message', ['message' => $this->getCartErrors($cart)]) | ||
); | ||
} | ||
|
||
$this->cartRepository->save($cart); | ||
return $cart; | ||
} | ||
|
||
/** | ||
* Get cart | ||
* | ||
* @param string $cartHash | ||
* @return Quote | ||
* @throws GraphQlNoSuchEntityException | ||
* @throws GraphQlAuthorizationException | ||
*/ | ||
private function getCart(string $cartHash): Quote | ||
{ | ||
try { | ||
$cartId = $this->maskedQuoteIdToQuoteId->execute($cartHash); | ||
$cart = $this->cartRepository->get($cartId); | ||
} catch (NoSuchEntityException $e) { | ||
throw new GraphQlNoSuchEntityException( | ||
__('Could not find a cart with ID "%masked_cart_id"', ['masked_cart_id' => $cartHash]) | ||
); | ||
} | ||
|
||
if (false === $this->isCartMutationAllowedForCurrentUser->execute($cartId)) { | ||
throw new GraphQlAuthorizationException( | ||
__( | ||
'The current user cannot perform operations on cart "%masked_cart_id"', | ||
['masked_cart_id' => $cartHash] | ||
) | ||
); | ||
} | ||
|
||
/** @var Quote $cart */ | ||
return $cart; | ||
} | ||
|
||
/** | ||
* Collecting cart errors | ||
* | ||
* @param Quote $cart | ||
* @return string | ||
*/ | ||
private function getCartErrors(Quote $cart): string | ||
{ | ||
$errorMessages = []; | ||
|
||
/** @var AbstractMessage $error */ | ||
foreach ($cart->getErrors() as $error) { | ||
$errorMessages[] = $error->getText(); | ||
} | ||
|
||
return implode(PHP_EOL, $errorMessages); | ||
} | ||
} |
149 changes: 149 additions & 0 deletions
149
app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\QuoteGraphQl\Model\Cart; | ||
|
||
use Magento\Catalog\Api\ProductRepositoryInterface; | ||
use Magento\Framework\DataObject; | ||
use Magento\Framework\DataObjectFactory; | ||
use Magento\Framework\Exception\NoSuchEntityException; | ||
use Magento\Framework\GraphQl\Exception\GraphQlInputException; | ||
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; | ||
use Magento\Framework\Stdlib\ArrayManager; | ||
use Magento\Quote\Model\Quote; | ||
|
||
/** | ||
* Add simple product to cart | ||
* | ||
* TODO: should be replaced for different types resolver | ||
*/ | ||
class AddSimpleProductToCart | ||
{ | ||
/** | ||
* @var ArrayManager | ||
*/ | ||
private $arrayManager; | ||
|
||
/** | ||
* @var DataObjectFactory | ||
*/ | ||
private $dataObjectFactory; | ||
|
||
/** | ||
* @var ProductRepositoryInterface | ||
*/ | ||
private $productRepository; | ||
|
||
/** | ||
* @param ArrayManager $arrayManager | ||
* @param DataObjectFactory $dataObjectFactory | ||
* @param ProductRepositoryInterface $productRepository | ||
*/ | ||
public function __construct( | ||
ArrayManager $arrayManager, | ||
DataObjectFactory $dataObjectFactory, | ||
ProductRepositoryInterface $productRepository | ||
) { | ||
$this->arrayManager = $arrayManager; | ||
$this->dataObjectFactory = $dataObjectFactory; | ||
$this->productRepository = $productRepository; | ||
} | ||
|
||
/** | ||
* Add simple product to cart | ||
* | ||
* @param Quote $cart | ||
* @param array $cartItemData | ||
* @return void | ||
* @throws GraphQlNoSuchEntityException | ||
* @throws GraphQlInputException | ||
*/ | ||
public function execute(Quote $cart, array $cartItemData): void | ||
{ | ||
$sku = $this->extractSku($cartItemData); | ||
$qty = $this->extractQty($cartItemData); | ||
$customizableOptions = $this->extractCustomizableOptions($cartItemData); | ||
|
||
try { | ||
$product = $this->productRepository->get($sku); | ||
} catch (NoSuchEntityException $e) { | ||
throw new GraphQlNoSuchEntityException(__('Could not find a product with SKU "%sku"', ['sku' => $sku])); | ||
} | ||
|
||
$result = $cart->addProduct($product, $this->createBuyRequest($qty, $customizableOptions)); | ||
|
||
if (is_string($result)) { | ||
throw new GraphQlInputException(__($result)); | ||
} | ||
} | ||
|
||
/** | ||
* Extract SKU from cart item data | ||
* | ||
* @param array $cartItemData | ||
* @return string | ||
* @throws GraphQlInputException | ||
*/ | ||
private function extractSku(array $cartItemData): string | ||
{ | ||
$sku = $this->arrayManager->get('data/sku', $cartItemData); | ||
if (!isset($sku)) { | ||
throw new GraphQlInputException(__('Missing key "sku" in cart item data')); | ||
} | ||
return (string)$sku; | ||
} | ||
|
||
/** | ||
* Extract Qty from cart item data | ||
* | ||
* @param array $cartItemData | ||
* @return float | ||
* @throws GraphQlInputException | ||
*/ | ||
private function extractQty(array $cartItemData): float | ||
{ | ||
$qty = $this->arrayManager->get('data/qty', $cartItemData); | ||
if (!isset($qty)) { | ||
throw new GraphQlInputException(__('Missing key "qty" in cart item data')); | ||
} | ||
return (float)$qty; | ||
} | ||
|
||
/** | ||
* Extract Customizable Options from cart item data | ||
* | ||
* @param array $cartItemData | ||
* @return array | ||
*/ | ||
private function extractCustomizableOptions(array $cartItemData): array | ||
{ | ||
$customizableOptions = $this->arrayManager->get('customizable_options', $cartItemData, []); | ||
|
||
$customizableOptionsData = []; | ||
foreach ($customizableOptions as $customizableOption) { | ||
$customizableOptionsData[$customizableOption['id']] = $customizableOption['value']; | ||
} | ||
return $customizableOptionsData; | ||
} | ||
|
||
/** | ||
* 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, | ||
], | ||
]); | ||
} | ||
} |
Oops, something went wrong.