Skip to content

Commit cd8fe10

Browse files
committed
MC-38593: Complex products children ids are not cached in Type class leading to multiple unnecessary db requests
1 parent 226b08d commit cd8fe10

File tree

6 files changed

+71
-12
lines changed

6 files changed

+71
-12
lines changed

app/code/Magento/Bundle/Model/Plugin/Frontend/Product.php renamed to app/code/Magento/Bundle/Model/Plugin/Frontend/ProductIdentitiesExtender.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,23 @@
77

88
namespace Magento\Bundle\Model\Plugin\Frontend;
99

10-
use Magento\Bundle\Model\Product\Type;
10+
use Magento\Bundle\Model\Product\Type as BundleType;
1111
use Magento\Catalog\Model\Product as CatalogProduct;
1212

1313
/**
1414
* Add child identities to product identities on storefront.
1515
*/
16-
class Product
16+
class ProductIdentitiesExtender
1717
{
1818
/**
19-
* @var Type
19+
* @var BundleType
2020
*/
2121
private $type;
2222

2323
/**
24-
* @param Type $type
24+
* @param BundleType $type
2525
*/
26-
public function __construct(Type $type)
26+
public function __construct(BundleType $type)
2727
{
2828
$this->type = $type;
2929
}
@@ -37,12 +37,15 @@ public function __construct(Type $type)
3737
*/
3838
public function afterGetIdentities(CatalogProduct $product, array $identities): array
3939
{
40+
if ($product->getTypeId() !== BundleType::TYPE_CODE) {
41+
42+
return $identities;
43+
}
4044
foreach ($this->type->getChildrenIds($product->getEntityId()) as $childIds) {
4145
foreach ($childIds as $childId) {
4246
$identities[] = CatalogProduct::CACHE_TAG . '_' . $childId;
4347
}
4448
}
45-
4649
return array_unique($identities);
4750
}
4851
}

app/code/Magento/Bundle/Model/Product/Type.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType
168168
*/
169169
private $arrayUtility;
170170

171+
/**
172+
* @var array
173+
*/
174+
private $cacheChildrenIds = [];
175+
171176
/**
172177
* @param \Magento\Catalog\Model\Product\Option $catalogProductOption
173178
* @param \Magento\Eav\Model\Config $eavConfig
@@ -285,7 +290,12 @@ public function getRelationInfo()
285290
*/
286291
public function getChildrenIds($parentId, $required = true)
287292
{
288-
return $this->_bundleSelection->getChildrenIds($parentId, $required);
293+
$cacheKey = $parentId . '-' . ($required ? 1 : 0);
294+
if (!isset($this->cacheChildrenIds[$cacheKey])) {
295+
$this->cacheChildrenIds[$cacheKey] = $this->_bundleSelection->getChildrenIds($parentId, $required);
296+
}
297+
298+
return $this->cacheChildrenIds[$cacheKey];
289299
}
290300

291301
/**

app/code/Magento/Bundle/Test/Unit/Model/Plugin/Frontend/ProductTest.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace Magento\Bundle\Test\Unit\Model\Plugin\Frontend;
99

10-
use Magento\Bundle\Model\Plugin\Frontend\Product as ProductPlugin;
10+
use Magento\Bundle\Model\Plugin\Frontend\ProductIdentitiesExtender as ProductPlugin;
1111
use Magento\Bundle\Model\Product\Type;
1212
use Magento\Catalog\Model\Product;
1313
use PHPUnit\Framework\MockObject\MockObject;
@@ -28,7 +28,7 @@ protected function setUp(): void
2828
{
2929
$this->product = $this->getMockBuilder(Product::class)
3030
->disableOriginalConstructor()
31-
->setMethods(['getEntityId'])
31+
->setMethods(['getEntityId', 'getTypeId'])
3232
->getMock();
3333

3434
$this->type = $this->getMockBuilder(Type::class)
@@ -65,6 +65,9 @@ public function testAfterGetIdentities()
6565
$this->product->expects($this->once())
6666
->method('getEntityId')
6767
->willReturn($id);
68+
$this->product->expects($this->once())
69+
->method('getTypeId')
70+
->willReturn(Type::TYPE_CODE);
6871
$this->type->expects($this->once())
6972
->method('getChildrenIds')
7073
->with($id)

app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Bundle\Model\Product\Type;
1212
use Magento\Bundle\Model\ResourceModel\BundleFactory;
1313
use Magento\Bundle\Model\ResourceModel\Option\Collection;
14+
use Magento\Bundle\Model\ResourceModel\Selection as ResourceSelection;
1415
use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor;
1516
use Magento\Bundle\Model\ResourceModel\Selection\Collection as SelectionCollection;
1617
use Magento\Bundle\Model\ResourceModel\Selection\CollectionFactory;
@@ -45,6 +46,7 @@
4546
/**
4647
* Test for bundle product type
4748
*
49+
* @SuppressWarnings(PHPMD.TooManyFields)
4850
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
4951
*/
5052
class TypeTest extends TestCase
@@ -124,6 +126,11 @@ class TypeTest extends TestCase
124126
*/
125127
private $catalogRuleProcessor;
126128

129+
/**
130+
* @var ResourceSelection|MockObject
131+
*/
132+
private $bundleSelection;
133+
127134
/**
128135
* @return void
129136
*/
@@ -173,7 +180,7 @@ protected function setUp(): void
173180
->disableOriginalConstructor()
174181
->getMockForAbstractClass();
175182
$this->bundleModelSelection = $this->getMockBuilder(SelectionFactory::class)
176-
->setMethods(['create'])
183+
->setMethods(['create', 'getChildrenIds'])
177184
->disableOriginalConstructor()
178185
->getMock();
179186
$this->bundleFactory = $this->getMockBuilder(BundleFactory::class)
@@ -194,13 +201,18 @@ protected function setUp(): void
194201
$this->catalogRuleProcessor = $this->getMockBuilder(CollectionProcessor::class)
195202
->disableOriginalConstructor()
196203
->getMock();
204+
$this->bundleSelection = $this->getMockBuilder(ResourceSelection::class)
205+
->onlyMethods(['getChildrenIds'])
206+
->disableOriginalConstructor()
207+
->getMock();
197208

198209
$objectHelper = new ObjectManager($this);
199210
$this->model = $objectHelper->getObject(
200211
Type::class,
201212
[
202213
'bundleModelSelection' => $this->bundleModelSelection,
203214
'bundleFactory' => $this->bundleFactory,
215+
'bundleSelection' => $this->bundleSelection,
204216
'bundleCollection' => $this->bundleCollectionFactory,
205217
'bundleOption' => $this->bundleOptionFactory,
206218
'catalogData' => $this->catalogData,
@@ -216,6 +228,34 @@ protected function setUp(): void
216228
);
217229
}
218230

231+
/**
232+
* @return void
233+
*/
234+
public function testGetChildrenIds()
235+
{
236+
$this->assertClassHasAttribute('cacheChildrenIds', Type::class);
237+
238+
$parentId = 1;
239+
$childrenIds = [
240+
[
241+
1 => [
242+
26 => "26",
243+
39 => "39",
244+
],
245+
],
246+
];
247+
248+
$this->bundleSelection->expects($this->once())
249+
->method('getChildrenIds')
250+
->with($parentId, true)
251+
->willReturn($childrenIds);
252+
$this->assertIsArray($this->model->getChildrenIds($parentId, true));
253+
254+
$this->bundleSelection->expects($this->never())
255+
->method('getChildrenIds');
256+
$this->assertEquals($childrenIds, $this->model->getChildrenIds($parentId, true));
257+
}
258+
219259
/**
220260
* @return void
221261
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)

app/code/Magento/Bundle/etc/frontend/di.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
</arguments>
1515
</type>
1616
<type name="Magento\Catalog\Model\Product">
17-
<plugin name="bundle" type="Magento\Bundle\Model\Plugin\Frontend\Product" sortOrder="100" />
17+
<plugin name="add_child_identities_bundle" type="Magento\Bundle\Model\Plugin\Frontend\ProductIdentitiesExtender"/>
1818
</type>
1919
</config>

dev/tests/integration/testsuite/Magento/Bundle/Model/Plugin/Frontend/ProductTest.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ public function testProductIsRegistered(): void
2828
{
2929
$pluginInfo = Bootstrap::getObjectManager()->get(PluginList::class)
3030
->get(\Magento\Catalog\Model\Product::class, []);
31-
$this->assertSame(Product::class, $pluginInfo['bundle']['instance']);
31+
$this->assertSame(
32+
ProductIdentitiesExtender::class,
33+
$pluginInfo['add_child_identities_bundle']['instance']
34+
);
3235
}
3336

3437
/**

0 commit comments

Comments
 (0)