|
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