From eea5cdd39cbd5f54c0660a696e27aecc8ba09d6c Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Fri, 7 Sep 2018 14:47:13 +0300 Subject: [PATCH 01/20] #141 Added add simple product to cart mutation to quote-graphql module --- .../Model/Product/Option/DateType.php | 59 +++++ .../Model/Hydrator/CartHydrator.php | 47 ++++ .../Resolver/Cart/AddSimpleProductsToCart.php | 226 +++++++++++++++++ .../Resolver/CartItem/CustomizableOptions.php | 235 ++++++++++++++++++ .../Model/Resolver/CartItemTypeResolver.php | 55 ++++ .../CartItemTypeResolverComposite.php | 55 ++++ .../Magento/QuoteGraphQl/etc/graphql/di.xml | 16 ++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 38 ++- 8 files changed, 730 insertions(+), 1 deletion(-) create mode 100644 app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php create mode 100644 app/code/Magento/QuoteGraphQl/etc/graphql/di.xml diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php new file mode 100644 index 000000000000..8733b9a6b1d0 --- /dev/null +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -0,0 +1,59 @@ +_dateExists() || $this->_timeExists()) { + return parent::validateUserValue($this->formatValues($values)); + } + + return $this; + } + + /** + * @param array $values + * @return array mixed + */ + 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; + } + + /** + * @return bool + */ + public function useCalendar() + { + return false; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php new file mode 100644 index 000000000000..5f386134bcc9 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php @@ -0,0 +1,47 @@ +getAllItems() as $cartItem) { + $productData = $cartItem->getProduct()->getData(); + $productData['model'] = $cartItem->getProduct(); + + $items[] = [ + 'id' => $cartItem->getItemId(), + 'qty' => $cartItem->getQty(), + 'product' => $productData, + 'model' => $cartItem, + ]; + } + + return [ + 'items' => $items, + ]; + } +} \ No newline at end of file diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php new file mode 100644 index 000000000000..49bbcb1e4372 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -0,0 +1,226 @@ +valueFactory = $valueFactory; + $this->userContext = $userContext; + $this->arrayManager = $arrayManager; + $this->productRepository = $productRepository; + $this->cartHydrator = $cartHydrator; + $this->guestCartRepository = $guestCartRepository; + $this->dataObjectFactory = $dataObjectFactory; + $this->cartRepository = $cartRepository; + $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; + } + + /** + * {@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 $cartItem) { + $sku = $this->arrayManager->get('details/sku', $cartItem); + $product = $this->productRepository->get($sku); + + $message = $cart->addProduct($product, $this->getBuyRequest($cartItem)); + + 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); + } + + /** + * Format GraphQl input data to a shape that buy request has + * + * @param array $cartItem + * @return DataObject + */ + private function getBuyRequest($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 + ] + ]); + } + + /** + * 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 + { + $customerId = $this->userContext->getUserId(); + + if (!$customerId) { + return $this->guestCartRepository->get($cartHash); + } + + $cartId = $this->maskedQuoteIdToQuoteId->execute((string) $cartHash); + return $this->cartRepository->get($cartId); + } +} \ No newline at end of file diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php new file mode 100644 index 000000000000..871d152faa86 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php @@ -0,0 +1,235 @@ +valueFactory = $valueFactory; + $this->userContext = $userContext; + $this->storeManager = $storeManager; + } + + /** + * {@inheritDoc} + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) : Value + { + if (!isset($value['model'])) { + return $this->valueFactory->create(function () { + return []; + }); + } + + /** @var QuoteItem $cartItem */ + $cartItem = $value['model']; + $optionIds = $cartItem->getOptionByCode('option_ids'); + + if (!$optionIds) { + return $this->valueFactory->create(function () { + return []; + }); + } + + $customOptions = []; + $customOptionIds = explode(',', $optionIds->getValue()); + + foreach ($customOptionIds as $optionId) { + $customOptionData = $this->getOptionData($cartItem, (int) $optionId); + + if (0 === count($customOptionData)) { + continue; + } + + $customOptions[] = $customOptionData; + } + + $result = function () use ($customOptions) { + return $customOptions; + }; + + return $this->valueFactory->create($result); + } + + /** + * @param QuoteItem $cartItem + * @param int $optionId + * @return array + * @throws NoSuchEntityException + * @throws LocalizedException + */ + private function getOptionData($cartItem, int $optionId): array + { + $product = $cartItem->getProduct(); + $option = $product->getOptionById($optionId); + + if (!$option) { + return []; + } + + $itemOption = $cartItem->getOptionByCode('option_' . $option->getId()); + + /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeGroup */ + $optionTypeGroup = $option->groupFactory($option->getType()) + ->setOption($option) + ->setConfigurationItem($cartItem) + ->setConfigurationItemOption($itemOption); + + if (ProductCustomOptionInterface::OPTION_GROUP_FILE == $option->getType()) { + $downloadParams = $cartItem->getFileDownloadParams(); + + if ($downloadParams) { + $url = $downloadParams->getUrl(); + if ($url) { + $optionTypeGroup->setCustomOptionDownloadUrl($url); + } + $urlParams = $downloadParams->getUrlParams(); + if ($urlParams) { + $optionTypeGroup->setCustomOptionUrlParams($urlParams); + } + } + } + + $selectedOptionValueData = [ + 'id' => $itemOption->getId(), + 'label' => $optionTypeGroup->getFormattedOptionValue($itemOption->getValue()), + ]; + + if (ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_RADIO == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX == $option->getType() + ) { + $optionValue = $option->getValueById($itemOption->getValue()); + $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); + + $selectedOptionValueData['price'] = [ + 'type' => strtoupper($optionValue->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ]; + + $selectedOptionValueData = [$selectedOptionValueData]; + } + + if (ProductCustomOptionInterface::OPTION_TYPE_FIELD == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_AREA == $option->getType() + || ProductCustomOptionInterface::OPTION_GROUP_DATE == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_TIME == $option->getType() + ) { + $priceValueUnits = $this->getPriceValueUnits($option->getPriceType()); + + $selectedOptionValueData['price'] = [ + 'type' => strtoupper($option->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $option->getPrice(), + ]; + + $selectedOptionValueData = [$selectedOptionValueData]; + } + + if (ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE == $option->getType()) { + $selectedOptionValueData = []; + $optionIds = explode(',', $itemOption->getValue()); + + foreach ($optionIds as $optionId) { + $optionValue = $option->getValueById($optionId); + $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); + + $selectedOptionValueData[] = [ + 'id' => $itemOption->getId(), + 'label' => $optionValue->getTitle(), + 'price' => [ + 'type' => strtoupper($optionValue->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ], + ]; + } + } + + return [ + 'id' => $option->getId(), + 'label' => $option->getTitle(), + 'type' => $option->getType(), + 'values' => $selectedOptionValueData, + 'sort_order' => $option->getSortOrder(), + ]; + } + + /** + * @param string $priceType + * @return string + * @throws NoSuchEntityException + */ + private function getPriceValueUnits(string $priceType): string + { + if (ProductPriceOptionsInterface::VALUE_PERCENT == $priceType) { + return '%'; + } + + return $this->getCurrencySymbol(); + } + + /** + * Get currency symbol + * @return string + * @throws NoSuchEntityException + */ + private function getCurrencySymbol(): string + { + /** @var Store|StoreInterface $store */ + $store = $this->storeManager->getStore(); + + return $store->getBaseCurrency()->getCurrencySymbol(); + } +} \ No newline at end of file diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php new file mode 100644 index 000000000000..75232190b736 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -0,0 +1,55 @@ +cartItemTypes = $cartItemTypes; + } + + /** + * {@inheritdoc} + * @throws GraphQlInputException + */ + public function resolveType(array $data) : string + { + if (!isset($data['product'])) { + return ''; + } + + $productData = $data['product']; + + if (!isset($productData['type_id'])) { + return ''; + } + + $productTypeId = $productData['type_id']; + + if (!isset($this->cartItemTypes[$productTypeId])) { + return ''; + } + + return $this->cartItemTypes[$productTypeId]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php new file mode 100644 index 000000000000..264887a66f62 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php @@ -0,0 +1,55 @@ +cartItemTypeResolvers = $cartItemTypeResolvers; + } + + /** + * {@inheritdoc} + * @throws GraphQlInputException + */ + public function resolveType(array $data) : string + { + if (!isset($data['product'])) { + throw new GraphQlInputException( + __('Missing key %1 in cart data', ['product']) + ); + } + + foreach ($this->cartItemTypeResolvers as $cartItemTypeResolver) { + $resolvedType = $cartItemTypeResolver->resolveType($data); + + if ($resolvedType) { + return $resolvedType; + } + } + + throw new GraphQlInputException( + __('Concrete type for %1 not implemented', ['CartItemInterface']) + ); + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml new file mode 100644 index 000000000000..0a13f1ba3455 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -0,0 +1,16 @@ + + + + + + + Magento\QuoteGraphQl\Model\Resolver\CartItemTypeResolver + + + + diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 46d1b97d0aea..8ee32e493c0d 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -2,5 +2,41 @@ # See COPYING.txt for license details. type Mutation { - createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user") + createEmptyCart: String @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user") } + +type Cart { + items: [CartItemInterface] +} + +input CartItemDetailsInput { + sku: String! + qty: Float! +} + +interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItemTypeResolverComposite") { + id: String! + qty: Float! + product: ProductInterface! +} + +type SelectedCustomizableOption { + id: Int! + label: String! + type: String! + values: [SelectedCustomizableOptionValue!]! + sort_order: Int! +} + +type SelectedCustomizableOptionValue { + id: Int + label: String! + price: CartItemSelectedOptionValuePrice! + sort_order: Int! +} + +type CartItemSelectedOptionValuePrice { + value: Float! + units: String! + type: PriceTypeEnum! +} \ No newline at end of file From 50a928c4c4192c8f85be46bbaaed14be7e7f0170 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Fri, 7 Sep 2018 14:56:13 +0300 Subject: [PATCH 02/20] #141 Added required configurations --- .../Magento/QuoteGraphQl/etc/graphql/di.xml | 7 ++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 24 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index 0a13f1ba3455..8f29b2559a7a 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -13,4 +13,11 @@ + + + + SimpleCartItem + + + diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 8ee32e493c0d..ab849ba56916 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -3,6 +3,30 @@ type Mutation { createEmptyCart: String @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user") + addSimpleProductsToCart(input: AddSimpleProductsToCartInput): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\AddSimpleProductsToCart") +} + +input AddSimpleProductsToCartInput { + cart_id: String! + cartItems: [SimpleProductCartItemInput!]! +} + +input SimpleProductCartItemInput { + details: CartItemDetailsInput! + customizable_options:[CustomizableOptionInput!] +} + +input CustomizableOptionInput { + id: Int! + value: String! +} + +type AddSimpleProductsToCartOutput { + cart: Cart! +} + +type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") { + customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItem\\CustomizableOptions") } type Cart { From 5105989b698c0fce1dec27b003225f9006b7a1c5 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Fri, 7 Sep 2018 16:32:22 +0300 Subject: [PATCH 03/20] #141 Added hard dependencies --- app/code/Magento/QuoteGraphQl/composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index 76ecfac373ef..9995e292e784 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -6,7 +6,9 @@ "php": "~7.1.3||~7.2.0", "magento/framework": "*", "magento/module-authorization": "*", - "magento/module-quote": "*" + "magento/module-quote": "*", + "magento/module-catalog": "*", + "magento/module-store": "*" }, "suggest": { "magento/module-graph-ql": "*", From 1734dfca837e8031940f834e732543bb3ee350ac Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Fri, 7 Sep 2018 16:37:09 +0300 Subject: [PATCH 04/20] #141 Fixed issues from Travis --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 1 + app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php | 2 +- .../Model/Resolver/Cart/AddSimpleProductsToCart.php | 2 +- .../Model/Resolver/CartItem/CustomizableOptions.php | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index 8733b9a6b1d0..f3f74867128f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\CatalogGraphQl\Model\Product\Option; diff --git a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php index 5f386134bcc9..6dec37909886 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php +++ b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php @@ -44,4 +44,4 @@ public function hydrate(CartInterface $cart): array 'items' => $items, ]; } -} \ No newline at end of file +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php index 49bbcb1e4372..cc44b1071b39 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -223,4 +223,4 @@ private function getCart(string $cartHash): CartInterface $cartId = $this->maskedQuoteIdToQuoteId->execute((string) $cartHash); return $this->cartRepository->get($cartId); } -} \ No newline at end of file +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php index 871d152faa86..67318be917c8 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php @@ -232,4 +232,4 @@ private function getCurrencySymbol(): string return $store->getBaseCurrency()->getCurrencySymbol(); } -} \ No newline at end of file +} From 7e7e82cd4e7cb59880ca079e5aa09434805a5dca Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Fri, 7 Sep 2018 18:34:15 +0300 Subject: [PATCH 05/20] #141 Running tests again --- app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php index 6dec37909886..1f3852aaf1e6 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php +++ b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php @@ -18,7 +18,6 @@ class CartHydrator { /** * @param CartInterface|Quote $cart - * * @return array */ public function hydrate(CartInterface $cart): array From 01404a02c0102e3dee9d649aa6baa46bc9e2d4a8 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Mon, 17 Sep 2018 22:31:23 +0300 Subject: [PATCH 06/20] #141 Added descriptions to classes and methods --- .../Model/Product/Option/DateType.php | 13 +++++++++++-- .../QuoteGraphQl/Model/Hydrator/CartHydrator.php | 5 +++++ .../Model/Resolver/Cart/AddSimpleProductsToCart.php | 5 ++++- .../Model/Resolver/CartItemTypeResolver.php | 4 ++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index f3f74867128f..364df839479c 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -8,6 +8,7 @@ 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; /** @@ -16,6 +17,8 @@ class DateType extends ProductDateOptionType { /** + * Make valid string as a value of date option type for GraphQl queries + * * {@inheritdoc} */ public function validateUserValue($values) @@ -28,8 +31,12 @@ public function validateUserValue($values) } /** - * @param array $values - * @return array mixed + * Format date value from string to date array + * + * @param [] $values + * + * @return [] + * @throws LocalizedException */ protected function formatValues($values) { @@ -51,6 +58,8 @@ protected function formatValues($values) } /** + * Check if calendar should be shown + * * @return bool */ public function useCalendar() diff --git a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php index 1f3852aaf1e6..55ad50f9ca5d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php +++ b/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php @@ -12,12 +12,17 @@ use Magento\Quote\Model\Quote\Item as QuoteItem; /** + * Cart Hydrator class + * * {@inheritdoc} */ class CartHydrator { /** + * Hydrate cart to plain array + * * @param CartInterface|Quote $cart + * * @return array */ public function hydrate(CartInterface $cart): array diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php index cc44b1071b39..d7d495667576 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -11,7 +11,6 @@ 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\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; @@ -29,6 +28,8 @@ use Magento\QuoteGraphQl\Model\Hydrator\CartHydrator; /** + * Add simple product to cart GraphQl resolver + * * {@inheritdoc} */ class AddSimpleProductsToCart implements ResolverInterface @@ -112,6 +113,8 @@ public function __construct( } /** + * 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 diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php index 75232190b736..583ef6e33c6d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -11,6 +11,8 @@ use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface; /** + * Resolver for cart item types that vary by product types + * * {@inheritdoc} */ class CartItemTypeResolver implements TypeResolverInterface @@ -29,6 +31,8 @@ public function __construct(array $cartItemTypes = []) } /** + * Resolve GraphQl types to retrieve product type specific information about cart items + * * {@inheritdoc} * @throws GraphQlInputException */ From 10648548d66c0dc0696fcad2af0ec21db8269e05 Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Tue, 18 Sep 2018 22:07:02 +0300 Subject: [PATCH 07/20] #141 Performed decoupling of the resolvers --- .../Model/Product/Option/DateType.php | 8 +- .../Cart/AddSimpleProductToCartProcessor.php | 120 ++++++++++++ .../Resolver/Cart/AddSimpleProductsToCart.php | 67 ++----- .../Resolver/CartItem/CustomizableOptions.php | 155 +--------------- .../DataProvider/Cart}/CartHydrator.php | 6 +- .../CartItem/CustomizableOption.php | 174 ++++++++++++++++++ 6 files changed, 318 insertions(+), 212 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php rename app/code/Magento/QuoteGraphQl/Model/{Hydrator => Resolver/DataProvider/Cart}/CartHydrator.php (92%) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index 364df839479c..d9308cf606e1 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -13,12 +13,12 @@ /** * 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) @@ -32,9 +32,7 @@ public function validateUserValue($values) /** * Format date value from string to date array - * * @param [] $values - * * @return [] * @throws LocalizedException */ @@ -58,9 +56,7 @@ protected function formatValues($values) } /** - * Check if calendar should be shown - * - * @return bool + * @inheritdoc */ public function useCalendar() { diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php new file mode 100644 index 000000000000..ff02f48ef665 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php @@ -0,0 +1,120 @@ +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 + ] + ]); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php index d7d495667576..845ae7591885 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -8,9 +8,6 @@ namespace Magento\QuoteGraphQl\Model\Resolver\Cart; use Magento\Authorization\Model\UserContextInterface; -use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Framework\DataObject; -use Magento\Framework\DataObjectFactory; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Exception\GraphQlInputException; @@ -25,15 +22,20 @@ use Magento\Quote\Api\GuestCartRepositoryInterface; use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Quote\Model\Quote; -use Magento\QuoteGraphQl\Model\Hydrator\CartHydrator; +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 */ @@ -44,21 +46,11 @@ class AddSimpleProductsToCart implements ResolverInterface */ private $maskedQuoteIdToQuoteId; - /** - * @var DataObjectFactory - */ - private $dataObjectFactory; - /** * @var GuestCartRepositoryInterface */ private $guestCartRepository; - /** - * @var ProductRepositoryInterface - */ - private $productRepository; - /** * @var CartHydrator */ @@ -80,42 +72,38 @@ class AddSimpleProductsToCart implements ResolverInterface private $userContext; /** - * @param DataObjectFactory $dataObjectFactory + * @param AddSimpleProductToCartProcessor $addSimpleProductToCartProcessor * @param CartHydrator $cartHydrator * @param ArrayManager $arrayManager * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId * @param CartRepositoryInterface $cartRepository * @param GuestCartRepositoryInterface $guestCartRepository - * @param ProductRepositoryInterface $productRepository * @param ValueFactory $valueFactory * @param UserContextInterface $userContext */ public function __construct( - DataObjectFactory $dataObjectFactory, + AddSimpleProductToCartProcessor $addSimpleProductToCartProcessor, CartHydrator $cartHydrator, ArrayManager $arrayManager, MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, CartRepositoryInterface $cartRepository, GuestCartRepositoryInterface $guestCartRepository, - ProductRepositoryInterface $productRepository, ValueFactory $valueFactory, UserContextInterface $userContext ) { $this->valueFactory = $valueFactory; $this->userContext = $userContext; $this->arrayManager = $arrayManager; - $this->productRepository = $productRepository; $this->cartHydrator = $cartHydrator; $this->guestCartRepository = $guestCartRepository; - $this->dataObjectFactory = $dataObjectFactory; $this->cartRepository = $cartRepository; $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; + $this->addSimpleProductToCartProcessor = $addSimpleProductToCartProcessor; } /** * Resolve adding simple product to cart for customers/guests - * - * {@inheritDoc} + * {@inheritdoc} */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) : Value { @@ -136,11 +124,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $cart = $this->getCart((string) $cartHash); - foreach ($cartItems as $cartItem) { - $sku = $this->arrayManager->get('details/sku', $cartItem); - $product = $this->productRepository->get($sku); + foreach ($cartItems as $cartItemData) { + $sku = $this->arrayManager->get('details/sku', $cartItemData); - $message = $cart->addProduct($product, $this->getBuyRequest($cartItem)); + $message = $this->addSimpleProductToCartProcessor->process($cart, $cartItemData); if (is_string($message)) { throw new GraphQlInputException( @@ -166,33 +153,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return $this->valueFactory->create($result); } - /** - * Format GraphQl input data to a shape that buy request has - * - * @param array $cartItem - * @return DataObject - */ - private function getBuyRequest($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 - ] - ]); - } - /** * Collecting cart errors - * * @param CartInterface|Quote $cart * @return string */ @@ -210,7 +172,6 @@ private function getCartErrors($cart): string /** * Retrieving quote mode based on customer authorization - * * @param string $cartHash * @return CartInterface|Quote * @throws NoSuchEntityException diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php index 67318be917c8..8961fea3acb4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php @@ -8,22 +8,13 @@ namespace Magento\QuoteGraphQl\Model\Resolver\CartItem; use Magento\Authorization\Model\UserContextInterface; -use Magento\Catalog\Api\Data\ProductCustomOptionInterface; -use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; -use Magento\Catalog\Model\Product\Option\Type\DefaultType as DefaultOptionType; -use Magento\Catalog\Model\Product\Option\Type\Select as SelectOptionType; -use Magento\Catalog\Model\Product\Option\Type\Text as TextOptionType; -use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Config\Element\Field; 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\Quote\Model\Quote\Item as QuoteItem; -use Magento\Store\Api\Data\StoreInterface; -use Magento\Store\Model\Store; -use Magento\Store\Model\StoreManagerInterface; +use Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomizableOption as CustomizableOptionDataProvider; /** * {@inheritdoc} @@ -31,9 +22,9 @@ class CustomizableOptions implements ResolverInterface { /** - * @var StoreManagerInterface + * @var CustomizableOptionDataProvider */ - private $storeManager; + private $customOptionDataProvider; /** * @var ValueFactory @@ -48,16 +39,16 @@ class CustomizableOptions implements ResolverInterface /** * @param ValueFactory $valueFactory * @param UserContextInterface $userContext - * @param StoreManagerInterface $storeManager + * @param CustomizableOptionDataProvider $customOptionDataProvider */ public function __construct( ValueFactory $valueFactory, UserContextInterface $userContext, - StoreManagerInterface $storeManager + CustomizableOptionDataProvider $customOptionDataProvider ) { $this->valueFactory = $valueFactory; $this->userContext = $userContext; - $this->storeManager = $storeManager; + $this->customOptionDataProvider = $customOptionDataProvider; } /** @@ -85,7 +76,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value $customOptionIds = explode(',', $optionIds->getValue()); foreach ($customOptionIds as $optionId) { - $customOptionData = $this->getOptionData($cartItem, (int) $optionId); + $customOptionData = $this->customOptionDataProvider->getData($cartItem, (int) $optionId); if (0 === count($customOptionData)) { continue; @@ -100,136 +91,4 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value return $this->valueFactory->create($result); } - - /** - * @param QuoteItem $cartItem - * @param int $optionId - * @return array - * @throws NoSuchEntityException - * @throws LocalizedException - */ - private function getOptionData($cartItem, int $optionId): array - { - $product = $cartItem->getProduct(); - $option = $product->getOptionById($optionId); - - if (!$option) { - return []; - } - - $itemOption = $cartItem->getOptionByCode('option_' . $option->getId()); - - /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeGroup */ - $optionTypeGroup = $option->groupFactory($option->getType()) - ->setOption($option) - ->setConfigurationItem($cartItem) - ->setConfigurationItemOption($itemOption); - - if (ProductCustomOptionInterface::OPTION_GROUP_FILE == $option->getType()) { - $downloadParams = $cartItem->getFileDownloadParams(); - - if ($downloadParams) { - $url = $downloadParams->getUrl(); - if ($url) { - $optionTypeGroup->setCustomOptionDownloadUrl($url); - } - $urlParams = $downloadParams->getUrlParams(); - if ($urlParams) { - $optionTypeGroup->setCustomOptionUrlParams($urlParams); - } - } - } - - $selectedOptionValueData = [ - 'id' => $itemOption->getId(), - 'label' => $optionTypeGroup->getFormattedOptionValue($itemOption->getValue()), - ]; - - if (ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_RADIO == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX == $option->getType() - ) { - $optionValue = $option->getValueById($itemOption->getValue()); - $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); - - $selectedOptionValueData['price'] = [ - 'type' => strtoupper($optionValue->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $optionValue->getPrice(), - ]; - - $selectedOptionValueData = [$selectedOptionValueData]; - } - - if (ProductCustomOptionInterface::OPTION_TYPE_FIELD == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_AREA == $option->getType() - || ProductCustomOptionInterface::OPTION_GROUP_DATE == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_TIME == $option->getType() - ) { - $priceValueUnits = $this->getPriceValueUnits($option->getPriceType()); - - $selectedOptionValueData['price'] = [ - 'type' => strtoupper($option->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $option->getPrice(), - ]; - - $selectedOptionValueData = [$selectedOptionValueData]; - } - - if (ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE == $option->getType()) { - $selectedOptionValueData = []; - $optionIds = explode(',', $itemOption->getValue()); - - foreach ($optionIds as $optionId) { - $optionValue = $option->getValueById($optionId); - $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); - - $selectedOptionValueData[] = [ - 'id' => $itemOption->getId(), - 'label' => $optionValue->getTitle(), - 'price' => [ - 'type' => strtoupper($optionValue->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $optionValue->getPrice(), - ], - ]; - } - } - - return [ - 'id' => $option->getId(), - 'label' => $option->getTitle(), - 'type' => $option->getType(), - 'values' => $selectedOptionValueData, - 'sort_order' => $option->getSortOrder(), - ]; - } - - /** - * @param string $priceType - * @return string - * @throws NoSuchEntityException - */ - private function getPriceValueUnits(string $priceType): string - { - if (ProductPriceOptionsInterface::VALUE_PERCENT == $priceType) { - return '%'; - } - - return $this->getCurrencySymbol(); - } - - /** - * Get currency symbol - * @return string - * @throws NoSuchEntityException - */ - private function getCurrencySymbol(): string - { - /** @var Store|StoreInterface $store */ - $store = $this->storeManager->getStore(); - - return $store->getBaseCurrency()->getCurrencySymbol(); - } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php similarity index 92% rename from app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php index 55ad50f9ca5d..6a0a5f26aa33 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Hydrator/CartHydrator.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Hydrator; +namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\Cart; use Magento\Quote\Api\Data\CartInterface; use Magento\Quote\Model\Quote; @@ -13,16 +13,12 @@ /** * Cart Hydrator class - * - * {@inheritdoc} */ class CartHydrator { /** * Hydrate cart to plain array - * * @param CartInterface|Quote $cart - * * @return array */ public function hydrate(CartInterface $cart): array diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php new file mode 100644 index 000000000000..0ea2cbb25d9d --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php @@ -0,0 +1,174 @@ +storeManager = $storeManager; + } + + /** + * Retrieve custom option data + * @param QuoteItem $cartItem + * @param int $optionId + * @return array + * @throws NoSuchEntityException + * @throws LocalizedException + */ + public function getData(QuoteItem $cartItem, int $optionId): array + { + $product = $cartItem->getProduct(); + $option = $product->getOptionById($optionId); + + if (!$option) { + return []; + } + + $itemOption = $cartItem->getOptionByCode('option_' . $option->getId()); + + /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeGroup */ + $optionTypeGroup = $option->groupFactory($option->getType()) + ->setOption($option) + ->setConfigurationItem($cartItem) + ->setConfigurationItemOption($itemOption); + + if (ProductCustomOptionInterface::OPTION_GROUP_FILE == $option->getType()) { + $downloadParams = $cartItem->getFileDownloadParams(); + + if ($downloadParams) { + $url = $downloadParams->getUrl(); + if ($url) { + $optionTypeGroup->setCustomOptionDownloadUrl($url); + } + $urlParams = $downloadParams->getUrlParams(); + if ($urlParams) { + $optionTypeGroup->setCustomOptionUrlParams($urlParams); + } + } + } + + $selectedOptionValueData = [ + 'id' => $itemOption->getId(), + 'label' => $optionTypeGroup->getFormattedOptionValue($itemOption->getValue()), + ]; + + if (ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_RADIO == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX == $option->getType() + ) { + $optionValue = $option->getValueById($itemOption->getValue()); + $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); + + $selectedOptionValueData['price'] = [ + 'type' => strtoupper($optionValue->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ]; + + $selectedOptionValueData = [$selectedOptionValueData]; + } + + if (ProductCustomOptionInterface::OPTION_TYPE_FIELD == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_AREA == $option->getType() + || ProductCustomOptionInterface::OPTION_GROUP_DATE == $option->getType() + || ProductCustomOptionInterface::OPTION_TYPE_TIME == $option->getType() + ) { + $priceValueUnits = $this->getPriceValueUnits($option->getPriceType()); + + $selectedOptionValueData['price'] = [ + 'type' => strtoupper($option->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $option->getPrice(), + ]; + + $selectedOptionValueData = [$selectedOptionValueData]; + } + + if (ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE == $option->getType()) { + $selectedOptionValueData = []; + $optionIds = explode(',', $itemOption->getValue()); + + foreach ($optionIds as $optionId) { + $optionValue = $option->getValueById($optionId); + $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); + + $selectedOptionValueData[] = [ + 'id' => $itemOption->getId(), + 'label' => $optionValue->getTitle(), + 'price' => [ + 'type' => strtoupper($optionValue->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ], + ]; + } + } + + return [ + 'id' => $option->getId(), + 'label' => $option->getTitle(), + 'type' => $option->getType(), + 'values' => $selectedOptionValueData, + 'sort_order' => $option->getSortOrder(), + ]; + } + + /** + * Retrieve price value unit + * @param string $priceType + * @return string + * @throws NoSuchEntityException + */ + private function getPriceValueUnits(string $priceType): string + { + if (ProductPriceOptionsInterface::VALUE_PERCENT == $priceType) { + return '%'; + } + + return $this->getCurrencySymbol(); + } + + /** + * Get currency symbol + * @return string + * @throws NoSuchEntityException + */ + private function getCurrencySymbol(): string + { + /** @var Store|StoreInterface $store */ + $store = $this->storeManager->getStore(); + + return $store->getBaseCurrency()->getCurrencySymbol(); + } +} From 34e010632ada4fbc6d22a302e8f5a390c37a282c Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Wed, 19 Sep 2018 22:22:15 +0300 Subject: [PATCH 08/20] #141 Added missed lines in phpdocs --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 1 + .../Model/Cart/AddSimpleProductToCartProcessor.php | 2 ++ .../Model/Resolver/Cart/AddSimpleProductsToCart.php | 2 ++ .../QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php | 2 +- .../Model/Resolver/CartItemTypeResolverComposite.php | 1 + .../Resolver/DataProvider/CartItem/CustomizableOption.php | 3 +++ 6 files changed, 10 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index d9308cf606e1..db03b1712612 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -32,6 +32,7 @@ public function validateUserValue($values) /** * Format date value from string to date array + * * @param [] $values * @return [] * @throws LocalizedException diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php index ff02f48ef665..3b6e1801c5f1 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php @@ -81,6 +81,7 @@ public function __construct( /** * Resolve adding simple product to cart for customers/guests + * * @param CartInterface|Quote $cart * @param array $cartItemData * @return QuoteItem|string @@ -97,6 +98,7 @@ public function process($cart, array $cartItemData) /** * Format GraphQl input data to a shape that buy request has + * * @param array $cartItem * @return DataObject */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php index 845ae7591885..d5b0b862d23d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -155,6 +155,7 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value /** * Collecting cart errors + * * @param CartInterface|Quote $cart * @return string */ @@ -172,6 +173,7 @@ private function getCartErrors($cart): string /** * Retrieving quote mode based on customer authorization + * * @param string $cartHash * @return CartInterface|Quote * @throws NoSuchEntityException diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php index 583ef6e33c6d..b8b197b45039 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -32,8 +32,8 @@ public function __construct(array $cartItemTypes = []) /** * Resolve GraphQl types to retrieve product type specific information about cart items - * * {@inheritdoc} + * * @throws GraphQlInputException */ public function resolveType(array $data) : string diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php index 264887a66f62..901f177ced98 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php @@ -30,6 +30,7 @@ public function __construct(array $cartItemTypeResolvers = []) /** * {@inheritdoc} + * * @throws GraphQlInputException */ public function resolveType(array $data) : string diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php index 0ea2cbb25d9d..909867c0457d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php @@ -40,6 +40,7 @@ public function __construct( /** * Retrieve custom option data + * * @param QuoteItem $cartItem * @param int $optionId * @return array @@ -146,6 +147,7 @@ public function getData(QuoteItem $cartItem, int $optionId): array /** * Retrieve price value unit + * * @param string $priceType * @return string * @throws NoSuchEntityException @@ -161,6 +163,7 @@ private function getPriceValueUnits(string $priceType): string /** * Get currency symbol + * * @return string * @throws NoSuchEntityException */ From e8011a8d05c77f9586c12a94ad63b057aee4204e Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Wed, 19 Sep 2018 23:40:57 +0300 Subject: [PATCH 09/20] #141 Removed redundant dependency --- .../Resolver/Cart/AddSimpleProductsToCart.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php index d5b0b862d23d..80aa42b4365d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php @@ -19,7 +19,6 @@ 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\QuoteGraphQl\Model\Cart\AddSimpleProductToCartProcessor; @@ -46,11 +45,6 @@ class AddSimpleProductsToCart implements ResolverInterface */ private $maskedQuoteIdToQuoteId; - /** - * @var GuestCartRepositoryInterface - */ - private $guestCartRepository; - /** * @var CartHydrator */ @@ -77,7 +71,6 @@ class AddSimpleProductsToCart implements ResolverInterface * @param ArrayManager $arrayManager * @param MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId * @param CartRepositoryInterface $cartRepository - * @param GuestCartRepositoryInterface $guestCartRepository * @param ValueFactory $valueFactory * @param UserContextInterface $userContext */ @@ -87,7 +80,6 @@ public function __construct( ArrayManager $arrayManager, MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, CartRepositoryInterface $cartRepository, - GuestCartRepositoryInterface $guestCartRepository, ValueFactory $valueFactory, UserContextInterface $userContext ) { @@ -95,7 +87,6 @@ public function __construct( $this->userContext = $userContext; $this->arrayManager = $arrayManager; $this->cartHydrator = $cartHydrator; - $this->guestCartRepository = $guestCartRepository; $this->cartRepository = $cartRepository; $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; $this->addSimpleProductToCartProcessor = $addSimpleProductToCartProcessor; @@ -180,13 +171,8 @@ private function getCartErrors($cart): string */ private function getCart(string $cartHash): CartInterface { - $customerId = $this->userContext->getUserId(); - - if (!$customerId) { - return $this->guestCartRepository->get($cartHash); - } - $cartId = $this->maskedQuoteIdToQuoteId->execute((string) $cartHash); + return $this->cartRepository->get($cartId); } } From 436dee71b71162e70d5166c3c39cbc561247222d Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Thu, 20 Sep 2018 21:10:17 +0300 Subject: [PATCH 10/20] #141 Restored config after patching the branch --- app/code/Magento/CatalogGraphQl/etc/graphql/di.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml index 68a292ede6b4..7e18ac34f0fc 100644 --- a/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/CatalogGraphQl/etc/graphql/di.xml @@ -6,6 +6,7 @@ */ --> + From 4942c6f202b097256c31fd8c32959a8867ae459a Mon Sep 17 00:00:00 2001 From: Roman Glushko Date: Thu, 20 Sep 2018 21:11:08 +0300 Subject: [PATCH 11/20] #141 Decoupling the CustomOption data provider --- .../CartItemTypeResolverComposite.php | 2 +- .../CartItem/CustomOptionPriceUnitLabel.php | 64 +++++++++ .../CustomOptionValueInterface.php | 35 +++++ .../DropdownCustomOptionValue.php | 64 +++++++++ .../MultipleCustomOptionValue.php | 71 +++++++++ .../TextCustomOptionValue.php | 61 ++++++++ .../CartItem/CustomOptionValueComposite.php | 68 +++++++++ .../CartItem/CustomizableOption.php | 136 ++---------------- app/code/Magento/QuoteGraphQl/etc/di.xml | 24 ++++ 9 files changed, 401 insertions(+), 124 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/DropdownCustomOptionValue.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php create mode 100644 app/code/Magento/QuoteGraphQl/etc/di.xml diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php index 901f177ced98..5af521756204 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php @@ -30,7 +30,7 @@ public function __construct(array $cartItemTypeResolvers = []) /** * {@inheritdoc} - * + * * @throws GraphQlInputException */ public function resolveType(array $data) : string diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php new file mode 100644 index 000000000000..f80b2994cc87 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php @@ -0,0 +1,64 @@ +storeManager = $storeManager; + } + + /** + * Retrieve price value unit + * + * @param string $priceType + * @return string + * @throws NoSuchEntityException + */ + public function getData(string $priceType): string + { + if (ProductPriceOptionsInterface::VALUE_PERCENT == $priceType) { + return '%'; + } + + return $this->getCurrencySymbol(); + } + + /** + * Get currency symbol + * + * @return string + * @throws NoSuchEntityException + */ + private function getCurrencySymbol(): string + { + /** @var Store|StoreInterface $store */ + $store = $this->storeManager->getStore(); + + return $store->getBaseCurrency()->getCurrencySymbol(); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php new file mode 100644 index 000000000000..700362ceea0e --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php @@ -0,0 +1,35 @@ +customOptionPriceUnitLabel = $customOptionPriceUnitLabel; + } + + /** + * {@inheritdoc} + * + * @throws NoSuchEntityException + */ + public function getData( + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption, + DefaultOptionType $optionTypeRenderer + ): array { + $selectedValue = $selectedOption->getValue(); + $optionValue = $option->getValueById($selectedValue); + $optionPriceType = (string) $optionValue->getPriceType(); + $priceValueUnits = $this->customOptionPriceUnitLabel->getData($optionPriceType); + + $selectedOptionValueData = [ + 'id' => $selectedOption->getId(), + 'label' => $optionTypeRenderer->getFormattedOptionValue($selectedValue), + 'price' => [ + 'type' => strtoupper($optionPriceType), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ] + ]; + + return [$selectedOptionValueData]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php new file mode 100644 index 000000000000..87ee56f56100 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php @@ -0,0 +1,71 @@ +customOptionPriceUnitLabel = $customOptionPriceUnitLabel; + } + + /** + * {@inheritdoc} + * + * @throws NoSuchEntityException + */ + public function getData( + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption, + DefaultType $optionTypeRenderer + ): array { + $selectedOptionValueData = []; + $optionIds = explode(',', $selectedOption->getValue()); + + if (0 === count($optionIds)) { + return $selectedOptionValueData; + } + + foreach ($optionIds as $optionId) { + $optionValue = $option->getValueById($optionId); + $priceValueUnits = $this->customOptionPriceUnitLabel->getData($optionValue->getPriceType()); + + $selectedOptionValueData[] = [ + 'id' => $selectedOption->getId(), + 'label' => $optionValue->getTitle(), + 'price' => [ + 'type' => strtoupper($optionValue->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $optionValue->getPrice(), + ], + ]; + } + + return $selectedOptionValueData; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php new file mode 100644 index 000000000000..78657603ff3e --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php @@ -0,0 +1,61 @@ +customOptionPriceUnitLabel = $customOptionPriceUnitLabel; + } + + /** + * {@inheritdoc} + * + * @throws NoSuchEntityException + */ + public function getData( + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption, + DefaultType $optionTypeRenderer + ): array { + $priceValueUnits = $this->customOptionPriceUnitLabel->getData($option->getPriceType()); + + $selectedOptionValueData = [ + 'id' => $selectedOption->getId(), + 'label' => $optionTypeRenderer->getFormattedOptionValue($selectedOption->getValue()), + 'price' => [ + 'type' => strtoupper($option->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $option->getPrice(), + ] + ]; + + return [$selectedOptionValueData]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php new file mode 100644 index 000000000000..4234753d1163 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php @@ -0,0 +1,68 @@ +customOptionValueTypeProviders = $customOptionValueTypeProviders; + } + + /** + * Retrieve custom option values data + * + * @param string $optionType + * @param $cartItem + * @param $option + * @param $selectedOption + * @return array + * @throws LocalizedException + */ + public function getData( + string $optionType, + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption + ): array { + if (!array_key_exists($optionType, $this->customOptionValueTypeProviders)) { + throw new LocalizedException(__('Option type "%1" is not supported', $optionType)); + } + + /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeRenderer */ + $optionTypeRenderer = $option->groupFactory($optionType) + ->setOption($option) + ->setConfigurationItem($cartItem) + ->setConfigurationItemOption($selectedOption); + + $customOptionValueTypeProvider = $this->customOptionValueTypeProviders[$optionType]; + + return $customOptionValueTypeProvider->getData($cartItem, $option, $selectedOption, $optionTypeRenderer); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php index 909867c0457d..d40cad024224 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php @@ -7,17 +7,8 @@ namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem; -use Magento\Catalog\Api\Data\ProductCustomOptionInterface; -use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; -use Magento\Catalog\Model\Product\Option\Type\DefaultType as DefaultOptionType; -use Magento\Catalog\Model\Product\Option\Type\Select as SelectOptionType; -use Magento\Catalog\Model\Product\Option\Type\Text as TextOptionType; use Magento\Framework\Exception\LocalizedException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Model\Quote\Item as QuoteItem; -use Magento\Store\Api\Data\StoreInterface; -use Magento\Store\Model\Store; -use Magento\Store\Model\StoreManagerInterface; /** * Custom Option Data provider @@ -25,17 +16,17 @@ class CustomizableOption { /** - * @var StoreManagerInterface + * @var CustomOptionValueComposite */ - private $storeManager; + private $customOptionValueDataProvider; /** - * @param StoreManagerInterface $storeManager + * @param CustomOptionValueComposite $customOptionValueDataProvider */ public function __construct( - StoreManagerInterface $storeManager + CustomOptionValueComposite $customOptionValueDataProvider ) { - $this->storeManager = $storeManager; + $this->customOptionValueDataProvider = $customOptionValueDataProvider; } /** @@ -44,97 +35,26 @@ public function __construct( * @param QuoteItem $cartItem * @param int $optionId * @return array - * @throws NoSuchEntityException * @throws LocalizedException */ public function getData(QuoteItem $cartItem, int $optionId): array { $product = $cartItem->getProduct(); $option = $product->getOptionById($optionId); + $optionType = $option->getType(); if (!$option) { return []; } - $itemOption = $cartItem->getOptionByCode('option_' . $option->getId()); + $selectedOption = $cartItem->getOptionByCode('option_' . $option->getId()); - /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeGroup */ - $optionTypeGroup = $option->groupFactory($option->getType()) - ->setOption($option) - ->setConfigurationItem($cartItem) - ->setConfigurationItemOption($itemOption); - - if (ProductCustomOptionInterface::OPTION_GROUP_FILE == $option->getType()) { - $downloadParams = $cartItem->getFileDownloadParams(); - - if ($downloadParams) { - $url = $downloadParams->getUrl(); - if ($url) { - $optionTypeGroup->setCustomOptionDownloadUrl($url); - } - $urlParams = $downloadParams->getUrlParams(); - if ($urlParams) { - $optionTypeGroup->setCustomOptionUrlParams($urlParams); - } - } - } - - $selectedOptionValueData = [ - 'id' => $itemOption->getId(), - 'label' => $optionTypeGroup->getFormattedOptionValue($itemOption->getValue()), - ]; - - if (ProductCustomOptionInterface::OPTION_TYPE_DROP_DOWN == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_RADIO == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_CHECKBOX == $option->getType() - ) { - $optionValue = $option->getValueById($itemOption->getValue()); - $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); - - $selectedOptionValueData['price'] = [ - 'type' => strtoupper($optionValue->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $optionValue->getPrice(), - ]; - - $selectedOptionValueData = [$selectedOptionValueData]; - } - - if (ProductCustomOptionInterface::OPTION_TYPE_FIELD == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_AREA == $option->getType() - || ProductCustomOptionInterface::OPTION_GROUP_DATE == $option->getType() - || ProductCustomOptionInterface::OPTION_TYPE_TIME == $option->getType() - ) { - $priceValueUnits = $this->getPriceValueUnits($option->getPriceType()); - - $selectedOptionValueData['price'] = [ - 'type' => strtoupper($option->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $option->getPrice(), - ]; - - $selectedOptionValueData = [$selectedOptionValueData]; - } - - if (ProductCustomOptionInterface::OPTION_TYPE_MULTIPLE == $option->getType()) { - $selectedOptionValueData = []; - $optionIds = explode(',', $itemOption->getValue()); - - foreach ($optionIds as $optionId) { - $optionValue = $option->getValueById($optionId); - $priceValueUnits = $this->getPriceValueUnits($optionValue->getPriceType()); - - $selectedOptionValueData[] = [ - 'id' => $itemOption->getId(), - 'label' => $optionValue->getTitle(), - 'price' => [ - 'type' => strtoupper($optionValue->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $optionValue->getPrice(), - ], - ]; - } - } + $selectedOptionValueData = $this->customOptionValueDataProvider->getData( + $optionType, + $cartItem, + $option, + $selectedOption + ); return [ 'id' => $option->getId(), @@ -144,34 +64,4 @@ public function getData(QuoteItem $cartItem, int $optionId): array 'sort_order' => $option->getSortOrder(), ]; } - - /** - * Retrieve price value unit - * - * @param string $priceType - * @return string - * @throws NoSuchEntityException - */ - private function getPriceValueUnits(string $priceType): string - { - if (ProductPriceOptionsInterface::VALUE_PERCENT == $priceType) { - return '%'; - } - - return $this->getCurrencySymbol(); - } - - /** - * Get currency symbol - * - * @return string - * @throws NoSuchEntityException - */ - private function getCurrencySymbol(): string - { - /** @var Store|StoreInterface $store */ - $store = $this->storeManager->getStore(); - - return $store->getBaseCurrency()->getCurrencySymbol(); - } } diff --git a/app/code/Magento/QuoteGraphQl/etc/di.xml b/app/code/Magento/QuoteGraphQl/etc/di.xml new file mode 100644 index 000000000000..276049cb61de --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/etc/di.xml @@ -0,0 +1,24 @@ + + + + + + + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue + Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\MultipleCustomOptionValue + + + + From 7990b83d7d27efdaa89d60292e37058d5b78c79f Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 19:05:52 +0300 Subject: [PATCH 12/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart --- .../Model/Cart/AddProductsToCart.php | 136 +++++++++++++ .../Model/Cart/AddSimpleProductToCart.php | 149 +++++++++++++++ .../Cart/AddSimpleProductToCartProcessor.php | 122 ------------ .../ExtractDataFromCart.php} | 14 +- .../DataProvider}/CustomizableOption.php | 17 +- .../CustomizableOptionValue/Composite.php | 68 +++++++ .../CustomizableOptionValue/Dropdown.php} | 39 ++-- .../CustomizableOptionValue/Multiple.php} | 26 ++- .../PriceUnitLabel.php} | 5 +- .../CustomizableOptionValue/Text.php | 59 ++++++ .../CustomizableOptionValueInterface.php} | 13 +- .../Resolver/AddSimpleProductsToCart.php | 77 ++++++++ .../{Coupon => }/ApplyCouponToCart.php | 2 +- .../Resolver/Cart/AddSimpleProductsToCart.php | 178 ------------------ .../Resolver/CartItem/CustomizableOptions.php | 94 --------- .../Model/Resolver/CartItemTypeResolver.php | 34 ++-- .../CartItemTypeResolverComposite.php | 56 ------ .../Resolver/{Cart => }/CreateEmptyCart.php | 2 +- .../Model/Resolver/CustomizableOptions.php | 65 +++++++ .../TextCustomOptionValue.php | 61 ------ .../CartItem/CustomOptionValueComposite.php | 68 ------- .../{Coupon => }/RemoveCouponFromCart.php | 2 +- app/code/Magento/QuoteGraphQl/etc/di.xml | 30 +-- .../Magento/QuoteGraphQl/etc/graphql/di.xml | 23 --- .../Magento/QuoteGraphQl/etc/schema.graphqls | 19 +- 25 files changed, 655 insertions(+), 704 deletions(-) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/Cart/CartHydrator.php => Cart/ExtractDataFromCart.php} (74%) rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/CartItem => CartItem/DataProvider}/CustomizableOption.php (70%) create mode 100644 app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Composite.php rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/CartItem/CustomOptionValue/DropdownCustomOptionValue.php => CartItem/DataProvider/CustomizableOptionValue/Dropdown.php} (50%) rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php => CartItem/DataProvider/CustomizableOptionValue/Multiple.php} (61%) rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php => CartItem/DataProvider/CustomizableOptionValue/PriceUnitLabel.php} (90%) create mode 100644 app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Text.php rename app/code/Magento/QuoteGraphQl/Model/{Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php => CartItem/DataProvider/CustomizableOptionValueInterface.php} (58%) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php rename app/code/Magento/QuoteGraphQl/Model/Resolver/{Coupon => }/ApplyCouponToCart.php (98%) delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php rename app/code/Magento/QuoteGraphQl/Model/Resolver/{Cart => }/CreateEmptyCart.php (98%) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/CustomizableOptions.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php delete mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php rename app/code/Magento/QuoteGraphQl/Model/Resolver/{Coupon => }/RemoveCouponFromCart.php (98%) delete mode 100644 app/code/Magento/QuoteGraphQl/etc/graphql/di.xml diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php new file mode 100644 index 000000000000..87be72f1df1f --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php @@ -0,0 +1,136 @@ +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; + } + + /** + * @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); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php new file mode 100644 index 000000000000..6b13c6c0af72 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -0,0 +1,149 @@ +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, + ], + ]); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php deleted file mode 100644 index 3b6e1801c5f1..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCartProcessor.php +++ /dev/null @@ -1,122 +0,0 @@ -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 - ] - ]); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php similarity index 74% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php rename to app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php index 6a0a5f26aa33..faefa686606e 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/Cart/CartHydrator.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromCart.php @@ -5,23 +5,23 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\Cart; +namespace Magento\QuoteGraphQl\Model\Cart; -use Magento\Quote\Api\Data\CartInterface; use Magento\Quote\Model\Quote; use Magento\Quote\Model\Quote\Item as QuoteItem; /** - * Cart Hydrator class + * Extract data from cart */ -class CartHydrator +class ExtractDataFromCart { /** - * Hydrate cart to plain array - * @param CartInterface|Quote $cart + * Extract data from cart + * + * @param Quote $cart * @return array */ - public function hydrate(CartInterface $cart): array + public function execute(Quote $cart): array { $items = []; diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOption.php similarity index 70% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php rename to app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOption.php index d40cad024224..3199668060ea 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomizableOption.php +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOption.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem; +namespace Magento\QuoteGraphQl\Model\CartItem\DataProvider; use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Model\Quote\Item as QuoteItem; @@ -16,17 +16,17 @@ class CustomizableOption { /** - * @var CustomOptionValueComposite + * @var CustomizableOptionValueInterface */ - private $customOptionValueDataProvider; + private $customizableOptionValue; /** - * @param CustomOptionValueComposite $customOptionValueDataProvider + * @param CustomizableOptionValueInterface $customOptionValueDataProvider */ public function __construct( - CustomOptionValueComposite $customOptionValueDataProvider + CustomizableOptionValueInterface $customOptionValueDataProvider ) { - $this->customOptionValueDataProvider = $customOptionValueDataProvider; + $this->customizableOptionValue = $customOptionValueDataProvider; } /** @@ -41,7 +41,6 @@ public function getData(QuoteItem $cartItem, int $optionId): array { $product = $cartItem->getProduct(); $option = $product->getOptionById($optionId); - $optionType = $option->getType(); if (!$option) { return []; @@ -49,8 +48,7 @@ public function getData(QuoteItem $cartItem, int $optionId): array $selectedOption = $cartItem->getOptionByCode('option_' . $option->getId()); - $selectedOptionValueData = $this->customOptionValueDataProvider->getData( - $optionType, + $selectedOptionValueData = $this->customizableOptionValue->getData( $cartItem, $option, $selectedOption @@ -62,6 +60,7 @@ public function getData(QuoteItem $cartItem, int $optionId): array 'type' => $option->getType(), 'values' => $selectedOptionValueData, 'sort_order' => $option->getSortOrder(), + 'is_required' => $option->getIsRequire(), ]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Composite.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Composite.php new file mode 100644 index 000000000000..529784512530 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Composite.php @@ -0,0 +1,68 @@ +objectManager = $objectManager; + $this->customizableOptionValues = $customizableOptionValues; + } + + /** + * @inheritdoc + */ + public function getData( + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption + ): array { + $optionType = $option->getType(); + + if (!array_key_exists($optionType, $this->customizableOptionValues)) { + throw new GraphQlInputException(__('Option type "%1" is not supported', $optionType)); + } + $customizableOptionValueClassName = $this->customizableOptionValues[$optionType]; + + $customizableOptionValue = $this->objectManager->get($customizableOptionValueClassName); + if (!$customizableOptionValue instanceof CustomizableOptionValueInterface) { + throw new LocalizedException( + __('%1 doesn\'t implement CustomizableOptionValueInterface', $customizableOptionValueClassName) + ); + } + return $customizableOptionValue->getData($cartItem, $option, $selectedOption); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/DropdownCustomOptionValue.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Dropdown.php similarity index 50% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/DropdownCustomOptionValue.php rename to app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Dropdown.php index f56dacca23ca..74ed40346500 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/DropdownCustomOptionValue.php +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Dropdown.php @@ -5,60 +5,61 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue; +namespace Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue; use Magento\Catalog\Model\Product\Option; -use Magento\Catalog\Model\Product\Option\Type\DefaultType as DefaultOptionType; -use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Catalog\Model\Product\Option\Type\Select as SelectOptionType; use Magento\Quote\Model\Quote\Item as QuoteItem; use Magento\Quote\Model\Quote\Item\Option as SelectedOption; -use Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionPriceUnitLabel; +use Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValueInterface; /** - * Dropdown Custom Option Value Data provider + * @inheritdoc */ -class DropdownCustomOptionValue implements CustomOptionValueInterface +class Dropdown implements CustomizableOptionValueInterface { /** - * @var CustomOptionPriceUnitLabel + * @var PriceUnitLabel */ - private $customOptionPriceUnitLabel; + private $priceUnitLabel; /** - * @param CustomOptionPriceUnitLabel $customOptionPriceUnitLabel + * @param PriceUnitLabel $priceUnitLabel */ public function __construct( - CustomOptionPriceUnitLabel $customOptionPriceUnitLabel + PriceUnitLabel $priceUnitLabel ) { - $this->customOptionPriceUnitLabel = $customOptionPriceUnitLabel; + $this->priceUnitLabel = $priceUnitLabel; } /** - * {@inheritdoc} - * - * @throws NoSuchEntityException + * @inheritdoc */ public function getData( QuoteItem $cartItem, Option $option, - SelectedOption $selectedOption, - DefaultOptionType $optionTypeRenderer + SelectedOption $selectedOption ): array { + /** @var SelectOptionType $optionTypeRenderer */ + $optionTypeRenderer = $option->groupFactory($option->getType()) + ->setOption($option) + ->setConfigurationItemOption($selectedOption); + $selectedValue = $selectedOption->getValue(); $optionValue = $option->getValueById($selectedValue); - $optionPriceType = (string) $optionValue->getPriceType(); - $priceValueUnits = $this->customOptionPriceUnitLabel->getData($optionPriceType); + $optionPriceType = (string)$optionValue->getPriceType(); + $priceValueUnits = $this->priceUnitLabel->getData($optionPriceType); $selectedOptionValueData = [ 'id' => $selectedOption->getId(), 'label' => $optionTypeRenderer->getFormattedOptionValue($selectedValue), + 'value' => $selectedValue, 'price' => [ 'type' => strtoupper($optionPriceType), 'units' => $priceValueUnits, 'value' => $optionValue->getPrice(), ] ]; - return [$selectedOptionValueData]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Multiple.php similarity index 61% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php rename to app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Multiple.php index 87ee56f56100..619e84568a54 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/MultipleCustomOptionValue.php +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Multiple.php @@ -5,44 +5,40 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue; +namespace Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue; use Magento\Catalog\Model\Product\Option; use Magento\Catalog\Model\Product\Option\Type\DefaultType; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Quote\Model\Quote\Item as QuoteItem; use Magento\Quote\Model\Quote\Item\Option as SelectedOption; -use Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionPriceUnitLabel; +use Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValueInterface; /** * Multiple Option Value Data provider */ -class MultipleCustomOptionValue implements CustomOptionValueInterface +class Multiple implements CustomizableOptionValueInterface { /** - * @var CustomOptionPriceUnitLabel + * @var PriceUnitLabel */ - private $customOptionPriceUnitLabel; + private $priceUnitLabel; /** - * @param CustomOptionPriceUnitLabel $customOptionPriceUnitLabel + * @param PriceUnitLabel $priceUnitLabel */ public function __construct( - CustomOptionPriceUnitLabel $customOptionPriceUnitLabel + PriceUnitLabel $priceUnitLabel ) { - $this->customOptionPriceUnitLabel = $customOptionPriceUnitLabel; + $this->priceUnitLabel = $priceUnitLabel; } /** - * {@inheritdoc} - * - * @throws NoSuchEntityException + * @inheritdoc */ public function getData( QuoteItem $cartItem, Option $option, - SelectedOption $selectedOption, - DefaultType $optionTypeRenderer + SelectedOption $selectedOption ): array { $selectedOptionValueData = []; $optionIds = explode(',', $selectedOption->getValue()); @@ -53,7 +49,7 @@ public function getData( foreach ($optionIds as $optionId) { $optionValue = $option->getValueById($optionId); - $priceValueUnits = $this->customOptionPriceUnitLabel->getData($optionValue->getPriceType()); + $priceValueUnits = $this->priceUnitLabel->getData($optionValue->getPriceType()); $selectedOptionValueData[] = [ 'id' => $selectedOption->getId(), diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/PriceUnitLabel.php similarity index 90% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php rename to app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/PriceUnitLabel.php index f80b2994cc87..bee2e54ed5f4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionPriceUnitLabel.php +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/PriceUnitLabel.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem; +namespace Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue; use Magento\Catalog\Model\Config\Source\ProductPriceOptionsInterface; use Magento\Framework\Exception\NoSuchEntityException; @@ -16,7 +16,7 @@ /** * Custom Option Data provider */ -class CustomOptionPriceUnitLabel +class PriceUnitLabel { /** * @var StoreManagerInterface @@ -37,7 +37,6 @@ public function __construct( * * @param string $priceType * @return string - * @throws NoSuchEntityException */ public function getData(string $priceType): string { diff --git a/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Text.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Text.php new file mode 100644 index 000000000000..4b29eb6a4a66 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValue/Text.php @@ -0,0 +1,59 @@ +priceUnitLabel = $priceUnitLabel; + } + + /** + * @inheritdoc + */ + public function getData( + QuoteItem $cartItem, + Option $option, + SelectedOption $selectedOption + ): array { + /** @var TextOptionType $optionTypeRenderer */ + $optionTypeRenderer = $option->groupFactory($option->getType()); + $priceValueUnits = $this->priceUnitLabel->getData($option->getPriceType()); + + $selectedOptionValueData = [ + 'id' => $selectedOption->getId(), + 'label' => '', + 'value' => $optionTypeRenderer->getFormattedOptionValue($selectedOption->getValue()), + 'price' => [ + 'type' => strtoupper($option->getPriceType()), + 'units' => $priceValueUnits, + 'value' => $option->getPrice(), + ], + ]; + return [$selectedOptionValueData]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValueInterface.php similarity index 58% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php rename to app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValueInterface.php index 700362ceea0e..fce8b80f6d47 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/CustomOptionValueInterface.php +++ b/app/code/Magento/QuoteGraphQl/Model/CartItem/DataProvider/CustomizableOptionValueInterface.php @@ -5,31 +5,28 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue; +namespace Magento\QuoteGraphQl\Model\CartItem\DataProvider; use Magento\Catalog\Model\Product\Option; -use Magento\Catalog\Model\Product\Option\Type\DefaultType; use Magento\Quote\Model\Quote\Item as QuoteItem; use Magento\Quote\Model\Quote\Item\Option as SelectedOption; /** - * Custom Option Value Data provider + * Customizable Option Value Data provider */ -interface CustomOptionValueInterface +interface CustomizableOptionValueInterface { /** - * Custom Option Type Data Provider + * Customizable Option Value Data Provider * * @param QuoteItem $cartItem * @param Option $option * @param SelectedOption $selectedOption - * @param DefaultType $optionTypeRenderer * @return array */ public function getData( QuoteItem $cartItem, Option $option, - SelectedOption $selectedOption, - DefaultType $optionTypeRenderer + SelectedOption $selectedOption ): array; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php new file mode 100644 index 000000000000..31a0b3d02e44 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/AddSimpleProductsToCart.php @@ -0,0 +1,77 @@ +arrayManager = $arrayManager; + $this->addProductsToCart = $addProductsToCart; + $this->extractDataFromCart = $extractDataFromCart; + } + + /** + * @inheritdoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + $cartHash = $this->arrayManager->get('input/cart_id', $args); + $cartItems = $this->arrayManager->get('input/cartItems', $args); + + if (!isset($cartHash)) { + throw new GraphQlInputException(__('Missing key "cart_id" in cart data')); + } + + if (!isset($cartItems) || !is_array($cartItems) || empty($cartItems)) { + throw new GraphQlInputException(__('Missing key "cartItems" in cart data')); + } + + $cart = $this->addProductsToCart->execute((string)$cartHash, $cartItems); + $cartData = $this->extractDataFromCart->execute($cart); + + return [ + 'cart' => $cartData, + ]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/ApplyCouponToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php similarity index 98% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/ApplyCouponToCart.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php index ab57b8ff499c..ac5cb38326bc 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/ApplyCouponToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ApplyCouponToCart.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\Coupon; +namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\Exception\CouldNotSaveException; use Magento\Framework\Exception\NoSuchEntityException; diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php deleted file mode 100644 index 80aa42b4365d..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/AddSimpleProductsToCart.php +++ /dev/null @@ -1,178 +0,0 @@ -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); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php deleted file mode 100644 index 8961fea3acb4..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItem/CustomizableOptions.php +++ /dev/null @@ -1,94 +0,0 @@ -valueFactory = $valueFactory; - $this->userContext = $userContext; - $this->customOptionDataProvider = $customOptionDataProvider; - } - - /** - * {@inheritDoc} - */ - public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) : Value - { - if (!isset($value['model'])) { - return $this->valueFactory->create(function () { - return []; - }); - } - - /** @var QuoteItem $cartItem */ - $cartItem = $value['model']; - $optionIds = $cartItem->getOptionByCode('option_ids'); - - if (!$optionIds) { - return $this->valueFactory->create(function () { - return []; - }); - } - - $customOptions = []; - $customOptionIds = explode(',', $optionIds->getValue()); - - foreach ($customOptionIds as $optionId) { - $customOptionData = $this->customOptionDataProvider->getData($cartItem, (int) $optionId); - - if (0 === count($customOptionData)) { - continue; - } - - $customOptions[] = $customOptionData; - } - - $result = function () use ($customOptions) { - return $customOptions; - }; - - return $this->valueFactory->create($result); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php index b8b197b45039..88db93c177f7 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -7,53 +7,49 @@ namespace Magento\QuoteGraphQl\Model\Resolver; -use Magento\Framework\GraphQl\Exception\GraphQlInputException; +use Magento\Framework\Exception\LocalizedException; use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface; /** - * Resolver for cart item types that vary by product types - * - * {@inheritdoc} + * @inheritdoc */ class CartItemTypeResolver implements TypeResolverInterface { /** - * @var string[] + * @var array */ - private $cartItemTypes = []; + private $supportedTypes = []; /** - * @param TypeResolverInterface[] $cartItemTypes + * @param array $supportedTypes */ - public function __construct(array $cartItemTypes = []) + public function __construct(array $supportedTypes = []) { - $this->cartItemTypes = $cartItemTypes; + $this->supportedTypes = $supportedTypes; } /** - * Resolve GraphQl types to retrieve product type specific information about cart items * {@inheritdoc} * - * @throws GraphQlInputException + * @throws LocalizedException */ public function resolveType(array $data) : string { if (!isset($data['product'])) { - return ''; + throw new LocalizedException(__('Missing key "product" in cart data')); } - $productData = $data['product']; if (!isset($productData['type_id'])) { - return ''; + throw new LocalizedException(__('Missing key "type_id" in product data')); } - $productTypeId = $productData['type_id']; - if (!isset($this->cartItemTypes[$productTypeId])) { - return ''; + if (!isset($this->supportedTypes[$productTypeId])) { + throw new LocalizedException( + __('Product "%product_type" type is not supported', ['product_type' => $productTypeId]) + ); } - - return $this->cartItemTypes[$productTypeId]; + return $this->supportedTypes[$productTypeId]; } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php deleted file mode 100644 index 5af521756204..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolverComposite.php +++ /dev/null @@ -1,56 +0,0 @@ -cartItemTypeResolvers = $cartItemTypeResolvers; - } - - /** - * {@inheritdoc} - * - * @throws GraphQlInputException - */ - public function resolveType(array $data) : string - { - if (!isset($data['product'])) { - throw new GraphQlInputException( - __('Missing key %1 in cart data', ['product']) - ); - } - - foreach ($this->cartItemTypeResolvers as $cartItemTypeResolver) { - $resolvedType = $cartItemTypeResolver->resolveType($data); - - if ($resolvedType) { - return $resolvedType; - } - } - - throw new GraphQlInputException( - __('Concrete type for %1 not implemented', ['CartItemInterface']) - ); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/CreateEmptyCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php similarity index 98% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/CreateEmptyCart.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php index 78f963831329..1ccc2fda58e5 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Cart/CreateEmptyCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CreateEmptyCart.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\Cart; +namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Authorization\Model\UserContextInterface; use Magento\Framework\GraphQl\Config\Element\Field; diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CustomizableOptions.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CustomizableOptions.php new file mode 100644 index 000000000000..a681b2ca0d00 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CustomizableOptions.php @@ -0,0 +1,65 @@ +customizableOption = $customizableOption; + } + + /** + * @inheritdoc + */ + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + if (!isset($value['model'])) { + throw new LocalizedException(__('"model" value should be specified')); + } + + /** @var QuoteItem $cartItem */ + $cartItem = $value['model']; + $quoteItemOption = $cartItem->getOptionByCode('option_ids'); + + if (null === $quoteItemOption) { + return []; + } + + $customizableOptionsData = []; + $customizableOptionIds = explode(',', $quoteItemOption->getValue()); + + foreach ($customizableOptionIds as $customizableOptionId) { + $customizableOption = $this->customizableOption->getData( + $cartItem, + (int)$customizableOptionId + ); + $customizableOptionsData[] = $customizableOption; + } + return $customizableOptionsData; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php deleted file mode 100644 index 78657603ff3e..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValue/TextCustomOptionValue.php +++ /dev/null @@ -1,61 +0,0 @@ -customOptionPriceUnitLabel = $customOptionPriceUnitLabel; - } - - /** - * {@inheritdoc} - * - * @throws NoSuchEntityException - */ - public function getData( - QuoteItem $cartItem, - Option $option, - SelectedOption $selectedOption, - DefaultType $optionTypeRenderer - ): array { - $priceValueUnits = $this->customOptionPriceUnitLabel->getData($option->getPriceType()); - - $selectedOptionValueData = [ - 'id' => $selectedOption->getId(), - 'label' => $optionTypeRenderer->getFormattedOptionValue($selectedOption->getValue()), - 'price' => [ - 'type' => strtoupper($option->getPriceType()), - 'units' => $priceValueUnits, - 'value' => $option->getPrice(), - ] - ]; - - return [$selectedOptionValueData]; - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php deleted file mode 100644 index 4234753d1163..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/DataProvider/CartItem/CustomOptionValueComposite.php +++ /dev/null @@ -1,68 +0,0 @@ -customOptionValueTypeProviders = $customOptionValueTypeProviders; - } - - /** - * Retrieve custom option values data - * - * @param string $optionType - * @param $cartItem - * @param $option - * @param $selectedOption - * @return array - * @throws LocalizedException - */ - public function getData( - string $optionType, - QuoteItem $cartItem, - Option $option, - SelectedOption $selectedOption - ): array { - if (!array_key_exists($optionType, $this->customOptionValueTypeProviders)) { - throw new LocalizedException(__('Option type "%1" is not supported', $optionType)); - } - - /** @var SelectOptionType|TextOptionType|DefaultOptionType $optionTypeRenderer */ - $optionTypeRenderer = $option->groupFactory($optionType) - ->setOption($option) - ->setConfigurationItem($cartItem) - ->setConfigurationItemOption($selectedOption); - - $customOptionValueTypeProvider = $this->customOptionValueTypeProviders[$optionType]; - - return $customOptionValueTypeProvider->getData($cartItem, $option, $selectedOption, $optionTypeRenderer); - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/RemoveCouponFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php similarity index 98% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/RemoveCouponFromCart.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php index abb5a0b57519..40175cc58995 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/Coupon/RemoveCouponFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\Coupon; +namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\Exception\CouldNotDeleteException; use Magento\Framework\Exception\NoSuchEntityException; diff --git a/app/code/Magento/QuoteGraphQl/etc/di.xml b/app/code/Magento/QuoteGraphQl/etc/di.xml index 276049cb61de..63ad9e193b95 100644 --- a/app/code/Magento/QuoteGraphQl/etc/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/di.xml @@ -6,18 +6,26 @@ */ --> - + + - - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\DropdownCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\TextCustomOptionValue - Magento\QuoteGraphQl\Model\Resolver\DataProvider\CartItem\CustomOptionValue\MultipleCustomOptionValue + + SimpleCartItem + + + + + + + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Text + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Dropdown + Magento\QuoteGraphQl\Model\CartItem\DataProvider\CustomizableOptionValue\Multiple diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml deleted file mode 100644 index 8f29b2559a7a..000000000000 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - Magento\QuoteGraphQl\Model\Resolver\CartItemTypeResolver - - - - - - - SimpleCartItem - - - - diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 7be066e125c1..17527612caa7 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -2,10 +2,10 @@ # See COPYING.txt for license details. type Mutation { - createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user") - applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Coupon\\ApplyCouponToCart") - removeCouponFromCart(input: RemoveCouponFromCartInput): RemoveCouponFromCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\Coupon\\RemoveCouponFromCart") - addSimpleProductsToCart(input: AddSimpleProductsToCartInput): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\Cart\\AddSimpleProductsToCart") + createEmptyCart: String @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\CreateEmptyCart") @doc(description:"Creates empty shopping cart for guest or logged in user") + applyCouponToCart(input: ApplyCouponToCartInput): ApplyCouponToCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ApplyCouponToCart") + removeCouponFromCart(input: RemoveCouponFromCartInput): RemoveCouponFromCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\RemoveCouponFromCart") + addSimpleProductsToCart(input: AddSimpleProductsToCartInput): AddSimpleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart") } input ApplyCouponToCartInput { @@ -18,6 +18,7 @@ type ApplyCouponToCartOutput { } type Cart { + items: [CartItemInterface] applied_coupon: AppliedCoupon } @@ -43,7 +44,7 @@ input AddSimpleProductsToCartInput { } input SimpleProductCartItemInput { - details: CartItemDetailsInput! + data: CartItemInput! customizable_options:[CustomizableOptionInput!] } @@ -57,15 +58,15 @@ type AddSimpleProductsToCartOutput { } type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") { - customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItem\\CustomizableOptions") + customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions") } -input CartItemDetailsInput { +input CartItemInput { sku: String! qty: Float! } -interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItemTypeResolverComposite") { +interface CartItemInterface @typeResolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CartItemTypeResolver") { id: String! qty: Float! product: ProductInterface! @@ -75,6 +76,7 @@ type SelectedCustomizableOption { id: Int! label: String! type: String! + is_required: Int! values: [SelectedCustomizableOptionValue!]! sort_order: Int! } @@ -82,6 +84,7 @@ type SelectedCustomizableOption { type SelectedCustomizableOptionValue { id: Int label: String! + value: String! price: CartItemSelectedOptionValuePrice! sort_order: Int! } From ada51dc5fe9f3e52f78253874627de21bb345f68 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 19:14:27 +0300 Subject: [PATCH 13/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart --- app/code/Magento/QuoteGraphQl/etc/schema.graphqls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 17527612caa7..f692aa57b218 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -82,7 +82,7 @@ type SelectedCustomizableOption { } type SelectedCustomizableOptionValue { - id: Int + id: Int! label: String! value: String! price: CartItemSelectedOptionValuePrice! From 484c65c2088cc4bdce6a59c94d13dfb3760f2662 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 19:53:11 +0300 Subject: [PATCH 14/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static builds --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 5 +++++ .../Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php | 2 ++ .../QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php | 4 ++-- .../QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index db03b1712612..b26d1fae376f 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -13,13 +13,18 @@ /** * Catalog product option date validator + * * {@inheritdoc} */ class DateType extends ProductDateOptionType { /** * Make valid string as a value of date option type for GraphQl queries + * * {@inheritdoc} + * + * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) + * @return $this */ public function validateUserValue($values) { diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php index 87be72f1df1f..daec9411307f 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddProductsToCart.php @@ -87,6 +87,8 @@ public function execute(string $cartHash, array $cartItems): Quote } /** + * Get cart + * * @param string $cartHash * @return Quote * @throws GraphQlNoSuchEntityException diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php index 6b13c6c0af72..aa5b41daebdc 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AddSimpleProductToCart.php @@ -92,7 +92,7 @@ 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')); + throw new GraphQlInputException(__('Missing key "sku" in cart item data')); } return (string)$sku; } @@ -108,7 +108,7 @@ 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')); + throw new GraphQlInputException(__('Missing key "qty" in cart item data')); } return (float)$qty; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php index 88db93c177f7..a4d0a890eaf3 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -8,6 +8,7 @@ namespace Magento\QuoteGraphQl\Model\Resolver; use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Query\Resolver\TypeResolverInterface; /** @@ -31,6 +32,9 @@ public function __construct(array $supportedTypes = []) /** * {@inheritdoc} * + * @param array $data + * @return string + * @throws GraphQlInputException * @throws LocalizedException */ public function resolveType(array $data) : string From 6b7300a16b0474ce8e31168d44190b55dcccad11 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 19:54:27 +0300 Subject: [PATCH 15/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static builds --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index b26d1fae376f..14b2d17781a5 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -24,7 +24,7 @@ class DateType extends ProductDateOptionType * {@inheritdoc} * * @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...) - * @return $this + * @return ProductDateOptionType */ public function validateUserValue($values) { From c21a016ac581fab5404f3ae03f24aca1f8fd8cb9 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 20:03:33 +0300 Subject: [PATCH 16/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static tests --- .../CatalogGraphQl/Model/Product/Option/DateType.php | 4 ++-- .../QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php | 7 +------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index 14b2d17781a5..1506f0f745ed 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -19,10 +19,10 @@ class DateType extends ProductDateOptionType { /** - * Make valid string as a value of date option type for GraphQl queries - * * {@inheritdoc} * + * 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 */ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php index a4d0a890eaf3..962463860a59 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/CartItemTypeResolver.php @@ -30,12 +30,7 @@ public function __construct(array $supportedTypes = []) } /** - * {@inheritdoc} - * - * @param array $data - * @return string - * @throws GraphQlInputException - * @throws LocalizedException + * @inheritdoc */ public function resolveType(array $data) : string { From d39230e634e50c248300efce12c794097ba196bd Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Wed, 26 Sep 2018 20:37:20 +0300 Subject: [PATCH 17/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static tests --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index 1506f0f745ed..e0c665fe8035 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -19,8 +19,6 @@ class DateType extends ProductDateOptionType { /** - * {@inheritdoc} - * * 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...) From d43164b5edc26e5f092a094a60f2f121b2223587 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Mon, 1 Oct 2018 12:48:01 +0300 Subject: [PATCH 18/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static tests --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index e0c665fe8035..76bc0abaeb02 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -12,9 +12,7 @@ use Magento\Framework\Stdlib\DateTime; /** - * Catalog product option date validator - * - * {@inheritdoc} + * @inheritdoc */ class DateType extends ProductDateOptionType { From c78b9938228c991dcc669ba174f2fced9b7ba66d Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Tue, 2 Oct 2018 13:29:10 +0300 Subject: [PATCH 19/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static tests --- .../Magento/CatalogGraphQl/Model/Product/Option/DateType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php index 76bc0abaeb02..e1106a3f696e 100644 --- a/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php +++ b/app/code/Magento/CatalogGraphQl/Model/Product/Option/DateType.php @@ -38,7 +38,7 @@ public function validateUserValue($values) * @return [] * @throws LocalizedException */ - protected function formatValues($values) + private function formatValues($values) { if (isset($values[$this->getOption()->getId()])) { $value = $values[$this->getOption()->getId()]; From 7e3c023a20b499ff671c09acbbc2c5e67b2f9196 Mon Sep 17 00:00:00 2001 From: Valeriy Nayda Date: Tue, 2 Oct 2018 13:43:34 +0300 Subject: [PATCH 20/20] GraphQL-141: [Mutations] Cart Operations > Add simple product to Cart -- fix static tests --- app/code/Magento/QuoteGraphQl/composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/code/Magento/QuoteGraphQl/composer.json b/app/code/Magento/QuoteGraphQl/composer.json index 9995e292e784..bed9157c4de5 100644 --- a/app/code/Magento/QuoteGraphQl/composer.json +++ b/app/code/Magento/QuoteGraphQl/composer.json @@ -11,8 +11,7 @@ "magento/module-store": "*" }, "suggest": { - "magento/module-graph-ql": "*", - "magento/module-catalog-graph-ql": "*" + "magento/module-graph-ql": "*" }, "license": [ "OSL-3.0",