|
10 | 10 | use Magento\Bundle\Api\Data\LinkInterface;
|
11 | 11 | use Magento\Bundle\Api\Data\LinkInterfaceFactory;
|
12 | 12 | use Magento\Bundle\Api\Data\OptionInterface;
|
| 13 | +use Magento\Bundle\Api\ProductLinkManagementAddChildrenInterface; |
13 | 14 | use Magento\Bundle\Api\ProductLinkManagementInterface;
|
14 | 15 | use Magento\Bundle\Model\Product\Type;
|
15 | 16 | use Magento\Bundle\Model\ResourceModel\Bundle;
|
|
30 | 31 | *
|
31 | 32 | * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
32 | 33 | */
|
33 |
| -class LinkManagement implements ProductLinkManagementInterface |
| 34 | +class LinkManagement implements ProductLinkManagementInterface, ProductLinkManagementAddChildrenInterface |
34 | 35 | {
|
35 | 36 | /**
|
36 | 37 | * @var ProductRepositoryInterface
|
@@ -189,19 +190,82 @@ public function saveChild(
|
189 | 190 | return true;
|
190 | 191 | }
|
191 | 192 |
|
| 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 | + |
192 | 257 | /**
|
193 | 258 | * Fill selection model with product link data
|
194 | 259 | *
|
195 | 260 | * @param Selection $selectionModel
|
196 | 261 | * @param LinkInterface $productLink
|
197 | 262 | * @param string $linkedProductId
|
198 | 263 | * @param string $parentProductId
|
199 |
| - * |
200 | 264 | * @return Selection
|
201 |
| - * |
202 | 265 | * @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
203 | 266 | * @SuppressWarnings(PHPMD.NPathComplexity)
|
204 |
| - * @deprecated use mapProductLinkToBundleSelectionModel |
| 267 | + * @deprecated |
| 268 | + * @see mapProductLinkToBundleSelectionModel |
205 | 269 | */
|
206 | 270 | protected function mapProductLinkToSelectionModel(
|
207 | 271 | Selection $selectionModel,
|
@@ -246,9 +310,9 @@ protected function mapProductLinkToSelectionModel(
|
246 | 310 | * @param LinkInterface $productLink
|
247 | 311 | * @param ProductInterface $parentProduct
|
248 | 312 | * @param int $linkedProductId
|
249 |
| - * @param string $linkField |
250 | 313 | * @return Selection
|
251 | 314 | * @throws NoSuchEntityException
|
| 315 | + * @SuppressWarnings(PHPMD.NPathComplexity) |
252 | 316 | */
|
253 | 317 | private function mapProductLinkToBundleSelectionModel(
|
254 | 318 | Selection $selectionModel,
|
@@ -290,8 +354,6 @@ private function mapProductLinkToBundleSelectionModel(
|
290 | 354 |
|
291 | 355 | /**
|
292 | 356 | * @inheritDoc
|
293 |
| - * |
294 |
| - * @SuppressWarnings(PHPMD.CyclomaticComplexity) |
295 | 357 | */
|
296 | 358 | public function addChild(
|
297 | 359 | ProductInterface $product,
|
@@ -325,49 +387,52 @@ public function addChild(
|
325 | 387 | /* @var $resource Bundle */
|
326 | 388 | $resource = $this->bundleFactory->create();
|
327 | 389 | $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( |
356 | 391 | $linkedProduct,
|
| 392 | + $selections, |
| 393 | + (int)$optionId, |
357 | 394 | $product,
|
358 |
| - (int)$linkProductModel->getEntityId() |
| 395 | + $linkField, |
| 396 | + $resource |
359 | 397 | );
|
| 398 | + } |
360 | 399 |
|
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 | + } |
362 | 413 |
|
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 | + ); |
368 | 427 | }
|
369 | 428 |
|
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 | + } |
371 | 436 | }
|
372 | 437 |
|
373 | 438 | /**
|
|
0 commit comments