Skip to content

Commit 65667f6

Browse files
author
Sergii Kovalenko
committed
Merge branch '2.3-develop' of https://github.com/magento/magento2ce into MAGETWO-84100
2 parents 21f7182 + a2b6f53 commit 65667f6

File tree

99 files changed

+5250
-809
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+5250
-809
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\BundleGraphQl\Model;
8+
9+
use Magento\Framework\GraphQl\Config\Data\TypeResolverInterface;
10+
11+
/**
12+
* {@inheritdoc}
13+
*/
14+
class BundleProductTypeResolver implements TypeResolverInterface
15+
{
16+
/**
17+
* {@inheritdoc}
18+
*/
19+
public function resolveType(array $data)
20+
{
21+
if (isset($data['type_id']) && $data['type_id'] == 'bundle') {
22+
return 'BundleProduct';
23+
}
24+
}
25+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\BundleGraphQl\Model\Plugin\Model\Resolver\Products\DataProvider;
8+
9+
use Magento\Bundle\Model\Product\Type as Bundle;
10+
use Magento\Framework\Api\SearchResultsInterface;
11+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product;
12+
use Magento\Bundle\Model\Product\OptionList;
13+
14+
/**
15+
* Fetch bundle product object and set necessary extension attributes for search result
16+
*/
17+
class ProductPlugin
18+
{
19+
/**
20+
* @var OptionList
21+
*/
22+
private $productOptionList;
23+
24+
/**
25+
* @param OptionList $productOptionList
26+
*/
27+
public function __construct(OptionList $productOptionList)
28+
{
29+
$this->productOptionList = $productOptionList;
30+
}
31+
32+
/**
33+
* Intercept GraphQLCatalog getList, and add any necessary bundle fields
34+
*
35+
* @param Product $subject
36+
* @param SearchResultsInterface $result
37+
* @return SearchResultsInterface
38+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
39+
*/
40+
public function afterGetList(Product $subject, SearchResultsInterface $result)
41+
{
42+
foreach ($result->getItems() as $product) {
43+
if ($product->getTypeId() === Bundle::TYPE_CODE) {
44+
$extensionAttributes = $product->getExtensionAttributes();
45+
$options = $this->productOptionList->getItems($product);
46+
$extensionAttributes->setBundleProductOptions($options);
47+
$product->setExtensionAttributes($extensionAttributes);
48+
}
49+
}
50+
return $result;
51+
}
52+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\BundleGraphQl\Model\Resolver\Products\DataProvider\Product\Formatter;
8+
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Bundle\Model\Product\Type as Bundle;
11+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\FormatterInterface;
12+
use Magento\Framework\Exception\RuntimeException;
13+
use Magento\Framework\GraphQl\Query\EnumLookup;
14+
15+
/**
16+
* Post formatting data to set main fields and options for bundle product
17+
*/
18+
class BundleOptions implements FormatterInterface
19+
{
20+
/**
21+
* @var EnumLookup
22+
*/
23+
private $enumLookup;
24+
25+
/**
26+
* BundleOptions constructor.
27+
* @param EnumLookup $enumLookup
28+
*/
29+
public function __construct(EnumLookup $enumLookup)
30+
{
31+
$this->enumLookup = $enumLookup;
32+
}
33+
34+
/**
35+
* Add bundle options and options to configurable types
36+
*
37+
* {@inheritdoc}
38+
*/
39+
public function format(Product $product, array $productData = [])
40+
{
41+
if ($product->getTypeId() === Bundle::TYPE_CODE) {
42+
$productData = $this->formatBundleAttributes($productData);
43+
$extensionAttributes = $product->getExtensionAttributes();
44+
$productData['bundle_product_options'] = $extensionAttributes->getBundleProductOptions();
45+
}
46+
47+
return $productData;
48+
}
49+
50+
/**
51+
* Format bundle specific top level attributes from product
52+
*
53+
* @param array $product
54+
* @return array
55+
* @throws RuntimeException
56+
*/
57+
private function formatBundleAttributes(array $product)
58+
{
59+
if (isset($product['price_view'])) {
60+
$product['price_view']
61+
= $this->enumLookup->getEnumValueFromField('PriceViewEnum', $product['price_view']);
62+
}
63+
if (isset($product['shipment_type'])) {
64+
$product['ship_bundle_items']
65+
= $this->enumLookup->getEnumValueFromField('ShipBundleItemsEnum', $product['shipment_type']);
66+
}
67+
if (isset($product['price_view'])) {
68+
$product['dynamic_price'] = !(bool)$product['price_type'];
69+
}
70+
if (isset($product['sku_type'])) {
71+
$product['dynamic_sku'] = !(bool)$product['sku_type'];
72+
}
73+
if (isset($product['weight_type'])) {
74+
$product['dynamic_weight'] = !(bool)$product['weight_type'];
75+
}
76+
return $product;
77+
}
78+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\BundleGraphQl\Model\Resolver\Products\Query;
8+
9+
use Magento\Bundle\Model\Product\Type as Bundle;
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Framework\Api\SearchCriteriaBuilder;
12+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product;
13+
use Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\FormatterInterface;
14+
use Magento\Bundle\Api\Data\LinkInterface;
15+
use Magento\Bundle\Model\Option;
16+
use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
17+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
18+
use Magento\Framework\GraphQl\Query\EnumLookup;
19+
20+
/**
21+
* Retrieves simple product data for child products, and formats children data
22+
*/
23+
class BundleProductPostProcessor implements \Magento\Framework\GraphQl\Query\PostFetchProcessorInterface
24+
{
25+
/**
26+
* @var SearchCriteriaBuilder
27+
*/
28+
private $searchCriteriaBuilder;
29+
30+
/**
31+
* @var Product
32+
*/
33+
private $productDataProvider;
34+
35+
/**
36+
* @var ProductResource
37+
*/
38+
private $productResource;
39+
40+
/**
41+
* @var FormatterInterface
42+
*/
43+
private $formatter;
44+
45+
/**
46+
* @var EnumLookup
47+
*/
48+
private $enumLookup;
49+
50+
/**
51+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
52+
* @param Product $productDataProvider
53+
* @param ProductResource $productResource
54+
* @param FormatterInterface $formatter
55+
* @param EnumLookup $enumLookup
56+
*/
57+
public function __construct(
58+
SearchCriteriaBuilder $searchCriteriaBuilder,
59+
Product $productDataProvider,
60+
ProductResource $productResource,
61+
FormatterInterface $formatter,
62+
EnumLookup $enumLookup
63+
) {
64+
$this->searchCriteriaBuilder = $searchCriteriaBuilder;
65+
$this->productDataProvider = $productDataProvider;
66+
$this->productResource = $productResource;
67+
$this->formatter = $formatter;
68+
$this->enumLookup = $enumLookup;
69+
}
70+
71+
/**
72+
* Process all bundle product data, including adding simple product data and formatting relevant attributes.
73+
*
74+
* @param array $resultData
75+
* @return array
76+
*/
77+
public function process(array $resultData)
78+
{
79+
$childrenSkus = [];
80+
$bundleMap = [];
81+
foreach ($resultData as $productKey => $product) {
82+
if (isset($product['type_id']) && $product['type_id'] === Bundle::TYPE_CODE) {
83+
if (isset($product['bundle_product_options'])) {
84+
$bundleMap[$product['sku']] = [];
85+
/** @var Option $option */
86+
foreach ($product['bundle_product_options'] as $optionKey => $option) {
87+
$resultData[$productKey]['items'][$optionKey]
88+
= $option->getData();
89+
/** @var LinkInterface $link */
90+
foreach ($option['product_links'] as $link) {
91+
$bundleMap[$product['sku']][] = $link->getSku();
92+
$childrenSkus[] = $link->getSku();
93+
$formattedLink = [
94+
'product' => new GraphQlNoSuchEntityException(
95+
__('Bundled product not found')
96+
),
97+
'price' => $link->getPrice(),
98+
'position' => $link->getPosition(),
99+
'id' => $link->getId(),
100+
'qty' => (int)$link->getQty(),
101+
'is_default' => (bool)$link->getIsDefault(),
102+
'price_type' => $this->enumLookup->getEnumValueFromField(
103+
'PriceTypeEnum',
104+
$link->getPriceType()
105+
) ?: 'DYNAMIC',
106+
'can_change_quantity' => $link->getCanChangeQuantity()
107+
];
108+
$resultData[$productKey]['items'][$optionKey]['options'][$link['sku']] = $formattedLink;
109+
}
110+
}
111+
}
112+
}
113+
}
114+
115+
$this->searchCriteriaBuilder->addFilter(ProductInterface::SKU, $childrenSkus, 'in');
116+
$childProducts = $this->productDataProvider->getList($this->searchCriteriaBuilder->create());
117+
$resultData = $this->addChildData($childProducts->getItems(), $resultData, $bundleMap);
118+
119+
return $resultData;
120+
}
121+
122+
/**
123+
* Format and add children product data to bundle product response items.
124+
*
125+
* @param \Magento\Catalog\Model\Product[] $childrenProducts
126+
* @param array $resultData
127+
* @param array $bundleMap Map of parent skus and their children they contain [$parentSku => [$child1, $child2...]]
128+
* @return array
129+
*/
130+
private function addChildData(array $childrenProducts, array $resultData, array $bundleMap)
131+
{
132+
foreach ($childrenProducts as $childProduct) {
133+
$childData = $this->formatter->format($childProduct);
134+
foreach ($resultData as $productKey => $item) {
135+
if ($item['type_id'] === Bundle::TYPE_CODE
136+
&& in_array($childData['sku'], $bundleMap[$item['sku']])
137+
) {
138+
$categoryLinks = $this->productResource->getCategoryIds($childProduct);
139+
foreach ($categoryLinks as $position => $categoryLink) {
140+
$childData['category_links'][] = ['position' => $position, 'category_id' => $categoryLink];
141+
}
142+
foreach ($item['items'] as $itemKey => $bundleItem) {
143+
foreach (array_keys($bundleItem['options']) as $optionKey) {
144+
if ($childData['sku'] === $optionKey) {
145+
$resultData[$productKey]['items'][$itemKey]['options'][$optionKey]['product']
146+
= $childData;
147+
$resultData[$productKey]['items'][$itemKey]['options'][$optionKey]['label']
148+
= $childData['name'];
149+
}
150+
}
151+
}
152+
}
153+
}
154+
}
155+
156+
return $resultData;
157+
}
158+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# BundleGraphQl
2+
3+
**BundleGraphQl** provides type and resolver information for the GraphQl module
4+
to generate bundle product information.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "magento/module-bundle-graph-ql",
3+
"description": "N/A",
4+
"type": "magento2-module",
5+
"version": "100.0.0-dev",
6+
"require": {
7+
"php": "7.0.2|7.0.4|~7.0.6|~7.1.0",
8+
"magento/module-catalog": "101.2.*",
9+
"magento/module-bundle": "100.3.*",
10+
"magento/module-catalog-graph-ql": "100.0.*",
11+
"magento/framework": "100.3.*"
12+
},
13+
"license": [
14+
"OSL-3.0",
15+
"AFL-3.0"
16+
],
17+
"autoload": {
18+
"files": [
19+
"registration.php"
20+
],
21+
"psr-4": {
22+
"Magento\\BundleGraphQl\\": ""
23+
}
24+
}
25+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product">
10+
<plugin name="add_bundle_data" type="Magento\BundleGraphQl\Model\Plugin\Model\Resolver\Products\DataProvider\ProductPlugin"/>
11+
</type>
12+
<type name="Magento\CatalogGraphQl\Model\Resolver\Products\Query\Filter">
13+
<arguments>
14+
<argument name="postProcessors" xsi:type="array">
15+
<item name="bundle_processor" xsi:type="object">Magento\BundleGraphQl\Model\Resolver\Products\Query\BundleProductPostProcessor</item>
16+
</argument>
17+
</arguments>
18+
</type>
19+
</config>

0 commit comments

Comments
 (0)