Skip to content

Commit dac1ea5

Browse files
authored
Merge pull request magento#4948 from magento-engcom/2.3-develop-graphql-daily-prs
- Community Contributions - GraphQL daily delivery
2 parents edec48a + 59aa830 commit dac1ea5

File tree

19 files changed

+855
-14
lines changed

19 files changed

+855
-14
lines changed
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\BundleGraphQl\Model\Cart;
9+
10+
use Magento\Bundle\Helper\Catalog\Product\Configuration;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Quote\Model\Quote\Item;
13+
use Magento\Framework\Pricing\Helper\Data;
14+
use Magento\Framework\Serialize\SerializerInterface;
15+
16+
/**
17+
* Data provider for bundled product options
18+
*/
19+
class BundleOptionDataProvider
20+
{
21+
/**
22+
* @var Data
23+
*/
24+
private $pricingHelper;
25+
26+
/**
27+
* @var SerializerInterface
28+
*/
29+
private $serializer;
30+
31+
/**
32+
* @var Configuration
33+
*/
34+
private $configuration;
35+
36+
/**
37+
* @param Data $pricingHelper
38+
* @param SerializerInterface $serializer
39+
* @param Configuration $configuration
40+
*/
41+
public function __construct(
42+
Data $pricingHelper,
43+
SerializerInterface $serializer,
44+
Configuration $configuration
45+
) {
46+
$this->pricingHelper = $pricingHelper;
47+
$this->serializer = $serializer;
48+
$this->configuration = $configuration;
49+
}
50+
51+
/**
52+
* Extract data for a bundled cart item
53+
*
54+
* @param Item $item
55+
* @return array
56+
*/
57+
public function getData(Item $item): array
58+
{
59+
$options = [];
60+
$product = $item->getProduct();
61+
62+
/** @var \Magento\Bundle\Model\Product\Type $typeInstance */
63+
$typeInstance = $product->getTypeInstance();
64+
65+
$optionsQuoteItemOption = $item->getOptionByCode('bundle_option_ids');
66+
$bundleOptionsIds = $optionsQuoteItemOption
67+
? $this->serializer->unserialize($optionsQuoteItemOption->getValue())
68+
: [];
69+
70+
if ($bundleOptionsIds) {
71+
/** @var \Magento\Bundle\Model\ResourceModel\Option\Collection $optionsCollection */
72+
$optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $product);
73+
74+
$selectionsQuoteItemOption = $item->getOptionByCode('bundle_selection_ids');
75+
76+
$bundleSelectionIds = $this->serializer->unserialize($selectionsQuoteItemOption->getValue());
77+
78+
if (!empty($bundleSelectionIds)) {
79+
$selectionsCollection = $typeInstance->getSelectionsByIds($bundleSelectionIds, $product);
80+
$bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true);
81+
82+
$options = $this->buildBundleOptions($bundleOptions, $item);
83+
}
84+
}
85+
86+
return $options;
87+
}
88+
89+
/**
90+
* Build bundle product options based on current selection
91+
*
92+
* @param \Magento\Bundle\Model\Option[] $bundleOptions
93+
* @param Item $item
94+
* @return array
95+
*/
96+
private function buildBundleOptions(array $bundleOptions, Item $item): array
97+
{
98+
$options = [];
99+
foreach ($bundleOptions as $bundleOption) {
100+
if (!$bundleOption->getSelections()) {
101+
continue;
102+
}
103+
104+
$options[] = [
105+
'id' => $bundleOption->getId(),
106+
'label' => $bundleOption->getTitle(),
107+
'type' => $bundleOption->getType(),
108+
'values' => $this->buildBundleOptionValues($bundleOption->getSelections(), $item),
109+
];
110+
}
111+
112+
return $options;
113+
}
114+
115+
/**
116+
* Build bundle product option values based on current selection
117+
*
118+
* @param Product[] $selections
119+
* @param Item $item
120+
* @return array
121+
*/
122+
private function buildBundleOptionValues(array $selections, Item $item): array
123+
{
124+
$values = [];
125+
126+
$product = $item->getProduct();
127+
foreach ($selections as $selection) {
128+
$qty = (float) $this->configuration->getSelectionQty($product, $selection->getSelectionId());
129+
if (!$qty) {
130+
continue;
131+
}
132+
133+
$selectionPrice = $this->configuration->getSelectionFinalPrice($item, $selection);
134+
135+
$values[] = [
136+
'id' => $selection->getSelectionId(),
137+
'label' => $selection->getName(),
138+
'quantity' => $qty,
139+
'price' => $this->pricingHelper->currency($selectionPrice, false, false),
140+
];
141+
}
142+
143+
return $values;
144+
}
145+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\BundleGraphQl\Model\Cart\BuyRequest;
9+
10+
use Magento\Framework\Stdlib\ArrayManager;
11+
use Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestDataProviderInterface;
12+
13+
/**
14+
* Data provider for bundle product buy requests
15+
*/
16+
class BundleDataProvider implements BuyRequestDataProviderInterface
17+
{
18+
/**
19+
* @var ArrayManager
20+
*/
21+
private $arrayManager;
22+
23+
/**
24+
* @param ArrayManager $arrayManager
25+
*/
26+
public function __construct(
27+
ArrayManager $arrayManager
28+
) {
29+
$this->arrayManager = $arrayManager;
30+
}
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function execute(array $cartItemData): array
36+
{
37+
$bundleOptions = [];
38+
$bundleInputs = $this->arrayManager->get('bundle_options', $cartItemData) ?? [];
39+
foreach ($bundleInputs as $bundleInput) {
40+
$bundleOptions['bundle_option'][$bundleInput['id']] = $bundleInput['value'];
41+
$bundleOptions['bundle_option_qty'][$bundleInput['id']] = $bundleInput['quantity'];
42+
}
43+
44+
return $bundleOptions;
45+
}
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\BundleGraphQl\Model\Resolver;
9+
10+
use Magento\BundleGraphQl\Model\Cart\BundleOptionDataProvider;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
13+
use Magento\Framework\GraphQl\Query\ResolverInterface;
14+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15+
16+
/**
17+
* Resolver for bundle product options
18+
*/
19+
class BundleOption implements ResolverInterface
20+
{
21+
/**
22+
* @var BundleOptionDataProvider
23+
*/
24+
private $dataProvider;
25+
26+
/**
27+
* @param BundleOptionDataProvider $bundleOptionDataProvider
28+
*/
29+
public function __construct(
30+
BundleOptionDataProvider $bundleOptionDataProvider
31+
) {
32+
$this->dataProvider = $bundleOptionDataProvider;
33+
}
34+
35+
/**
36+
* @inheritdoc
37+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
38+
*/
39+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
40+
{
41+
if (!isset($value['model'])) {
42+
throw new GraphQlInputException(__('Value must contain "model" property.'));
43+
}
44+
return $this->dataProvider->getData($value['model']);
45+
}
46+
}

app/code/Magento/BundleGraphQl/composer.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
"magento/module-catalog": "*",
88
"magento/module-bundle": "*",
99
"magento/module-catalog-graph-ql": "*",
10+
"magento/module-quote": "*",
11+
"magento/module-quote-graph-ql": "*",
1012
"magento/module-store": "*",
1113
"magento/framework": "*"
1214
},

app/code/Magento/BundleGraphQl/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,11 @@
1616
</argument>
1717
</arguments>
1818
</type>
19+
<type name="Magento\QuoteGraphQl\Model\Resolver\CartItemTypeResolver">
20+
<arguments>
21+
<argument name="supportedTypes" xsi:type="array">
22+
<item name="bundle" xsi:type="string">BundleCartItem</item>
23+
</argument>
24+
</arguments>
25+
</type>
1926
</config>

app/code/Magento/BundleGraphQl/etc/graphql/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@
1313
</argument>
1414
</arguments>
1515
</type>
16+
<type name="Magento\QuoteGraphQl\Model\Cart\BuyRequest\BuyRequestBuilder">
17+
<arguments>
18+
<argument name="providers" xsi:type="array">
19+
<item name="bundle" xsi:type="object">Magento\BundleGraphQl\Model\Cart\BuyRequest\BundleDataProvider</item>
20+
</argument>
21+
</arguments>
22+
</type>
1623
<type name="Magento\Framework\GraphQl\Schema\Type\Enum\DefaultDataMapper">
1724
<arguments>
1825
<argument name="map" xsi:type="array">

app/code/Magento/BundleGraphQl/etc/module.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
99
<module name="Magento_BundleGraphQl" >
1010
<sequence>
11+
<module name="Magento_QuoteGraphQl"/>
1112
<module name="Magento_Catalog"/>
1213
<module name="Magento_BundleProduct"/>
1314
<module name="Magento_Store"/>

app/code/Magento/BundleGraphQl/etc/schema.graphqls

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,50 @@
11
# Copyright © Magento, Inc. All rights reserved.
22
# See COPYING.txt for license details.
33

4+
type Mutation {
5+
addBundleProductsToCart(input: AddBundleProductsToCartInput): AddBundleProductsToCartOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\AddSimpleProductsToCart")
6+
}
7+
8+
input AddBundleProductsToCartInput {
9+
cart_id: String!
10+
cart_items: [BundleProductCartItemInput!]!
11+
}
12+
13+
input BundleProductCartItemInput {
14+
data: CartItemInput!
15+
bundle_options:[BundleOptionInput!]!
16+
customizable_options:[CustomizableOptionInput!]
17+
}
18+
19+
input BundleOptionInput {
20+
id: Int!
21+
quantity: Float!
22+
value: [String!]!
23+
}
24+
25+
type AddBundleProductsToCartOutput {
26+
cart: Cart!
27+
}
28+
29+
type BundleCartItem implements CartItemInterface {
30+
customizable_options: [SelectedCustomizableOption]! @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions")
31+
bundle_options: [SelectedBundleOption!]! @resolver(class: "Magento\\BundleGraphQl\\Model\\Resolver\\BundleOption")
32+
}
33+
34+
type SelectedBundleOption {
35+
id: Int!
36+
label: String!
37+
type: String!
38+
values: [SelectedBundleOptionValue!]!
39+
}
40+
41+
type SelectedBundleOptionValue {
42+
id: Int!
43+
label: String!
44+
quantity: Float!
45+
price: Float!
46+
}
47+
448
type BundleItem @doc(description: "BundleItem defines an individual item in a bundle product.") {
549
option_id: Int @doc(description: "An ID assigned to each type of item in a bundle product.")
650
title: String @doc(description: "The display name of the item.")

app/code/Magento/DownloadableGraphQl/etc/schema.graphqls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ type DownloadableProductLinks @doc(description: "DownloadableProductLinks define
4848
sort_order: Int @doc(description: "A number indicating the sort order")
4949
price: Float @doc(description: "The price of the downloadable product")
5050
sample_url: String @doc(description: "URL to the downloadable sample")
51-
is_shareable: Boolean @deprecated(reason: "This information shoud not be exposed on frontend")
52-
number_of_downloads: Int @deprecated(reason: "This information shoud not be exposed on frontend")
51+
is_shareable: Boolean @deprecated(reason: "This information should not be exposed on frontend")
52+
number_of_downloads: Int @deprecated(reason: "This information should not be exposed on frontend")
5353
link_type: DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample")
5454
sample_type: DownloadableFileTypeEnum @deprecated(reason: "`sample_url` serves to get the downloadable sample")
5555
sample_file: String @deprecated(reason: "`sample_url` serves to get the downloadable sample")

app/code/Magento/QuoteGraphQl/Model/Cart/BuyRequest/BuyRequestDataProviderInterface.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
interface BuyRequestDataProviderInterface
1414
{
1515
/**
16-
* Build buy request for adding product to cart
16+
* Provide buy request data from add to cart item request
1717
*
1818
* @param array $cartItemData
19-
* @return DataObject
19+
* @return array
2020
*/
2121
public function execute(array $cartItemData): array;
2222
}

app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ private function processCartItems(Quote $cart, array $items): void
116116
$itemId = (int)$item['cart_item_id'];
117117
$customizableOptions = $item['customizable_options'] ?? [];
118118

119+
$cartItem = $cart->getItemById($itemId);
120+
if ($cartItem && $cartItem->getParentItemId()) {
121+
throw new GraphQlInputException(__('Child items may not be updated.'));
122+
}
123+
119124
if (count($customizableOptions) === 0 && !isset($item['quantity'])) {
120125
throw new GraphQlInputException(__('Required parameter "quantity" for "cart_items" is missing.'));
121126
}

0 commit comments

Comments
 (0)