Skip to content

Commit e9b2930

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

File tree

9 files changed

+75
-19
lines changed

9 files changed

+75
-19
lines changed

app/code/Magento/Bundle/Model/Plugin/Frontend/ProductIdentitiesExtender.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ public function __construct(BundleType $type)
3838
public function afterGetIdentities(CatalogProduct $product, array $identities): array
3939
{
4040
if ($product->getTypeId() !== BundleType::TYPE_CODE) {
41-
4241
return $identities;
4342
}
4443
foreach ($this->type->getChildrenIds($product->getEntityId()) as $childIds) {
4544
foreach ($childIds as $childId) {
4645
$identities[] = CatalogProduct::CACHE_TAG . '_' . $childId;
4746
}
4847
}
48+
4949
return array_unique($identities);
5050
}
5151
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,27 @@
55
*/
66
namespace Magento\Bundle\Model\Plugin;
77

8-
use Magento\Bundle\Model\Product\Type;
8+
use Magento\Bundle\Model\Product\Type as BundleType;
99
use Magento\Catalog\Model\Product as CatalogProduct;
1010

1111
class Product
1212
{
1313
/**
14-
* @var Type
14+
* @var BundleType
1515
*/
1616
private $type;
1717

1818
/**
19-
* @param Type $type
19+
* @param BundleType $type
2020
*/
21-
public function __construct(Type $type)
21+
public function __construct(BundleType $type)
2222
{
2323
$this->type = $type;
2424
}
2525

2626
/**
27+
* Add parent identities to product identities
28+
*
2729
* @param CatalogProduct $product
2830
* @param array $identities
2931
* @return string[]
@@ -32,6 +34,9 @@ public function afterGetIdentities(
3234
CatalogProduct $product,
3335
array $identities
3436
) {
37+
if ($product->getTypeId() !== BundleType::TYPE_CODE) {
38+
return $identities;
39+
}
3540
foreach ($this->type->getParentIdsByChild($product->getEntityId()) as $parentId) {
3641
$identities[] = CatalogProduct::CACHE_TAG . '_' . $parentId;
3742
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ class Type extends \Magento\Catalog\Model\Product\Type\AbstractType
173173
*/
174174
private $cacheChildrenIds = [];
175175

176+
/**
177+
* @var array
178+
*/
179+
private $cacheParentIdsByChild = [];
180+
176181
/**
177182
* @param \Magento\Catalog\Model\Product\Option $catalogProductOption
178183
* @param \Magento\Eav\Model\Config $eavConfig
@@ -306,7 +311,12 @@ public function getChildrenIds($parentId, $required = true)
306311
*/
307312
public function getParentIdsByChild($childId)
308313
{
309-
return $this->_bundleSelection->getParentIdsByChild($childId);
314+
$cacheKey = is_array($childId) ? implode('-', $childId) : $childId;
315+
if (!isset($this->cacheParentIdsByChild[$cacheKey])) {
316+
$this->cacheParentIdsByChild[$cacheKey] = $this->_bundleSelection->getParentIdsByChild($childId);
317+
}
318+
319+
return $this->cacheParentIdsByChild[$cacheKey];
310320
}
311321

312322
/**

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
use PHPUnit\Framework\MockObject\MockObject;
1414
use PHPUnit\Framework\TestCase;
1515

16-
class ProductTest extends TestCase
16+
class ProductIdentitiesExtenderTest extends TestCase
1717
{
1818
/** @var \Magento\Bundle\Model\Plugin\Product */
1919
private $plugin;

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ protected function setUp(): void
180180
->disableOriginalConstructor()
181181
->getMockForAbstractClass();
182182
$this->bundleModelSelection = $this->getMockBuilder(SelectionFactory::class)
183-
->setMethods(['create', 'getChildrenIds'])
183+
->setMethods(['create'])
184184
->disableOriginalConstructor()
185185
->getMock();
186186
$this->bundleFactory = $this->getMockBuilder(BundleFactory::class)
@@ -202,7 +202,7 @@ protected function setUp(): void
202202
->disableOriginalConstructor()
203203
->getMock();
204204
$this->bundleSelection = $this->getMockBuilder(ResourceSelection::class)
205-
->onlyMethods(['getChildrenIds'])
205+
->onlyMethods(['getChildrenIds', 'getParentIdsByChild'])
206206
->disableOriginalConstructor()
207207
->getMock();
208208

@@ -256,6 +256,31 @@ public function testGetChildrenIds()
256256
$this->assertEquals($childrenIds, $this->model->getChildrenIds($parentId, true));
257257
}
258258

259+
public function testGetParentIdsByChild()
260+
{
261+
$this->assertClassHasAttribute('cacheParentIdsByChild', Type::class);
262+
263+
$childId = 10;
264+
$parentIdsByChild = [
265+
[
266+
1 => [
267+
26 => "26",
268+
39 => "39",
269+
],
270+
],
271+
];
272+
273+
$this->bundleSelection->expects($this->once())
274+
->method('getParentIdsByChild')
275+
->with($childId)
276+
->willReturn($parentIdsByChild);
277+
$this->assertIsArray($this->model->getParentIdsByChild($childId));
278+
279+
$this->bundleSelection->expects($this->never())
280+
->method('getParentIdsByChild');
281+
$this->assertEquals($parentIdsByChild, $this->model->getParentIdsByChild($childId));
282+
}
283+
259284
/**
260285
* @return void
261286
* @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="add_child_identities_bundle" type="Magento\Bundle\Model\Plugin\Frontend\ProductIdentitiesExtender"/>
17+
<plugin name="add_bundle_child_identities" type="Magento\Bundle\Model\Plugin\Frontend\ProductIdentitiesExtender" sortOrder="100"/>
1818
</type>
1919
</config>

app/code/Magento/ConfigurableProduct/Model/Plugin/ProductIdentitiesExtender.php

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

88
namespace Magento\ConfigurableProduct\Model\Plugin;
99

10-
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
10+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
1111
use Magento\Catalog\Api\ProductRepositoryInterface;
1212
use Magento\Catalog\Model\Product;
1313

@@ -17,7 +17,7 @@
1717
class ProductIdentitiesExtender
1818
{
1919
/**
20-
* @var Configurable
20+
* @var ConfigurableType
2121
*/
2222
private $configurableType;
2323

@@ -27,10 +27,10 @@ class ProductIdentitiesExtender
2727
private $productRepository;
2828

2929
/**
30-
* @param Configurable $configurableType
30+
* @param ConfigurableType $configurableType
3131
* @param ProductRepositoryInterface $productRepository
3232
*/
33-
public function __construct(Configurable $configurableType, ProductRepositoryInterface $productRepository)
33+
public function __construct(ConfigurableType $configurableType, ProductRepositoryInterface $productRepository)
3434
{
3535
$this->configurableType = $configurableType;
3636
$this->productRepository = $productRepository;
@@ -46,10 +46,15 @@ public function __construct(Configurable $configurableType, ProductRepositoryInt
4646
*/
4747
public function afterGetIdentities(Product $subject, array $identities): array
4848
{
49+
if ($subject->getTypeId() !== ConfigurableType::TYPE_CODE) {
50+
return $identities;
51+
}
52+
$parentProductIdentities = [];
4953
foreach ($this->configurableType->getParentIdsByChild($subject->getId()) as $parentId) {
5054
$parentProduct = $this->productRepository->getById($parentId);
51-
$identities = array_merge($identities, $parentProduct->getIdentities());
55+
$parentProductIdentities[] = $parentProduct->getIdentities();
5256
}
57+
$identities = array_merge($identities, $parentProductIdentities);
5358

5459
return array_unique($identities);
5560
}

app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
214214
*/
215215
private $searchCriteriaBuilder;
216216

217+
/**
218+
* @var array
219+
*/
220+
private $cacheParentIdsByChild;
221+
217222
/**
218223
* @codingStandardsIgnoreStart/End
219224
* @param \Magento\Catalog\Model\Product\Option $catalogProductOption
@@ -364,7 +369,12 @@ public function getChildrenIds($parentId, $required = true)
364369
*/
365370
public function getParentIdsByChild($childId)
366371
{
367-
return $this->_catalogProductTypeConfigurable->getParentIdsByChild($childId);
372+
$cacheKey = is_array($childId) ? implode('-', $childId) : $childId;
373+
if (!isset($this->cacheParentIdsByChild[$cacheKey])) {
374+
$this->cacheParentIdsByChild[$cacheKey] = $this->_catalogProductTypeConfigurable->getParentIdsByChild($childId);
375+
}
376+
377+
return $this->cacheParentIdsByChild[$cacheKey];
368378
}
369379

370380
/**

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@
99
namespace Magento\Bundle\Model\Plugin\Frontend;
1010

1111
use Magento\Catalog\Api\ProductRepositoryInterface;
12+
use Magento\Catalog\Model\Product;
1213
use Magento\TestFramework\Helper\Bootstrap;
1314
use Magento\TestFramework\Interception\PluginList;
1415
use PHPUnit\Framework\TestCase;
1516

1617
/**
1718
* Test bundle fronted product plugin adds children products ids to bundle product identities.
1819
*/
19-
class ProductTest extends TestCase
20+
class ProductIdentitiesExtenderTest extends TestCase
2021
{
2122
/**
2223
* Check, product plugin is registered for storefront.
@@ -27,10 +28,10 @@ class ProductTest extends TestCase
2728
public function testProductIsRegistered(): void
2829
{
2930
$pluginInfo = Bootstrap::getObjectManager()->get(PluginList::class)
30-
->get(\Magento\Catalog\Model\Product::class, []);
31+
->get(Product::class, []);
3132
$this->assertSame(
3233
ProductIdentitiesExtender::class,
33-
$pluginInfo['add_child_identities_bundle']['instance']
34+
$pluginInfo['add_bundle_child_identities']['instance']
3435
);
3536
}
3637

0 commit comments

Comments
 (0)