Skip to content

Commit 9e0df17

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-commerce/magento2ce into PR-04202023
2 parents 4e61fef + f6543e2 commit 9e0df17

22 files changed

+1190
-150
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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 ProductLinkManagementAddChildrenInterface
15+
{
16+
/**
17+
* Bulk add children operation
18+
*
19+
* @param \Magento\Catalog\Api\Data\ProductInterface $product
20+
* @param int $optionId
21+
* @param \Magento\Bundle\Api\Data\LinkInterface[] $linkedProducts
22+
* @throws \Magento\Framework\Exception\NoSuchEntityException
23+
* @throws \Magento\Framework\Exception\CouldNotSaveException
24+
* @throws \Magento\Framework\Exception\InputException
25+
* @return void
26+
*/
27+
public function addChildren(
28+
\Magento\Catalog\Api\Data\ProductInterface $product,
29+
int $optionId,
30+
array $linkedProducts
31+
);
32+
}

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

Lines changed: 108 additions & 43 deletions
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\ProductLinkManagementAddChildrenInterface;
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, ProductLinkManagementAddChildrenInterface
3435
{
3536
/**
3637
* @var ProductRepositoryInterface
@@ -189,19 +190,82 @@ public function saveChild(
189190
return true;
190191
}
191192

193+
/**
194+
* Linked product processing
195+
*
196+
* @param LinkInterface $linkedProduct
197+
* @param array $selections
198+
* @param int $optionId
199+
* @param ProductInterface $product
200+
* @param string $linkField
201+
* @param Bundle $resource
202+
* @return int
203+
* @throws CouldNotSaveException
204+
* @throws InputException
205+
* @throws NoSuchEntityException
206+
*/
207+
private function processLinkedProduct(
208+
LinkInterface $linkedProduct,
209+
array $selections,
210+
int $optionId,
211+
ProductInterface $product,
212+
string $linkField,
213+
Bundle $resource
214+
): int {
215+
$linkProductModel = $this->productRepository->get($linkedProduct->getSku());
216+
if ($linkProductModel->isComposite()) {
217+
throw new InputException(__('The bundle product can\'t contain another composite product.'));
218+
}
219+
220+
if ($selections) {
221+
foreach ($selections as $selection) {
222+
if ($selection['option_id'] == $optionId &&
223+
$selection['product_id'] == $linkProductModel->getEntityId() &&
224+
$selection['parent_product_id'] == $product->getData($linkField)) {
225+
if (!$product->getCopyFromView()) {
226+
throw new CouldNotSaveException(
227+
__(
228+
'Child with specified sku: "%1" already assigned to product: "%2"',
229+
[$linkedProduct->getSku(), $product->getSku()]
230+
)
231+
);
232+
}
233+
}
234+
}
235+
}
236+
237+
$selectionModel = $this->bundleSelection->create();
238+
$selectionModel = $this->mapProductLinkToBundleSelectionModel(
239+
$selectionModel,
240+
$linkedProduct,
241+
$product,
242+
(int)$linkProductModel->getEntityId()
243+
);
244+
245+
$selectionModel->setOptionId($optionId);
246+
247+
try {
248+
$selectionModel->save();
249+
$resource->addProductRelation($product->getData($linkField), $linkProductModel->getEntityId());
250+
} catch (\Exception $e) {
251+
throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
252+
}
253+
254+
return (int)$selectionModel->getId();
255+
}
256+
192257
/**
193258
* Fill selection model with product link data
194259
*
195260
* @param Selection $selectionModel
196261
* @param LinkInterface $productLink
197262
* @param string $linkedProductId
198263
* @param string $parentProductId
199-
*
200264
* @return Selection
201-
*
202265
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
203266
* @SuppressWarnings(PHPMD.NPathComplexity)
204-
* @deprecated use mapProductLinkToBundleSelectionModel
267+
* @deprecated
268+
* @see mapProductLinkToBundleSelectionModel
205269
*/
206270
protected function mapProductLinkToSelectionModel(
207271
Selection $selectionModel,
@@ -246,9 +310,9 @@ protected function mapProductLinkToSelectionModel(
246310
* @param LinkInterface $productLink
247311
* @param ProductInterface $parentProduct
248312
* @param int $linkedProductId
249-
* @param string $linkField
250313
* @return Selection
251314
* @throws NoSuchEntityException
315+
* @SuppressWarnings(PHPMD.NPathComplexity)
252316
*/
253317
private function mapProductLinkToBundleSelectionModel(
254318
Selection $selectionModel,
@@ -290,8 +354,6 @@ private function mapProductLinkToBundleSelectionModel(
290354

291355
/**
292356
* @inheritDoc
293-
*
294-
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
295357
*/
296358
public function addChild(
297359
ProductInterface $product,
@@ -325,49 +387,52 @@ public function addChild(
325387
/* @var $resource Bundle */
326388
$resource = $this->bundleFactory->create();
327389
$selections = $resource->getSelectionsData($product->getData($linkField));
328-
/** @var Product $linkProductModel */
329-
$linkProductModel = $this->productRepository->get($linkedProduct->getSku());
330-
if ($linkProductModel->isComposite()) {
331-
throw new InputException(__('The bundle product can\'t contain another composite product.'));
332-
}
333-
334-
if ($selections) {
335-
foreach ($selections as $selection) {
336-
if ($selection['option_id'] == $optionId &&
337-
$selection['product_id'] == $linkProductModel->getEntityId() &&
338-
$selection['parent_product_id'] == $product->getData($linkField)) {
339-
if (!$product->getCopyFromView()) {
340-
throw new CouldNotSaveException(
341-
__(
342-
'Child with specified sku: "%1" already assigned to product: "%2"',
343-
[$linkedProduct->getSku(), $product->getSku()]
344-
)
345-
);
346-
}
347-
348-
return $this->bundleSelection->create()->load($linkProductModel->getEntityId());
349-
}
350-
}
351-
}
352-
353-
$selectionModel = $this->bundleSelection->create();
354-
$selectionModel = $this->mapProductLinkToBundleSelectionModel(
355-
$selectionModel,
390+
return $this->processLinkedProduct(
356391
$linkedProduct,
392+
$selections,
393+
(int)$optionId,
357394
$product,
358-
(int)$linkProductModel->getEntityId()
395+
$linkField,
396+
$resource
359397
);
398+
}
360399

361-
$selectionModel->setOptionId($optionId);
400+
/**
401+
* @inheritDoc
402+
*/
403+
public function addChildren(
404+
ProductInterface $product,
405+
int $optionId,
406+
array $linkedProducts
407+
) : void {
408+
if ($product->getTypeId() != Product\Type::TYPE_BUNDLE) {
409+
throw new InputException(
410+
__('The product with the "%1" SKU isn\'t a bundle product.', $product->getSku())
411+
);
412+
}
362413

363-
try {
364-
$selectionModel->save();
365-
$resource->addProductRelation($product->getData($linkField), $linkProductModel->getEntityId());
366-
} catch (\Exception $e) {
367-
throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
414+
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
415+
$options = $this->optionCollection->create();
416+
$options->setIdFilter($optionId);
417+
$options->setProductLinkFilter($product->getData($linkField));
418+
$existingOption = $options->getFirstItem();
419+
420+
if (!$existingOption->getId()) {
421+
throw new InputException(
422+
__(
423+
'Product with specified sku: "%1" does not contain option: "%2"',
424+
[$product->getSku(), $optionId]
425+
)
426+
);
368427
}
369428

370-
return (int)$selectionModel->getId();
429+
/* @var $resource Bundle */
430+
$resource = $this->bundleFactory->create();
431+
$selections = $resource->getSelectionsData($product->getData($linkField));
432+
433+
foreach ($linkedProducts as $linkedProduct) {
434+
$this->processLinkedProduct($linkedProduct, $selections, $optionId, $product, $linkField, $resource);
435+
}
371436
}
372437

373438
/**

0 commit comments

Comments
 (0)