Skip to content

Commit

Permalink
Merge pull request #162 from magento-lynx/2.4-gl-graphql-v1
Browse files Browse the repository at this point in the history
LYNX-258 & LYNX-259
  • Loading branch information
sumesh-GL authored Oct 26, 2023
2 parents 53769f6 + bac4885 commit 94f014f
Show file tree
Hide file tree
Showing 7 changed files with 591 additions and 40 deletions.
83 changes: 83 additions & 0 deletions app/code/Magento/Quote/Test/Fixture/MakeCartInactive.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php
/************************************************************************
*
* Copyright 2023 Adobe
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe
* and its suppliers and are protected by all applicable intellectual
* property laws, including trade secret and copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe.
* ************************************************************************
*/
declare(strict_types=1);

namespace Magento\Quote\Test\Fixture;

use Magento\Framework\DataObject;
use Magento\Framework\Exception\InvalidArgumentException;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\QuoteFactory;
use Magento\Quote\Model\ResourceModel\Quote as QuoteResource;
use Magento\TestFramework\Fixture\DataFixtureInterface;

/**
* Mark cart as inactive
*/
class MakeCartInactive implements DataFixtureInterface
{
private const FIELD_CART_ID = 'cart_id';

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

/**
* @var QuoteFactory
*/
private QuoteFactory $quoteFactory;

/**
* @var QuoteResource
*/
private QuoteResource $quoteResource;

/**
* @param CartRepositoryInterface $cartRepository
* @param QuoteFactory $quoteFactory
* @param QuoteResource $quoteResource
*/
public function __construct(
CartRepositoryInterface $cartRepository,
QuoteFactory $quoteFactory,
QuoteResource $quoteResource
) {
$this->cartRepository = $cartRepository;
$this->quoteFactory = $quoteFactory;
$this->quoteResource = $quoteResource;
}

/**
* @param array $data
* @return void
* @throws InvalidArgumentException
*/
public function apply(array $data = []): ?DataObject
{
if (empty($data[self::FIELD_CART_ID])) {
throw new InvalidArgumentException(__('"%field" is required', ['field' => self::FIELD_CART_ID]));
}

$quote = $this->quoteFactory->create();
$this->quoteResource->load($quote, $data[self::FIELD_CART_ID]);
$quote->setIsActive(false);
$this->cartRepository->save($quote);

return $quote;
}
}
78 changes: 78 additions & 0 deletions app/code/Magento/QuoteGraphQl/Model/Cart/ValidateMaskedQuoteId.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php
/************************************************************************
*
* Copyright 2023 Adobe
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe
* and its suppliers and are protected by all applicable intellectual
* property laws, including trade secret and copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe.
* ************************************************************************
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Cart;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;

/**
* Validates a pre-defined masked quote id
*/
class ValidateMaskedQuoteId
{
/**
* @var MaskedQuoteIdToQuoteIdInterface
*/
private MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId;

/**
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
*/
public function __construct(
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
) {
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
}

/**
* Validate masked id
*
* @param string $maskedId
* @throws GraphQlAlreadyExistsException
* @throws GraphQlInputException
*/
public function execute(string $maskedId): void
{
if (mb_strlen($maskedId) != 32) {
throw new GraphQlInputException(__('Cart ID length should to be 32 symbols.'));
}

if ($this->isQuoteWithSuchMaskedIdAlreadyExists($maskedId)) {
throw new GraphQlAlreadyExistsException(__('Cart with ID "%1" already exists.', $maskedId));
}
}

/**
* Check is quote with such maskedId already exists
*
* @param string $maskedId
* @return bool
*/
private function isQuoteWithSuchMaskedIdAlreadyExists(string $maskedId): bool
{
try {
$this->maskedQuoteIdToQuoteId->execute($maskedId);
return true;
} catch (NoSuchEntityException $e) {
return false;
}
}
}
50 changes: 11 additions & 39 deletions app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@

namespace Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException;
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForCustomer;
use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForGuest;
use Magento\QuoteGraphQl\Model\Cart\ValidateMaskedQuoteId;

/**
* @inheritdoc
Expand All @@ -37,19 +35,27 @@ class CreateEmptyCart implements ResolverInterface
*/
private $maskedQuoteIdToQuoteId;

/**
* @var ValidateMaskedQuoteId
*/
private ValidateMaskedQuoteId $validateMaskedQuoteId;

/**
* @param CreateEmptyCartForCustomer $createEmptyCartForCustomer
* @param CreateEmptyCartForGuest $createEmptyCartForGuest
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
* @param ValidateMaskedQuoteId $validateMaskedQuoteId
*/
public function __construct(
CreateEmptyCartForCustomer $createEmptyCartForCustomer,
CreateEmptyCartForGuest $createEmptyCartForGuest,
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
ValidateMaskedQuoteId $validateMaskedQuoteId
) {
$this->createEmptyCartForCustomer = $createEmptyCartForCustomer;
$this->createEmptyCartForGuest = $createEmptyCartForGuest;
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
$this->validateMaskedQuoteId = $validateMaskedQuoteId;
}

/**
Expand All @@ -62,46 +68,12 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
$predefinedMaskedQuoteId = null;
if (isset($args['input']['cart_id'])) {
$predefinedMaskedQuoteId = $args['input']['cart_id'];
$this->validateMaskedId($predefinedMaskedQuoteId);
$this->validateMaskedQuoteId->execute($predefinedMaskedQuoteId);
}

$maskedQuoteId = (0 === $customerId || null === $customerId)
? $this->createEmptyCartForGuest->execute($predefinedMaskedQuoteId)
: $this->createEmptyCartForCustomer->execute($customerId, $predefinedMaskedQuoteId);
return $maskedQuoteId;
}

/**
* Validate masked id
*
* @param string $maskedId
* @throws GraphQlAlreadyExistsException
* @throws GraphQlInputException
*/
private function validateMaskedId(string $maskedId): void
{
if (mb_strlen($maskedId) != 32) {
throw new GraphQlInputException(__('Cart ID length should to be 32 symbols.'));
}

if ($this->isQuoteWithSuchMaskedIdAlreadyExists($maskedId)) {
throw new GraphQlAlreadyExistsException(__('Cart with ID "%1" already exists.', $maskedId));
}
}

/**
* Check is quote with such maskedId already exists
*
* @param string $maskedId
* @return bool
*/
private function isQuoteWithSuchMaskedIdAlreadyExists(string $maskedId): bool
{
try {
$this->maskedQuoteIdToQuoteId->execute($maskedId);
return true;
} catch (NoSuchEntityException $e) {
return false;
}
}
}
102 changes: 102 additions & 0 deletions app/code/Magento/QuoteGraphQl/Model/Resolver/CreateGuestCart.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/************************************************************************
*
* Copyright 2023 Adobe
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Adobe and its suppliers, if any. The intellectual
* and technical concepts contained herein are proprietary to Adobe
* and its suppliers and are protected by all applicable intellectual
* property laws, including trade secret and copyright laws.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe.
* ************************************************************************
*/
declare(strict_types=1);

namespace Magento\QuoteGraphQl\Model\Resolver;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Exception\GraphQlAlreadyExistsException;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface;
use Magento\QuoteGraphQl\Model\Cart\CreateEmptyCartForGuest;
use Magento\QuoteGraphQl\Model\Cart\ValidateMaskedQuoteId;

/**
* Creates a guest cart
*/
class CreateGuestCart implements ResolverInterface
{
/**
* @var CreateEmptyCartForGuest
*/
private CreateEmptyCartForGuest $createEmptyCartForGuest;

/**
* @var MaskedQuoteIdToQuoteIdInterface
*/
private MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId;

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

/**
* @var ValidateMaskedQuoteId
*/
private ValidateMaskedQuoteId $validateMaskedQuoteId;

/**
* @param CreateEmptyCartForGuest $createEmptyCartForGuest
* @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId
* @param CartRepositoryInterface $cartRepository
* @param ValidateMaskedQuoteId $validateMaskedQuoteId
*/
public function __construct(
CreateEmptyCartForGuest $createEmptyCartForGuest,
MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId,
CartRepositoryInterface $cartRepository,
ValidateMaskedQuoteId $validateMaskedQuoteId
) {
$this->createEmptyCartForGuest = $createEmptyCartForGuest;
$this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId;
$this->cartRepository = $cartRepository;
$this->validateMaskedQuoteId = $validateMaskedQuoteId;
}

/**
* @inheritdoc
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
$customerId = $context->getUserId();

$predefinedMaskedQuoteId = null;
if (isset($args['input']['cart_uid'])) {
$predefinedMaskedQuoteId = $args['input']['cart_uid'];
$this->validateMaskedQuoteId->execute($predefinedMaskedQuoteId);
}

if ($customerId === 0 || $customerId === null) {
$maskedQuoteId = $this->createEmptyCartForGuest->execute($predefinedMaskedQuoteId);
$cartId = $this->maskedQuoteIdToQuoteId->execute($maskedQuoteId);
$cart = $this->cartRepository->get($cartId);
} else {
throw new GraphQlAlreadyExistsException(
__('Use `Query.customerCart` for logged in customer.')
);
}

return [
'cart' => [
'model' => $cart,
],
];
}
}
11 changes: 10 additions & 1 deletion app/code/Magento/QuoteGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ type Query {
}

type Mutation {
createEmptyCart(input: createEmptyCartInput @doc(description: "An optional input object that assigns the specified ID to the cart.")): String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Create an empty shopping cart for a guest or logged in user")
createGuestCart(input: CreateGuestCartInput): CreateGuestCartOutput @doc(description: "Create a new shopping cart") @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateGuestCart")
createEmptyCart(input: createEmptyCartInput @doc(description: "An optional input object that assigns the specified ID to the cart.")): String @deprecated(reason: "Use `Mutation.createGuestCart` or `Query.customerCart` for logged in customer") @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Create an empty shopping cart for a guest or logged in user")
addSimpleProductsToCart(input: AddSimpleProductsToCartInput @doc(description: "An input object that defines which simple products to add to the cart.")): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") @doc(description:"Add one or more simple products to the specified cart. We recommend using `addProductsToCart` instead.")
addVirtualProductsToCart(input: AddVirtualProductsToCartInput @doc(description: "An input object that defines which virtual products to add to the cart.")): AddVirtualProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") @doc(description:"Add one or more virtual products to the specified cart. We recommend using `addProductsToCart` instead.")
applyCouponToCart(input: ApplyCouponToCartInput @doc(description: "An input object that defines the coupon code to apply to the cart.")): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart") @doc(description:"Apply a pre-defined coupon code to the specified cart.")
Expand All @@ -29,6 +30,10 @@ type Mutation {
addProductsToCart(cartId: String! @doc(description: "The cart ID of the shopper."), cartItems: [CartItemInput!]! @doc(description: "An array that defines the products to add to the cart.")): AddProductsToCartOutput @doc(description:"Add any type of product to the cart.") @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddProductsToCart")
}

input CreateGuestCartInput {
cart_uid: ID @doc(description: "Optional client-generated ID")
}

input createEmptyCartInput @doc(description: "Assigns a specific `cart_id` to the empty cart.") {
cart_id: String @doc(description: "The ID to assign to the cart.")
}
Expand Down Expand Up @@ -186,6 +191,10 @@ type CartDiscount @doc(description: "Contains information about discounts applie
label: [String!]! @doc(description: "The description of the discount.")
}

type CreateGuestCartOutput {
cart: Cart @doc(description: "The newly created cart.")
}

type SetPaymentMethodOnCartOutput @doc(description: "Contains details about the cart after setting the payment method.") {
cart: Cart! @doc(description: "The cart after setting the payment method.")
}
Expand Down
Loading

0 comments on commit 94f014f

Please sign in to comment.