Skip to content

Commit 7466c8f

Browse files
committed
ACP2E-326: [Magento Cloud] Disabled virtual products showing in Bundle product option collection in GraphQL response
- With test
1 parent 203a44f commit 7466c8f

File tree

6 files changed

+570
-19
lines changed

6 files changed

+570
-19
lines changed

app/code/Magento/BundleGraphQl/Model/Resolver/Links/Collection.php

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@
1111
use Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory;
1212
use Magento\Bundle\Model\ResourceModel\Selection\Collection as LinkCollection;
1313
use Magento\Framework\App\ObjectManager;
14+
use Magento\Framework\Exception\NoSuchEntityException;
15+
use Magento\Framework\Exception\RuntimeException;
1416
use Magento\Framework\GraphQl\Query\EnumLookup;
1517
use Magento\Framework\GraphQl\Query\Uid;
18+
use Magento\Catalog\Api\ProductRepositoryInterface;
19+
use Zend_Db_Select_Exception;
1620

1721
/**
1822
* Collection to fetch link data at resolution time.
@@ -47,20 +51,29 @@ class Collection
4751
/** @var Uid */
4852
private $uidEncoder;
4953

54+
/**
55+
* @var ProductRepositoryInterface
56+
*/
57+
private $productRepository;
58+
5059
/**
5160
* @param CollectionFactory $linkCollectionFactory
5261
* @param EnumLookup $enumLookup
5362
* @param Uid|null $uidEncoder
63+
* @param ProductRepositoryInterface|null $productRepository
5464
*/
5565
public function __construct(
5666
CollectionFactory $linkCollectionFactory,
5767
EnumLookup $enumLookup,
58-
Uid $uidEncoder = null
68+
Uid $uidEncoder = null,
69+
?ProductRepositoryInterface $productRepository = null
5970
) {
6071
$this->linkCollectionFactory = $linkCollectionFactory;
6172
$this->enumLookup = $enumLookup;
6273
$this->uidEncoder = $uidEncoder ?: ObjectManager::getInstance()
6374
->get(Uid::class);
75+
$this->productRepository = $productRepository ?: ObjectManager::getInstance()
76+
->get(ProductRepositoryInterface::class);
6477
}
6578

6679
/**
@@ -85,6 +98,9 @@ public function addIdFilters(int $optionId, int $parentId) : void
8598
*
8699
* @param int $optionId
87100
* @return array
101+
* @throws NoSuchEntityException
102+
* @throws RuntimeException
103+
* @throws Zend_Db_Select_Exception
88104
*/
89105
public function getLinksForOptionId(int $optionId) : array
90106
{
@@ -101,6 +117,10 @@ public function getLinksForOptionId(int $optionId) : array
101117
* Fetch link data and return in array format. Keys for links will be their option Ids.
102118
*
103119
* @return array
120+
* @throws NoSuchEntityException
121+
* @throws RuntimeException
122+
* @throws Zend_Db_Select_Exception
123+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
104124
*/
105125
private function fetch() : array
106126
{
@@ -123,26 +143,33 @@ private function fetch() : array
123143

124144
/** @var Selection $link */
125145
foreach ($linkCollection as $link) {
146+
$productDetails = [];
126147
$data = $link->getData();
127-
$formattedLink = [
128-
'price' => $link->getSelectionPriceValue(),
129-
'position' => $link->getPosition(),
130-
'id' => $link->getSelectionId(),
131-
'uid' => $this->uidEncoder->encode((string) $link->getSelectionId()),
132-
'qty' => (float)$link->getSelectionQty(),
133-
'quantity' => (float)$link->getSelectionQty(),
134-
'is_default' => (bool)$link->getIsDefault(),
135-
'price_type' => $this->enumLookup->getEnumValueFromField(
136-
'PriceTypeEnum',
137-
(string)$link->getSelectionPriceType()
138-
) ?: 'DYNAMIC',
139-
'can_change_quantity' => $link->getSelectionCanChangeQty(),
140-
];
141-
$data = array_replace($data, $formattedLink);
142-
if (!isset($this->links[$link->getOptionId()])) {
143-
$this->links[$link->getOptionId()] = [];
148+
if (isset($data['product_id'])) {
149+
$productDetails = $this->productRepository->getById($data['product_id']);
150+
}
151+
152+
if ($productDetails && $productDetails->getIsSalable()) {
153+
$formattedLink = [
154+
'price' => $link->getSelectionPriceValue(),
155+
'position' => $link->getPosition(),
156+
'id' => $link->getSelectionId(),
157+
'uid' => $this->uidEncoder->encode((string)$link->getSelectionId()),
158+
'qty' => (float)$link->getSelectionQty(),
159+
'quantity' => (float)$link->getSelectionQty(),
160+
'is_default' => (bool)$link->getIsDefault(),
161+
'price_type' => $this->enumLookup->getEnumValueFromField(
162+
'PriceTypeEnum',
163+
(string)$link->getSelectionPriceType()
164+
) ?: 'DYNAMIC',
165+
'can_change_quantity' => $link->getSelectionCanChangeQty(),
166+
];
167+
$data = array_replace($data, $formattedLink);
168+
if (!isset($this->links[$link->getOptionId()])) {
169+
$this->links[$link->getOptionId()] = [];
170+
}
171+
$this->links[$link->getOptionId()][] = $data;
144172
}
145-
$this->links[$link->getOptionId()][] = $data;
146173
}
147174

148175
return $this->links;
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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\GraphQl\Bundle;
9+
10+
use Exception;
11+
use Magento\TestFramework\Helper\Bootstrap;
12+
use Magento\TestFramework\Helper\CompareArraysRecursively;
13+
use Magento\TestFramework\TestCase\GraphQlAbstract;
14+
15+
/**
16+
* class BundleProductWithDisabledProductTest
17+
*
18+
* Test Bundle product with disabled product and verify graphQl response
19+
*/
20+
class BundleProductWithDisabledProductTest extends GraphQlAbstract
21+
{
22+
/**
23+
* @var CompareArraysRecursively
24+
*/
25+
private $compareArraysRecursively;
26+
27+
/**
28+
* @inheritDoc
29+
*/
30+
protected function setUp(): void
31+
{
32+
$objectManager = Bootstrap::getObjectManager();
33+
$this->compareArraysRecursively = $objectManager->create(CompareArraysRecursively::class);
34+
}
35+
36+
/**
37+
* Test Bundle product with disabled product test.
38+
*
39+
* @magentoApiDataFixture Magento/Bundle/_files/bundle_product_with_disabled_product_options.php
40+
*
41+
* @throws Exception
42+
*/
43+
public function testBundleProductWithMultipleOptionsWithDisabledProduct(): void
44+
{
45+
$categorySku = 'c1';
46+
$query
47+
= <<<QUERY
48+
{
49+
categoryList(filters: {url_path: {eq: "{$categorySku}"}}) {
50+
children_count
51+
id
52+
url_path
53+
url_key
54+
id
55+
products {
56+
total_count
57+
items {
58+
... on BundleProduct {
59+
id
60+
categories {
61+
id
62+
name
63+
description
64+
}
65+
dynamic_price
66+
price_range {
67+
minimum_price {
68+
regular_price {
69+
value
70+
currency
71+
}
72+
}
73+
maximum_price {
74+
regular_price {
75+
value
76+
currency
77+
}
78+
}
79+
}
80+
sku
81+
name
82+
short_description {
83+
html
84+
}
85+
description {
86+
html
87+
}
88+
stock_status
89+
__typename
90+
url_key
91+
items {
92+
position
93+
uid
94+
option_id
95+
options {
96+
uid
97+
label
98+
id
99+
price
100+
quantity
101+
product {
102+
... on VirtualProduct {
103+
sku
104+
stock_status
105+
name
106+
}
107+
price_range {
108+
minimum_price {
109+
regular_price {
110+
value
111+
currency
112+
}
113+
}
114+
maximum_price {
115+
regular_price {
116+
value
117+
currency
118+
}
119+
}
120+
}
121+
}
122+
}
123+
}
124+
}
125+
}
126+
}
127+
}
128+
}
129+
QUERY;
130+
131+
$response = $this->graphQlQuery($query);
132+
$this->assertBundleProduct($response);
133+
}
134+
135+
/**
136+
* Assert bundle product response.
137+
*
138+
* @param array $response
139+
*/
140+
private function assertBundleProduct(array $response): void
141+
{
142+
$this->assertNotEmpty(
143+
$response['categoryList'][0]['products']['items'],
144+
'Precondition failed: "items" must not be empty'
145+
);
146+
$productItems = end($response['categoryList'][0]['products']['items'])['items'];
147+
$this->assertEquals(3, count($productItems[0]['options']));
148+
$this->assertEquals('virtual1', $productItems[0]['options'][0]['product']['sku']);
149+
$this->assertEquals('virtual2', $productItems[0]['options'][1]['product']['sku']);
150+
$this->assertEquals('virtual3', $productItems[0]['options'][2]['product']['sku']);
151+
$this->assertEquals(3, count($productItems[1]['options']));
152+
$this->assertEquals('virtual1', $productItems[1]['options'][0]['product']['sku']);
153+
$this->assertEquals('virtual2', $productItems[1]['options'][1]['product']['sku']);
154+
$this->assertEquals('virtual3', $productItems[1]['options'][2]['product']['sku']);
155+
}
156+
}

0 commit comments

Comments
 (0)