Skip to content

Commit f0cd2ff

Browse files
committed
ACP2E-1347: Bundle product save slow
1 parent 5118cde commit f0cd2ff

File tree

4 files changed

+119
-5
lines changed

4 files changed

+119
-5
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
*
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Magento\Bundle\Api;
10+
11+
/**
12+
* Interface for Bulk children addition
13+
*/
14+
interface ProductAddChildrenInterface
15+
{
16+
/**
17+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
18+
* @param int $optionId
19+
* @param \Magento\Bundle\Api\Data\LinkInterface[] $linkedProducts
20+
* @throws \Magento\Framework\Exception\NoSuchEntityException
21+
* @throws \Magento\Framework\Exception\CouldNotSaveException
22+
* @throws \Magento\Framework\Exception\InputException
23+
* @return void
24+
*/
25+
public function addChildren(
26+
\Magento\Catalog\Api\Data\ProductInterface $product,
27+
int $optionId,
28+
array $linkedProducts
29+
);
30+
}

app/code/Magento/Bundle/Model/LinkManagement.php

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use Magento\Bundle\Api\Data\LinkInterface;
1111
use Magento\Bundle\Api\Data\LinkInterfaceFactory;
1212
use Magento\Bundle\Api\Data\OptionInterface;
13+
use Magento\Bundle\Api\ProductAddChildrenInterface;
1314
use Magento\Bundle\Api\ProductLinkManagementInterface;
1415
use Magento\Bundle\Model\Product\Type;
1516
use Magento\Bundle\Model\ResourceModel\Bundle;
@@ -30,7 +31,7 @@
3031
*
3132
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
3233
*/
33-
class LinkManagement implements ProductLinkManagementInterface
34+
class LinkManagement implements ProductLinkManagementInterface, ProductAddChildrenInterface
3435
{
3536
/**
3637
* @var ProductRepositoryInterface
@@ -370,6 +371,81 @@ public function addChild(
370371
return (int)$selectionModel->getId();
371372
}
372373

374+
/**
375+
* @inheritDoc
376+
*/
377+
public function addChildren(
378+
ProductInterface $product,
379+
int $optionId,
380+
array $linkedProducts
381+
) : void {
382+
if ($product->getTypeId() != Product\Type::TYPE_BUNDLE) {
383+
throw new InputException(
384+
__('The product with the "%1" SKU isn\'t a bundle product.', $product->getSku())
385+
);
386+
}
387+
388+
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
389+
$options = $this->optionCollection->create();
390+
$options->setIdFilter($optionId);
391+
$options->setProductLinkFilter($product->getData($linkField));
392+
$existingOption = $options->getFirstItem();
393+
394+
if (!$existingOption->getId()) {
395+
throw new InputException(
396+
__(
397+
'Product with specified sku: "%1" does not contain option: "%2"',
398+
[$product->getSku(), $optionId]
399+
)
400+
);
401+
}
402+
403+
/* @var $resource Bundle */
404+
$resource = $this->bundleFactory->create();
405+
$selections = $resource->getSelectionsData($product->getData($linkField));
406+
407+
foreach ($linkedProducts as $linkedProduct) {
408+
$linkProductModel = $this->productRepository->get($linkedProduct->getSku());
409+
if ($linkProductModel->isComposite()) {
410+
throw new InputException(__('The bundle product can\'t contain another composite product.'));
411+
}
412+
413+
if ($selections) {
414+
foreach ($selections as $selection) {
415+
if ($selection['option_id'] == $optionId &&
416+
$selection['product_id'] == $linkProductModel->getEntityId() &&
417+
$selection['parent_product_id'] == $product->getData($linkField)) {
418+
if (!$product->getCopyFromView()) {
419+
throw new CouldNotSaveException(
420+
__(
421+
'Child with specified sku: "%1" already assigned to product: "%2"',
422+
[$linkedProduct->getSku(), $product->getSku()]
423+
)
424+
);
425+
}
426+
}
427+
}
428+
}
429+
430+
$selectionModel = $this->bundleSelection->create();
431+
$selectionModel = $this->mapProductLinkToBundleSelectionModel(
432+
$selectionModel,
433+
$linkedProduct,
434+
$product,
435+
(int)$linkProductModel->getEntityId()
436+
);
437+
438+
$selectionModel->setOptionId($optionId);
439+
440+
try {
441+
$selectionModel->save();
442+
$resource->addProductRelation($product->getData($linkField), $linkProductModel->getEntityId());
443+
} catch (\Exception $e) {
444+
throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
445+
}
446+
}
447+
}
448+
373449
/**
374450
* @inheritDoc
375451
*/

app/code/Magento/Bundle/Model/Option/SaveAction.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Bundle\Api\Data\LinkInterface;
1212
use Magento\Bundle\Api\Data\OptionInterface;
1313
use Magento\Bundle\Api\ProductLinkManagementInterface;
14+
use Magento\Bundle\Api\ProductAddChildrenInterface;
1415
use Magento\Bundle\Model\Product\Type;
1516
use Magento\Bundle\Model\ResourceModel\Option;
1617
use Magento\Bundle\Model\ResourceModel\Option\Collection;
@@ -48,25 +49,33 @@ class SaveAction
4849
*/
4950
private $linkManagement;
5051

52+
/**
53+
* @var ProductAddChildrenInterface
54+
*/
55+
private $addChildren;
56+
5157
/**
5258
* @param Option $optionResource
5359
* @param MetadataPool $metadataPool
5460
* @param Type $type
5561
* @param ProductLinkManagementInterface $linkManagement
5662
* @param StoreManagerInterface|null $storeManager
63+
* @param ProductAddChildrenInterface|null $addChildren
5764
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
5865
*/
5966
public function __construct(
6067
Option $optionResource,
6168
MetadataPool $metadataPool,
6269
Type $type,
6370
ProductLinkManagementInterface $linkManagement,
64-
?StoreManagerInterface $storeManager = null
71+
?StoreManagerInterface $storeManager = null,
72+
?ProductAddChildrenInterface $addChildren = null
6573
) {
6674
$this->optionResource = $optionResource;
6775
$this->metadataPool = $metadataPool;
6876
$this->type = $type;
6977
$this->linkManagement = $linkManagement;
78+
$this->addChildren = $addChildren;
7079
}
7180

7281
/**
@@ -204,9 +213,7 @@ private function updateOptionSelection(ProductInterface $product, OptionInterfac
204213
$linkedProduct->getSku()
205214
);
206215
}
207-
foreach ($linksToAdd as $linkedProduct) {
208-
$this->linkManagement->addChild($product, $option->getOptionId(), $linkedProduct);
209-
}
216+
$this->addChildren->addChildren($product, $option->getOptionId(), $linksToAdd);
210217
}
211218

212219
/**

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<preference for="Magento\Bundle\Api\ProductOptionTypeListInterface" type="Magento\Bundle\Model\OptionTypeList" />
1010
<preference for="Magento\Bundle\Api\Data\OptionTypeInterface" type="Magento\Bundle\Model\Source\Option\Type" />
1111
<preference for="Magento\Bundle\Api\ProductLinkManagementInterface" type="Magento\Bundle\Model\LinkManagement" />
12+
<preference for="Magento\Bundle\Api\ProductAddChildrenInterface" type="Magento\Bundle\Model\LinkManagement" />
1213
<preference for="Magento\Bundle\Api\Data\LinkInterface" type="Magento\Bundle\Model\Link" />
1314
<preference for="Magento\Bundle\Api\ProductOptionRepositoryInterface" type="Magento\Bundle\Model\OptionRepository" />
1415
<preference for="Magento\Bundle\Api\ProductOptionManagementInterface" type="Magento\Bundle\Model\OptionManagement" />

0 commit comments

Comments
 (0)