PageRenderTime 43ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/magento/module-bundle/Model/LinkManagement.php

https://gitlab.com/yousafsyed/easternglamor
PHP | 357 lines | 240 code | 38 blank | 79 comment | 34 complexity | 47c85d3983e24939f50701b209c2eea5 MD5 | raw file
  1. <?php
  2. /**
  3. *
  4. * Copyright © 2016 Magento. All rights reserved.
  5. * See COPYING.txt for license details.
  6. */
  7. namespace Magento\Bundle\Model;
  8. use Magento\Catalog\Api\ProductRepositoryInterface;
  9. use Magento\Framework\Exception\CouldNotSaveException;
  10. use Magento\Framework\Exception\InputException;
  11. /**
  12. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  13. */
  14. class LinkManagement implements \Magento\Bundle\Api\ProductLinkManagementInterface
  15. {
  16. /**
  17. * @var \Magento\Catalog\Api\ProductRepositoryInterface
  18. */
  19. protected $productRepository;
  20. /**
  21. * @var \Magento\Bundle\Api\Data\LinkInterfaceFactory
  22. */
  23. protected $linkFactory;
  24. /**
  25. * @var \Magento\Bundle\Model\ResourceModel\BundleFactory
  26. */
  27. protected $bundleFactory;
  28. /**
  29. * @var SelectionFactory
  30. */
  31. protected $bundleSelection;
  32. /**
  33. * @var \Magento\Bundle\Model\ResourceModel\Option\CollectionFactory
  34. */
  35. protected $optionCollection;
  36. /**
  37. * @var \Magento\Framework\Api\DataObjectHelper
  38. */
  39. protected $dataObjectHelper;
  40. /**
  41. * @param ProductRepositoryInterface $productRepository
  42. * @param \Magento\Bundle\Api\Data\LinkInterfaceFactory $linkFactory
  43. * @param \Magento\Bundle\Model\ResourceModel\BundleFactory $bundleFactory
  44. * @param \Magento\Bundle\Model\SelectionFactory $bundleSelection
  45. * @param \Magento\Bundle\Model\ResourceModel\Option\CollectionFactory $optionCollection
  46. * @param \Magento\Store\Model\StoreManagerInterface $storeManager
  47. * @param \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
  48. */
  49. public function __construct(
  50. ProductRepositoryInterface $productRepository,
  51. \Magento\Bundle\Api\Data\LinkInterfaceFactory $linkFactory,
  52. \Magento\Bundle\Model\SelectionFactory $bundleSelection,
  53. \Magento\Bundle\Model\ResourceModel\BundleFactory $bundleFactory,
  54. \Magento\Bundle\Model\ResourceModel\Option\CollectionFactory $optionCollection,
  55. \Magento\Store\Model\StoreManagerInterface $storeManager,
  56. \Magento\Framework\Api\DataObjectHelper $dataObjectHelper
  57. ) {
  58. $this->productRepository = $productRepository;
  59. $this->linkFactory = $linkFactory;
  60. $this->bundleFactory = $bundleFactory;
  61. $this->bundleSelection = $bundleSelection;
  62. $this->optionCollection = $optionCollection;
  63. $this->storeManager = $storeManager;
  64. $this->dataObjectHelper = $dataObjectHelper;
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. public function getChildren($productSku, $optionId = null)
  70. {
  71. $product = $this->productRepository->get($productSku);
  72. if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
  73. throw new InputException(__('Only implemented for bundle product'));
  74. }
  75. $childrenList = [];
  76. foreach ($this->getOptions($product) as $option) {
  77. if (!$option->getSelections() || ($optionId !== null && $option->getOptionId() != $optionId)) {
  78. continue;
  79. }
  80. /** @var \Magento\Catalog\Model\Product $selection */
  81. foreach ($option->getSelections() as $selection) {
  82. $childrenList[] = $this->buildLink($selection, $product);
  83. }
  84. }
  85. return $childrenList;
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function addChildByProductSku($sku, $optionId, \Magento\Bundle\Api\Data\LinkInterface $linkedProduct)
  91. {
  92. /** @var \Magento\Catalog\Model\Product $product */
  93. $product = $this->productRepository->get($sku);
  94. return $this->addChild($product, $optionId, $linkedProduct);
  95. }
  96. /**
  97. * {@inheritdoc}
  98. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  99. * @SuppressWarnings(PHPMD.NPathComplexity)
  100. */
  101. public function saveChild(
  102. $sku,
  103. \Magento\Bundle\Api\Data\LinkInterface $linkedProduct
  104. ) {
  105. $product = $this->productRepository->get($sku);
  106. if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
  107. throw new InputException(
  108. __('Product with specified sku: "%1" is not a bundle product', [$product->getSku()])
  109. );
  110. }
  111. /** @var \Magento\Catalog\Model\Product $linkProductModel */
  112. $linkProductModel = $this->productRepository->get($linkedProduct->getSku());
  113. if ($linkProductModel->isComposite()) {
  114. throw new InputException(__('Bundle product could not contain another composite product'));
  115. }
  116. if (!$linkedProduct->getId()) {
  117. throw new InputException(__('Id field of product link is required'));
  118. }
  119. /** @var \Magento\Bundle\Model\Selection $selectionModel */
  120. $selectionModel = $this->bundleSelection->create();
  121. $selectionModel->load($linkedProduct->getId());
  122. if (!$selectionModel->getId()) {
  123. throw new InputException(__('Can not find product link with id "%1"', [$linkedProduct->getId()]));
  124. }
  125. $selectionModel = $this->mapProductLinkToSelectionModel(
  126. $selectionModel,
  127. $linkedProduct,
  128. $linkProductModel->getId(),
  129. $product->getId()
  130. );
  131. try {
  132. $selectionModel->save();
  133. } catch (\Exception $e) {
  134. throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
  135. }
  136. return true;
  137. }
  138. /**
  139. * @param \Magento\Bundle\Model\Selection $selectionModel
  140. * @param \Magento\Bundle\Api\Data\LinkInterface $productLink
  141. * @param string $linkedProductId
  142. * @param string $parentProductId
  143. * @return \Magento\Bundle\Model\Selection
  144. */
  145. protected function mapProductLinkToSelectionModel(
  146. \Magento\Bundle\Model\Selection $selectionModel,
  147. \Magento\Bundle\Api\Data\LinkInterface $productLink,
  148. $linkedProductId,
  149. $parentProductId
  150. ) {
  151. $selectionModel->setProductId($linkedProductId);
  152. $selectionModel->setParentProductId($parentProductId);
  153. if (($productLink->getOptionId() !== null)) {
  154. $selectionModel->setOptionId($productLink->getOptionId());
  155. }
  156. if ($productLink->getPosition() !== null) {
  157. $selectionModel->setPosition($productLink->getPosition());
  158. }
  159. if ($productLink->getQty() !== null) {
  160. $selectionModel->setSelectionQty($productLink->getQty());
  161. }
  162. if ($productLink->getPriceType() !== null) {
  163. $selectionModel->setSelectionPriceType($productLink->getPriceType());
  164. }
  165. if ($productLink->getPrice() !== null) {
  166. $selectionModel->setSelectionPriceValue($productLink->getPrice());
  167. }
  168. if ($productLink->getCanChangeQuantity() !== null) {
  169. $selectionModel->setSelectionCanChangeQty($productLink->getCanChangeQuantity());
  170. }
  171. if ($productLink->getIsDefault() !== null) {
  172. $selectionModel->setIsDefault($productLink->getIsDefault());
  173. }
  174. return $selectionModel;
  175. }
  176. /**
  177. * {@inheritdoc}
  178. */
  179. public function addChild(
  180. \Magento\Catalog\Api\Data\ProductInterface $product,
  181. $optionId,
  182. \Magento\Bundle\Api\Data\LinkInterface $linkedProduct
  183. ) {
  184. if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
  185. throw new InputException(
  186. __('Product with specified sku: "%1" is not a bundle product', $product->getSku())
  187. );
  188. }
  189. $options = $this->optionCollection->create();
  190. $options->setIdFilter($optionId);
  191. $existingOption = $options->getFirstItem();
  192. if (!$existingOption->getId()) {
  193. throw new InputException(
  194. __(
  195. 'Product with specified sku: "%1" does not contain option: "%2"',
  196. [$product->getSku(), $optionId]
  197. )
  198. );
  199. }
  200. /* @var $resource \Magento\Bundle\Model\ResourceModel\Bundle */
  201. $resource = $this->bundleFactory->create();
  202. $selections = $resource->getSelectionsData($product->getId());
  203. /** @var \Magento\Catalog\Model\Product $linkProductModel */
  204. $linkProductModel = $this->productRepository->get($linkedProduct->getSku());
  205. if ($linkProductModel->isComposite()) {
  206. throw new InputException(__('Bundle product could not contain another composite product'));
  207. }
  208. if ($selections) {
  209. foreach ($selections as $selection) {
  210. if ($selection['option_id'] == $optionId &&
  211. $selection['product_id'] == $linkProductModel->getId()) {
  212. throw new CouldNotSaveException(
  213. __(
  214. 'Child with specified sku: "%1" already assigned to product: "%2"',
  215. [$linkedProduct->getSku(), $product->getSku()]
  216. )
  217. );
  218. }
  219. }
  220. }
  221. $selectionModel = $this->bundleSelection->create();
  222. $selectionModel = $this->mapProductLinkToSelectionModel(
  223. $selectionModel,
  224. $linkedProduct,
  225. $linkProductModel->getId(),
  226. $product->getId()
  227. );
  228. $selectionModel->setOptionId($optionId);
  229. try {
  230. $selectionModel->save();
  231. $resource->addProductRelations($product->getId(), [$linkProductModel->getId()]);
  232. } catch (\Exception $e) {
  233. throw new CouldNotSaveException(__('Could not save child: "%1"', $e->getMessage()), $e);
  234. }
  235. return $selectionModel->getId();
  236. }
  237. /**
  238. * {@inheritdoc}
  239. */
  240. public function removeChild($sku, $optionId, $childSku)
  241. {
  242. $product = $this->productRepository->get($sku);
  243. if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
  244. throw new InputException(__('Product with specified sku: %1 is not a bundle product', $sku));
  245. }
  246. $excludeSelectionIds = [];
  247. $usedProductIds = [];
  248. $removeSelectionIds = [];
  249. foreach ($this->getOptions($product) as $option) {
  250. /** @var \Magento\Bundle\Model\Selection $selection */
  251. foreach ($option->getSelections() as $selection) {
  252. if ((strcasecmp($selection->getSku(), $childSku) == 0) && ($selection->getOptionId() == $optionId)) {
  253. $removeSelectionIds[] = $selection->getSelectionId();
  254. continue;
  255. }
  256. $excludeSelectionIds[] = $selection->getSelectionId();
  257. $usedProductIds[] = $selection->getProductId();
  258. }
  259. }
  260. if (empty($removeSelectionIds)) {
  261. throw new \Magento\Framework\Exception\NoSuchEntityException(
  262. __('Requested bundle option product doesn\'t exist')
  263. );
  264. }
  265. /* @var $resource \Magento\Bundle\Model\ResourceModel\Bundle */
  266. $resource = $this->bundleFactory->create();
  267. $resource->dropAllUnneededSelections($product->getId(), $excludeSelectionIds);
  268. $resource->removeProductRelations($product->getId(), array_unique($usedProductIds));
  269. return true;
  270. }
  271. /**
  272. * @param \Magento\Catalog\Model\Product $selection
  273. * @param \Magento\Catalog\Model\Product $product
  274. * @return \Magento\Bundle\Api\Data\LinkInterface
  275. */
  276. private function buildLink(\Magento\Catalog\Model\Product $selection, \Magento\Catalog\Model\Product $product)
  277. {
  278. $selectionPriceType = $selectionPrice = null;
  279. /** @var \Magento\Bundle\Model\Selection $product */
  280. if ($product->getPriceType()) {
  281. $selectionPriceType = $selection->getSelectionPriceType();
  282. $selectionPrice = $selection->getSelectionPriceValue();
  283. }
  284. /** @var \Magento\Bundle\Api\Data\LinkInterface $link */
  285. $link = $this->linkFactory->create();
  286. $this->dataObjectHelper->populateWithArray(
  287. $link,
  288. $selection->getData(),
  289. '\Magento\Bundle\Api\Data\LinkInterface'
  290. );
  291. $link->setIsDefault($selection->getIsDefault())
  292. ->setId($selection->getSelectionId())
  293. ->setQty($selection->getSelectionQty())
  294. ->setCanChangeQuantity($selection->getSelectionCanChangeQty())
  295. ->setPrice($selectionPrice)
  296. ->setPriceType($selectionPriceType);
  297. return $link;
  298. }
  299. /**
  300. * @param \Magento\Catalog\Api\Data\ProductInterface $product
  301. * @return \Magento\Bundle\Api\Data\OptionInterface[]
  302. */
  303. private function getOptions(\Magento\Catalog\Api\Data\ProductInterface $product)
  304. {
  305. /** @var \Magento\Bundle\Model\Product\Type $productTypeInstance */
  306. $productTypeInstance = $product->getTypeInstance();
  307. $productTypeInstance->setStoreFilter(
  308. $product->getStoreId(),
  309. $product
  310. );
  311. $optionCollection = $productTypeInstance->getOptionsCollection($product);
  312. $selectionCollection = $productTypeInstance->getSelectionsCollection(
  313. $productTypeInstance->getOptionsIds($product),
  314. $product
  315. );
  316. $options = $optionCollection->appendSelections($selectionCollection);
  317. return $options;
  318. }
  319. }