This repository has been archived by the owner on Dec 19, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 154
#141 add simple product to cart #170
Merged
magento-engcom-team
merged 22 commits into
2.3-develop
from
141-add-simple-product-to-cart
Oct 3, 2018
Merged
Changes from 9 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
eea5cdd
#141 Added add simple product to cart mutation to quote-graphql module
50a928c
#141 Added required configurations
5105989
#141 Added hard dependencies
1734dfc
#141 Fixed issues from Travis
7e7e82c
#141 Running tests again
01404a0
#141 Added descriptions to classes and methods
1064854
#141 Performed decoupling of the resolvers
34e0106
#141 Added missed lines in phpdocs
e8011a8
#141 Removed redundant dependency
436dee7
#141 Restored config after patching the branch
4942c6f
#141 Decoupling the CustomOption data provider
e901431
Merge remote-tracking branch 'origin/2.3-develop' into 141-add-simple…
7990b83
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
ada51dc
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
484c65c
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
6b7300a
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
c21a016
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
d39230e
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
d43164b
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
fa5940a
Merge remote-tracking branch 'origin/2.3-develop' into 141-add-simple…
c78b993
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
7e3c023
GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
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,66 @@ | ||
<?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; | ||
|
||
/** | ||
* Catalog product option date validator | ||
* {@inheritdoc} | ||
*/ | ||
class DateType extends ProductDateOptionType | ||
{ | ||
/** | ||
* Make valid string as a value of date option type for GraphQl queries | ||
* {@inheritdoc} | ||
*/ | ||
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 | ||
*/ | ||
protected 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; | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.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,122 @@ | ||
<?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\LocalizedException; | ||
use Magento\Framework\Exception\NoSuchEntityException; | ||
use Magento\Framework\Stdlib\ArrayManager; | ||
use Magento\Quote\Api\CartRepositoryInterface; | ||
use Magento\Quote\Api\Data\CartInterface; | ||
use Magento\Quote\Api\GuestCartRepositoryInterface; | ||
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; | ||
use Magento\Quote\Model\Quote; | ||
use Magento\Quote\Model\Quote\Item as QuoteItem; | ||
|
||
/** | ||
* Add simple product to cart process | ||
*/ | ||
class AddSimpleProductToCartProcessor | ||
{ | ||
/** | ||
* @var ArrayManager | ||
*/ | ||
private $arrayManager; | ||
|
||
/** | ||
* @var CartRepositoryInterface | ||
*/ | ||
private $cartRepository; | ||
|
||
/** | ||
* @var MaskedQuoteIdToQuoteIdInterface | ||
*/ | ||
private $maskedQuoteIdToQuoteId; | ||
|
||
/** | ||
* @var DataObjectFactory | ||
*/ | ||
private $dataObjectFactory; | ||
|
||
/** | ||
* @var GuestCartRepositoryInterface | ||
*/ | ||
private $guestCartRepository; | ||
|
||
/** | ||
* @var ProductRepositoryInterface | ||
*/ | ||
private $productRepository; | ||
|
||
/** | ||
* @param ArrayManager $arrayManager | ||
* @param DataObjectFactory $dataObjectFactory | ||
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId | ||
* @param CartRepositoryInterface $cartRepository | ||
* @param GuestCartRepositoryInterface $guestCartRepository | ||
* @param ProductRepositoryInterface $productRepository | ||
*/ | ||
public function __construct( | ||
ArrayManager $arrayManager, | ||
DataObjectFactory $dataObjectFactory, | ||
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, | ||
CartRepositoryInterface $cartRepository, | ||
GuestCartRepositoryInterface $guestCartRepository, | ||
ProductRepositoryInterface $productRepository | ||
) { | ||
$this->productRepository = $productRepository; | ||
$this->guestCartRepository = $guestCartRepository; | ||
$this->dataObjectFactory = $dataObjectFactory; | ||
$this->cartRepository = $cartRepository; | ||
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; | ||
$this->arrayManager = $arrayManager; | ||
} | ||
|
||
/** | ||
* Resolve adding simple product to cart for customers/guests | ||
* | ||
* @param CartInterface|Quote $cart | ||
* @param array $cartItemData | ||
* @return QuoteItem|string | ||
* @throws LocalizedException | ||
* @throws NoSuchEntityException | ||
*/ | ||
public function process($cart, array $cartItemData) | ||
{ | ||
$sku = $this->arrayManager->get('details/sku', $cartItemData); | ||
$product = $this->productRepository->get($sku); | ||
|
||
return $cart->addProduct($product, $this->getBuyRequest($cartItemData)); | ||
} | ||
|
||
/** | ||
* Format GraphQl input data to a shape that buy request has | ||
* | ||
* @param array $cartItem | ||
* @return DataObject | ||
*/ | ||
private function getBuyRequest(array $cartItem): DataObject | ||
{ | ||
$customOptions = []; | ||
$qty = $this->arrayManager->get('details/qty', $cartItem); | ||
$customizableOptions = $this->arrayManager->get('customizable_options', $cartItem, []); | ||
|
||
foreach ($customizableOptions as $customizableOption) { | ||
$customOptions[$customizableOption['id']] = $customizableOption['value']; | ||
} | ||
|
||
return $this->dataObjectFactory->create([ | ||
'data' => [ | ||
'qty' => $qty, | ||
'options' => $customOptions | ||
] | ||
]); | ||
} | ||
} |
178 changes: 178 additions & 0 deletions
178
app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.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,178 @@ | ||
<?php | ||
/** | ||
* Copyright © Magento, Inc. All rights reserved. | ||
* See COPYING.txt for license details. | ||
*/ | ||
declare(strict_types=1); | ||
|
||
namespace Magento\QuoteGraphQl\Model\Resolver\Cart; | ||
|
||
use Magento\Authorization\Model\UserContextInterface; | ||
use Magento\Framework\Exception\NoSuchEntityException; | ||
use Magento\Framework\GraphQl\Config\Element\Field; | ||
use Magento\Framework\GraphQl\Exception\GraphQlInputException; | ||
use Magento\Framework\GraphQl\Query\Resolver\Value; | ||
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory; | ||
use Magento\Framework\GraphQl\Query\ResolverInterface; | ||
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; | ||
use Magento\Framework\Message\AbstractMessage; | ||
use Magento\Framework\Stdlib\ArrayManager; | ||
use Magento\Quote\Api\CartRepositoryInterface; | ||
use Magento\Quote\Api\Data\CartInterface; | ||
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; | ||
use Magento\Quote\Model\Quote; | ||
use Magento\QuoteGraphQl\Model\Cart\AddSimpleProductToCartProcessor; | ||
use Magento\QuoteGraphQl\Model\Resolver\DataProvider\Cart\CartHydrator; | ||
|
||
/** | ||
* Add simple product to cart GraphQl resolver | ||
* {@inheritdoc} | ||
*/ | ||
class AddSimpleProductsToCart implements ResolverInterface | ||
{ | ||
/** | ||
* @var AddSimpleProductToCartProcessor | ||
*/ | ||
private $addSimpleProductToCartProcessor; | ||
|
||
/** | ||
* @var CartRepositoryInterface | ||
*/ | ||
private $cartRepository; | ||
|
||
/** | ||
* @var MaskedQuoteIdToQuoteIdInterface | ||
*/ | ||
private $maskedQuoteIdToQuoteId; | ||
|
||
/** | ||
* @var CartHydrator | ||
*/ | ||
private $cartHydrator; | ||
|
||
/** | ||
* @var ArrayManager | ||
*/ | ||
private $arrayManager; | ||
|
||
/** | ||
* @var ValueFactory | ||
*/ | ||
private $valueFactory; | ||
|
||
/** | ||
* @var UserContextInterface | ||
*/ | ||
private $userContext; | ||
|
||
/** | ||
* @param AddSimpleProductToCartProcessor $addSimpleProductToCartProcessor | ||
* @param CartHydrator $cartHydrator | ||
* @param ArrayManager $arrayManager | ||
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId | ||
* @param CartRepositoryInterface $cartRepository | ||
* @param ValueFactory $valueFactory | ||
* @param UserContextInterface $userContext | ||
*/ | ||
public function __construct( | ||
AddSimpleProductToCartProcessor $addSimpleProductToCartProcessor, | ||
CartHydrator $cartHydrator, | ||
ArrayManager $arrayManager, | ||
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, | ||
CartRepositoryInterface $cartRepository, | ||
ValueFactory $valueFactory, | ||
UserContextInterface $userContext | ||
) { | ||
$this->valueFactory = $valueFactory; | ||
$this->userContext = $userContext; | ||
$this->arrayManager = $arrayManager; | ||
$this->cartHydrator = $cartHydrator; | ||
$this->cartRepository = $cartRepository; | ||
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; | ||
$this->addSimpleProductToCartProcessor = $addSimpleProductToCartProcessor; | ||
} | ||
|
||
/** | ||
* Resolve adding simple product to cart for customers/guests | ||
* {@inheritdoc} | ||
*/ | ||
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) : Value | ||
{ | ||
$cartHash = $this->arrayManager->get('input/cart_id', $args); | ||
$cartItems = $this->arrayManager->get('input/cartItems', $args); | ||
|
||
if (!isset($cartHash)) { | ||
throw new GraphQlInputException( | ||
__('Missing key %1 in cart data', ['cart_id']) | ||
); | ||
} | ||
|
||
if (!isset($cartItems)) { | ||
throw new GraphQlInputException( | ||
__('Missing key %1 in cart data', ['cartItems']) | ||
); | ||
} | ||
|
||
$cart = $this->getCart((string) $cartHash); | ||
|
||
foreach ($cartItems as $cartItemData) { | ||
$sku = $this->arrayManager->get('details/sku', $cartItemData); | ||
|
||
$message = $this->addSimpleProductToCartProcessor->process($cart, $cartItemData); | ||
|
||
if (is_string($message)) { | ||
throw new GraphQlInputException( | ||
__('%1: %2', $sku, $message) | ||
); | ||
} | ||
|
||
if ($cart->getData('has_error')) { | ||
throw new GraphQlInputException( | ||
__('%1: %2', $sku, $this->getCartErrors($cart)) | ||
); | ||
} | ||
} | ||
|
||
$this->cartRepository->save($cart); | ||
|
||
$result = function () use ($cart) { | ||
return [ | ||
'cart' => $this->cartHydrator->hydrate($cart) | ||
]; | ||
}; | ||
|
||
return $this->valueFactory->create($result); | ||
} | ||
|
||
/** | ||
* Collecting cart errors | ||
* | ||
* @param CartInterface|Quote $cart | ||
* @return string | ||
*/ | ||
private function getCartErrors($cart): string | ||
{ | ||
$errorMessages = []; | ||
|
||
/** @var AbstractMessage $error */ | ||
foreach ($cart->getErrors() as $error) { | ||
$errorMessages[] = $error->getText(); | ||
} | ||
|
||
return implode(PHP_EOL, $errorMessages); | ||
} | ||
|
||
/** | ||
* Retrieving quote mode based on customer authorization | ||
* | ||
* @param string $cartHash | ||
* @return CartInterface|Quote | ||
* @throws NoSuchEntityException | ||
*/ | ||
private function getCart(string $cartHash): CartInterface | ||
{ | ||
$cartId = $this->maskedQuoteIdToQuoteId->execute((string) $cartHash); | ||
|
||
return $this->cartRepository->get($cartId); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this one needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why it's needed is ProductDateOptionType wants to see date value as an associate array (like ['year' => '2018', 'month' => '1', 'day' => '1']). By this changes, we allow to use string as a date value. This meets our schema shape.
The same approach is used in REST API.