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

GraphQl-622: No possibility to update customizable_options in updateCartItems mutation #626

Merged
merged 12 commits into from
Jun 25, 2019
Merged
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