123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\ConfigurableProduct\Model\Product;
- use Magento\Catalog\Api\Data\ProductInterface;
- use Magento\ConfigurableProduct\Api\OptionRepositoryInterface;
- use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
- use Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable as ResourceModelConfigurable;
- use Magento\Framework\EntityManager\Operation\ExtensionInterface;
- use Magento\ConfigurableProduct\Api\Data\OptionInterface;
- use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute;
- /**
- * Class SaveHandler
- */
- class SaveHandler implements ExtensionInterface
- {
- /**
- * @var OptionRepositoryInterface
- */
- private $optionRepository;
- /**
- * @var ResourceModelConfigurable
- */
- private $resourceModel;
- /**
- * SaveHandler constructor
- *
- * @param ResourceModelConfigurable $resourceModel
- * @param OptionRepositoryInterface $optionRepository
- */
- public function __construct(
- ResourceModelConfigurable $resourceModel,
- OptionRepositoryInterface $optionRepository
- ) {
- $this->resourceModel = $resourceModel;
- $this->optionRepository = $optionRepository;
- }
- /**
- * @param ProductInterface $entity
- * @param array $arguments
- * @return ProductInterface
- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
- */
- public function execute($entity, $arguments = [])
- {
- if ($entity->getTypeId() !== Configurable::TYPE_CODE) {
- return $entity;
- }
- $extensionAttributes = $entity->getExtensionAttributes();
- if ($extensionAttributes === null) {
- return $entity;
- }
- if ($extensionAttributes->getConfigurableProductOptions() !== null) {
- $this->deleteConfigurableProductAttributes($entity);
- }
- $configurableOptions = (array) $extensionAttributes->getConfigurableProductOptions();
- if (!empty($configurableOptions)) {
- $this->saveConfigurableProductAttributes($entity, $configurableOptions);
- }
- $configurableLinks = $extensionAttributes->getConfigurableProductLinks();
- if ($configurableLinks !== null) {
- $configurableLinks = (array)$configurableLinks;
- $this->resourceModel->saveProducts($entity, $configurableLinks);
- }
- return $entity;
- }
- /**
- * Save only newly created attributes for configurable product.
- *
- * @param ProductInterface $product
- * @param array $attributes
- * @return array
- */
- private function saveConfigurableProductAttributes(ProductInterface $product, array $attributes): array
- {
- $ids = [];
- $existingAttributeIds = [];
- foreach ($this->optionRepository->getList($product->getSku()) as $option) {
- $existingAttributeIds[$option->getAttributeId()] = $option;
- }
- /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\Attribute $attribute */
- foreach ($attributes as $attribute) {
- if (!in_array($attribute->getAttributeId(), array_keys($existingAttributeIds))
- || $this->isOptionChanged($existingAttributeIds[$attribute->getAttributeId()], $attribute)
- ) {
- $attribute->setId(null);
- $ids[] = $this->optionRepository->save($product->getSku(), $attribute);
- }
- }
- return $ids;
- }
- /**
- * Remove product attributes which no longer used.
- *
- * @param ProductInterface $product
- * @return void
- */
- private function deleteConfigurableProductAttributes(ProductInterface $product): void
- {
- $newAttributeIds = [];
- foreach ($product->getExtensionAttributes()->getConfigurableProductOptions() as $option) {
- $newAttributeIds[$option->getAttributeId()] = $option;
- }
- foreach ($this->optionRepository->getList($product->getSku()) as $option) {
- if (!in_array($option->getAttributeId(), array_keys($newAttributeIds))
- || $this->isOptionChanged($option, $newAttributeIds[$option->getAttributeId()])
- ) {
- $this->optionRepository->deleteById($product->getSku(), $option->getId());
- }
- }
- }
- /**
- * Check if existing option is changed.
- *
- * @param OptionInterface $option
- * @param Attribute $attribute
- * @return bool
- */
- private function isOptionChanged(OptionInterface $option, Attribute $attribute): bool
- {
- if ($option->getLabel() == $attribute->getLabel() && $option->getPosition() == $attribute->getPosition()) {
- return false;
- }
- return true;
- }
- }
|