Skip to content

Commit

Permalink
ENGCOM-5349: GraphQl-622: No possibility to update customizable_optio…
Browse files Browse the repository at this point in the history
…ns in updateCartItems mutation magento#626

 - Merge Pull Request magento/graphql-ce#626 from magento/graphql-ce:622-customizable-options-update-cart
 - Merged commits:
   1. 0e8cf92
   2. 19b92cd
   3. 62e0530
   4. 9787c95
   5. 7d9a133
   6. c0c04ff
   7. f81a633
   8. 91251ea
   9. ba64fbf
   10. 1cec875
   11. 1cf357b
   12. d3734f8
  • Loading branch information
magento-engcom-team committed Jun 24, 2019
2 parents 1e58f70 + d3734f8 commit 42c3639
Show file tree
Hide file tree
Showing 10 changed files with 628 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
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;
Expand All @@ -21,25 +19,25 @@
class AddSimpleProductToCart
{
/**
* @var DataObjectFactory
* @var CreateBuyRequest
*/
private $dataObjectFactory;
private $createBuyRequest;

/**
* @var ProductRepositoryInterface
*/
private $productRepository;

/**
* @param DataObjectFactory $dataObjectFactory
* @param ProductRepositoryInterface $productRepository
* @param CreateBuyRequest $createBuyRequest
*/
public function __construct(
DataObjectFactory $dataObjectFactory,
ProductRepositoryInterface $productRepository
ProductRepositoryInterface $productRepository,
CreateBuyRequest $createBuyRequest
) {
$this->dataObjectFactory = $dataObjectFactory;
$this->productRepository = $productRepository;
$this->createBuyRequest = $createBuyRequest;
}

/**
Expand All @@ -56,7 +54,7 @@ public function execute(Quote $cart, array $cartItemData): void
{
$sku = $this->extractSku($cartItemData);
$quantity = $this->extractQuantity($cartItemData);
$customizableOptions = $this->extractCustomizableOptions($cartItemData);
$customizableOptions = $cartItemData['customizable_options'] ?? [];

try {
$product = $this->productRepository->get($sku);
Expand All @@ -65,7 +63,7 @@ public function execute(Quote $cart, array $cartItemData): void
}

try {
$result = $cart->addProduct($product, $this->createBuyRequest($quantity, $customizableOptions));
$result = $cart->addProduct($product, $this->createBuyRequest->execute($quantity, $customizableOptions));
} catch (\Exception $e) {
throw new GraphQlInputException(
__(
Expand Down Expand Up @@ -116,60 +114,4 @@ private function extractQuantity(array $cartItemData): float
}
return $quantity;
}

/**
* Extract Customizable Options from cart item data
*
* @param array $cartItemData
* @return array
*/
private function extractCustomizableOptions(array $cartItemData): array
{
if (!isset($cartItemData['customizable_options']) || empty($cartItemData['customizable_options'])) {
return [];
}

$customizableOptionsData = [];
foreach ($cartItemData['customizable_options'] as $customizableOption) {
if (isset($customizableOption['value_string'])) {
$customizableOptionsData[$customizableOption['id']] = $this->convertCustomOptionValue(
$customizableOption['value_string']
);
}
}
return $customizableOptionsData;
}

/**
* Format GraphQl input data to a shape that buy request has
*
* @param float $quantity
* @param array $customOptions
* @return DataObject
*/
private function createBuyRequest(float $quantity, array $customOptions): DataObject
{
return $this->dataObjectFactory->create([
'data' => [
'qty' => $quantity,
'options' => $customOptions,
],
]);
}

/**
* Convert custom options vakue
*
* @param string $value
* @return string|array
*/
private function convertCustomOptionValue(string $value)
{
$value = trim($value);
if (substr($value, 0, 1) === "[" &&
substr($value, strlen($value) - 1, 1) === "]") {
return explode(',', substr($value, 1, -1));
}
return $value;
}
}
75 changes: 75 additions & 0 deletions app/code/Magento/QuoteGraphQl/Model/Cart/CreateBuyRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?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\DataObject;
use Magento\Framework\DataObjectFactory;

/**
* Creates buy request that can be used for working with cart items
*/
class CreateBuyRequest
{
/**
* @var DataObjectFactory
*/
private $dataObjectFactory;

/**
* @param DataObjectFactory $dataObjectFactory
*/
public function __construct(
DataObjectFactory $dataObjectFactory
) {
$this->dataObjectFactory = $dataObjectFactory;
}

/**
* Returns buy request for working with cart items
*
* @param float $qty
* @param array $customizableOptionsData
* @return DataObject
*/
public function execute(float $qty, array $customizableOptionsData): DataObject
{
$customizableOptions = [];
foreach ($customizableOptionsData as $customizableOption) {
if (isset($customizableOption['value_string'])) {
$customizableOptions[$customizableOption['id']] = $this->convertCustomOptionValue(
$customizableOption['value_string']
);
}
}

return $this->dataObjectFactory->create(
[
'data' => [
'qty' => $qty,
'options' => $customizableOptions,
],
]
);
}

/**
* Convert custom options value
*
* @param string $value
* @return string|array
*/
private function convertCustomOptionValue(string $value)
{
$value = trim($value);
if (substr($value, 0, 1) === "[" &&
substr($value, strlen($value) - 1, 1) === "]") {
return explode(',', substr($value, 1, -1));
}
return $value;
}
}
147 changes: 147 additions & 0 deletions app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
<?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\LocalizedException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
use Magento\Quote\Api\CartItemRepositoryInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Item;

/**
* Update cart item
*/
class UpdateCartItem
{
/**
* @var CreateBuyRequest
*/
private $createBuyRequest;

/**
* @var CartRepositoryInterface
*/
private $quoteRepository;

/**
* @var CartItemRepositoryInterface
*/
private $cartItemRepository;

/**
* @param CartItemRepositoryInterface $cartItemRepository
* @param CartRepositoryInterface $quoteRepository
* @param CreateBuyRequest $createBuyRequest
*/
public function __construct(
CartItemRepositoryInterface $cartItemRepository,
CartRepositoryInterface $quoteRepository,
CreateBuyRequest $createBuyRequest
) {
$this->cartItemRepository = $cartItemRepository;
$this->quoteRepository = $quoteRepository;
$this->createBuyRequest = $createBuyRequest;
}

/**
* Update cart item
*
* @param Quote $cart
* @param int $cartItemId
* @param float $quantity
* @param array $customizableOptionsData
* @return void
* @throws GraphQlInputException
* @throws GraphQlNoSuchEntityException
* @throws NoSuchEntityException
*/
public function execute(Quote $cart, int $cartItemId, float $quantity, array $customizableOptionsData): void
{
if (count($customizableOptionsData) === 0) { // Update only item's qty
$this->updateItemQuantity($cartItemId, $cart, $quantity);

return;
}

try {
$result = $cart->updateItem(
$cartItemId,
$this->createBuyRequest->execute($quantity, $customizableOptionsData)
);
} catch (LocalizedException $e) {
throw new GraphQlInputException(
__(
'Could not update cart item: %message',
['message' => $e->getMessage()]
)
);
}

if ($result->getHasError()) {
throw new GraphQlInputException(
__(
'Could not update cart item: %message',
['message' => $result->getMessage()]
)
);
}

$this->quoteRepository->save($cart);
}

/**
* Updates item qty for the specified cart
*
* @param int $itemId
* @param Quote $cart
* @param float $quantity
* @throws GraphQlNoSuchEntityException
* @throws NoSuchEntityException
* @throws GraphQlNoSuchEntityException
*/
private function updateItemQuantity(int $itemId, Quote $cart, float $quantity)
{
$cartItem = $cart->getItemById($itemId);
if ($cartItem === false) {
throw new GraphQlNoSuchEntityException(
__('Could not find cart item with id: %1.', $itemId)
);
}
$cartItem->setQty($quantity);
$this->validateCartItem($cartItem);
$this->cartItemRepository->save($cartItem);
}

/**
* Validate cart item
*
* @param Item $cartItem
* @return void
* @throws GraphQlInputException
*/
private function validateCartItem(Item $cartItem): void
{
if ($cartItem->getHasError()) {
$errors = [];
foreach ($cartItem->getMessage(false) as $message) {
$errors[] = $message;
}
if (!empty($errors)) {
throw new GraphQlInputException(
__(
'Could not update the product with SKU %sku: %message',
['sku' => $cartItem->getSku(), 'message' => __(implode("\n", $errors))]
)
);
}
}
}
}
Loading

0 comments on commit 42c3639

Please sign in to comment.