LinkManagement.php 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. /**
  3. *
  4. * Copyright © Magento, Inc. All rights reserved.
  5. * See COPYING.txt for license details.
  6. */
  7. namespace Magento\ConfigurableProduct\Model;
  8. use Magento\Framework\Exception\InputException;
  9. use Magento\Framework\Exception\NoSuchEntityException;
  10. use Magento\Framework\Exception\StateException;
  11. class LinkManagement implements \Magento\ConfigurableProduct\Api\LinkManagementInterface
  12. {
  13. /**
  14. * @var \Magento\Catalog\Api\ProductRepositoryInterface
  15. */
  16. private $productRepository;
  17. /**
  18. * @var \Magento\Catalog\Api\Data\ProductInterfaceFactory
  19. */
  20. private $productFactory;
  21. /**
  22. * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable
  23. */
  24. private $configurableType;
  25. /**
  26. * @var \Magento\Framework\Api\DataObjectHelper
  27. */
  28. private $dataObjectHelper;
  29. /**
  30. * @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory;
  31. */
  32. private $optionsFactory;
  33. /**
  34. * @var \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory
  35. */
  36. private $attributeFactory;
  37. /**
  38. * Constructor
  39. *
  40. * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
  41. * @param \Magento\Catalog\Api\Data\ProductInterfaceFactory $productFactory
  42. * @param \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $configurableType
  43. * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
  44. * @param \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory $attributeFactory
  45. */
  46. public function __construct(
  47. \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
  48. \Magento\Catalog\Api\Data\ProductInterfaceFactory $productFactory,
  49. \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $configurableType,
  50. \Magento\Framework\Api\DataObjectHelper $dataObjectHelper,
  51. \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory $attributeFactory = null
  52. ) {
  53. $this->productRepository = $productRepository;
  54. $this->productFactory = $productFactory;
  55. $this->configurableType = $configurableType;
  56. $this->dataObjectHelper = $dataObjectHelper;
  57. $this->attributeFactory = $attributeFactory ?: \Magento\Framework\App\ObjectManager::getInstance()
  58. ->get(\Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory::class);
  59. }
  60. /**
  61. * {@inheritdoc}
  62. */
  63. public function getChildren($sku)
  64. {
  65. /** @var \Magento\Catalog\Model\Product $product */
  66. $product = $this->productRepository->get($sku);
  67. if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
  68. return [];
  69. }
  70. /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable $productTypeInstance */
  71. $productTypeInstance = $product->getTypeInstance();
  72. $productTypeInstance->setStoreFilter($product->getStoreId(), $product);
  73. $childrenList = [];
  74. /** @var \Magento\Catalog\Model\Product $child */
  75. foreach ($productTypeInstance->getUsedProducts($product) as $child) {
  76. $attributes = [];
  77. foreach ($child->getAttributes() as $attribute) {
  78. $attrCode = $attribute->getAttributeCode();
  79. $value = $child->getDataUsingMethod($attrCode) ?: $child->getData($attrCode);
  80. if (null !== $value) {
  81. $attributes[$attrCode] = $value;
  82. }
  83. }
  84. $attributes['store_id'] = $child->getStoreId();
  85. /** @var \Magento\Catalog\Api\Data\ProductInterface $productDataObject */
  86. $productDataObject = $this->productFactory->create();
  87. $this->dataObjectHelper->populateWithArray(
  88. $productDataObject,
  89. $attributes,
  90. \Magento\Catalog\Api\Data\ProductInterface::class
  91. );
  92. $childrenList[] = $productDataObject;
  93. }
  94. return $childrenList;
  95. }
  96. /**
  97. * {@inheritdoc}
  98. */
  99. public function addChild($sku, $childSku)
  100. {
  101. $product = $this->productRepository->get($sku);
  102. $child = $this->productRepository->get($childSku);
  103. $childrenIds = array_values($this->configurableType->getChildrenIds($product->getId())[0]);
  104. if (in_array($child->getId(), $childrenIds)) {
  105. throw new StateException(__('The product is already attached.'));
  106. }
  107. $configurableProductOptions = $product->getExtensionAttributes()->getConfigurableProductOptions();
  108. if (empty($configurableProductOptions)) {
  109. throw new StateException(__("The parent product doesn't have configurable product options."));
  110. }
  111. $attributeIds = [];
  112. foreach ($configurableProductOptions as $configurableProductOption) {
  113. $attributeCode = $configurableProductOption->getProductAttribute()->getAttributeCode();
  114. if (!$child->getData($attributeCode)) {
  115. throw new StateException(
  116. __(
  117. 'The child product doesn\'t have the "%1" attribute value. Verify the value and try again.',
  118. $attributeCode
  119. )
  120. );
  121. }
  122. $attributeIds[] = $configurableProductOption->getAttributeId();
  123. }
  124. $configurableOptionData = $this->getConfigurableAttributesData($attributeIds);
  125. /** @var \Magento\ConfigurableProduct\Helper\Product\Options\Factory $optionFactory */
  126. $optionFactory = $this->getOptionsFactory();
  127. $options = $optionFactory->create($configurableOptionData);
  128. $childrenIds[] = $child->getId();
  129. $product->getExtensionAttributes()->setConfigurableProductOptions($options);
  130. $product->getExtensionAttributes()->setConfigurableProductLinks($childrenIds);
  131. $this->productRepository->save($product);
  132. return true;
  133. }
  134. /**
  135. * {@inheritdoc}
  136. */
  137. public function removeChild($sku, $childSku)
  138. {
  139. $product = $this->productRepository->get($sku);
  140. if ($product->getTypeId() != \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) {
  141. throw new InputException(
  142. __('The product with the "%1" SKU isn\'t a configurable product.', $sku)
  143. );
  144. }
  145. $options = $product->getTypeInstance()->getUsedProducts($product);
  146. $ids = [];
  147. foreach ($options as $option) {
  148. if ($option->getSku() == $childSku) {
  149. continue;
  150. }
  151. $ids[] = $option->getId();
  152. }
  153. if (count($options) == count($ids)) {
  154. throw new NoSuchEntityException(
  155. __("The option that was requested doesn't exist. Verify the entity and try again.")
  156. );
  157. }
  158. $product->getExtensionAttributes()->setConfigurableProductLinks($ids);
  159. $this->productRepository->save($product);
  160. return true;
  161. }
  162. /**
  163. * Get Options Factory
  164. *
  165. * @return \Magento\ConfigurableProduct\Helper\Product\Options\Factory
  166. *
  167. * @deprecated 100.2.0
  168. */
  169. private function getOptionsFactory()
  170. {
  171. if (!$this->optionsFactory) {
  172. $this->optionsFactory = \Magento\Framework\App\ObjectManager::getInstance()
  173. ->get(\Magento\ConfigurableProduct\Helper\Product\Options\Factory::class);
  174. }
  175. return $this->optionsFactory;
  176. }
  177. /**
  178. * Get Configurable Attribute Data
  179. *
  180. * @param int[] $attributeIds
  181. * @return array
  182. */
  183. private function getConfigurableAttributesData($attributeIds)
  184. {
  185. $configurableAttributesData = [];
  186. $attributeValues = [];
  187. $attributes = $this->attributeFactory->create()
  188. ->getCollection()
  189. ->addFieldToFilter('attribute_id', $attributeIds)
  190. ->getItems();
  191. foreach ($attributes as $attribute) {
  192. foreach ($attribute->getOptions() as $option) {
  193. if ($option->getValue()) {
  194. $attributeValues[] = [
  195. 'label' => $option->getLabel(),
  196. 'attribute_id' => $attribute->getId(),
  197. 'value_index' => $option->getValue(),
  198. ];
  199. }
  200. }
  201. $configurableAttributesData[] =
  202. [
  203. 'attribute_id' => $attribute->getId(),
  204. 'code' => $attribute->getAttributeCode(),
  205. 'label' => $attribute->getStoreLabel(),
  206. 'values' => $attributeValues,
  207. ];
  208. }
  209. return $configurableAttributesData;
  210. }
  211. }