/** * Save product links * * @param \Magento\Catalog\Model\Product $product * @param array $links * @throws CouldNotSaveException * @return void */ protected function saveLinks($product, array $links) { foreach ($links as $type => $linksData) { $links[$type] = $this->dataMapper->map($linksData); } $this->linkInitializer->initializeLinks($product, $links); try { $product->save(); } catch (\Exception $exception) { throw new CouldNotSaveException('Invalid data provided for linked products'); } }
/** * {@inheritdoc} */ public function run() { $this->logger->log('Installing product links:'); $entityFileAssociation = ['related', 'upsell', 'crosssell']; foreach ($this->postInstaller->getInstalledModuleList() as $moduleName) { foreach ($entityFileAssociation as $linkType) { $fileName = substr($moduleName, strpos($moduleName, "_") + 1) . '/Links/' . $linkType . '.csv'; $fileName = $this->fixtureHelper->getPath($fileName); if (!$fileName) { continue; } /** @var \Magento\SampleData\Helper\Csv\ReaderFactory $csvReader */ $csvReader = $this->csvReaderFactory->create(['fileName' => $fileName, 'mode' => 'r']); foreach ($csvReader as $row) { /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productFactory->create(); $productId = $product->getIdBySku($row['sku']); if (!$productId) { continue; } $product->setId($productId); $links = [$linkType => []]; foreach (explode("\n", $row['linked_sku']) as $linkedProductSku) { $linkedProductId = $product->getIdBySku($linkedProductSku); if ($linkedProductId) { $links[$linkType][$linkedProductId] = []; } } $this->linksInitializer->initializeLinks($product, $links); $product->getLinkInstance()->saveProductRelations($product); $this->logger->logInline('.'); } } } }
/** * {@inheritdoc} */ public function setProductLinks($sku, $type, array $items) { $linkTypes = $this->linkTypeProvider->getLinkTypes(); if (!isset($linkTypes[$type])) { throw new NoSuchEntityException(__('Provided link type "%1" does not exist', $type)); } $product = $this->productRepository->get($sku); $assignedSkuList = []; /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */ foreach ($items as $link) { $assignedSkuList[] = $link->getLinkedProductSku(); } $linkedProductIds = $this->productResource->getProductsIdsBySkus($assignedSkuList); $links = []; /** @var \Magento\Catalog\Api\Data\ProductLinkInterface[] $items*/ foreach ($items as $link) { $data = $link->__toArray(); $linkedSku = $link->getLinkedProductSku(); if (!isset($linkedProductIds[$linkedSku])) { throw new NoSuchEntityException(__('Product with SKU "%1" does not exist', $linkedSku)); } $data['product_id'] = $linkedProductIds[$linkedSku]; $links[$linkedProductIds[$linkedSku]] = $data; } $this->linkInitializer->initializeLinks($product, [$type => $links]); try { $product->save(); } catch (\Exception $exception) { throw new CouldNotSaveException(__('Invalid data provided for linked products')); } return true; }
/** * Initialize product before saving * * @param \Magento\Catalog\Model\Product $product * @return \Magento\Catalog\Model\Product */ public function initialize(\Magento\Catalog\Model\Product $product) { $productData = $this->request->getPost('product'); if ($productData) { $stockData = isset($productData['stock_data']) ? $productData['stock_data'] : array(); $productData['stock_data'] = $this->stockFilter->filter($stockData); } foreach (array('category_ids', 'website_ids') as $field) { if (!isset($productData[$field])) { $productData[$field] = array(); } } $wasLockedMedia = false; if ($product->isLockedAttribute('media')) { $product->unlockAttribute('media'); $wasLockedMedia = true; } $product->addData($productData); if ($wasLockedMedia) { $product->lockAttribute('media'); } if ($this->storeManager->hasSingleStore()) { $product->setWebsiteIds(array($this->storeManager->getStore(true)->getWebsite()->getId())); } /** * Create Permanent Redirect for old URL key */ if ($product->getId() && isset($productData['url_key_create_redirect'])) { $product->setData('save_rewrites_history', (bool) $productData['url_key_create_redirect']); } /** * Check "Use Default Value" checkboxes values */ $useDefaults = $this->request->getPost('use_default'); if ($useDefaults) { foreach ($useDefaults as $attributeCode) { $product->setData($attributeCode, false); } } $links = $this->request->getPost('links'); $links = is_array($links) ? $links : array(); $linkTypes = array('related', 'upsell', 'crosssell'); foreach ($linkTypes as $type) { if (isset($links[$type])) { $links[$type] = $this->jsHelper->decodeGridSerializedInput($links[$type]); } } $product = $this->productLinks->initializeLinks($product, $links); /** * Initialize product options */ if (isset($productData['options']) && !$product->getOptionsReadonly()) { // mark custom options that should to fall back to default value $options = $this->mergeProductOptions($productData['options'], $this->request->getPost('options_use_default')); $product->setProductOptions($options); } $product->setCanSaveCustomOptions((bool) $this->request->getPost('affect_product_custom_options') && !$product->getOptionsReadonly()); return $product; }
/** * {@inheritdoc} */ public function initializeLinks(\Magento\Catalog\Model\Product $product, array $links) { $pluginInfo = $this->pluginList->getNext($this->subjectType, 'initializeLinks'); if (!$pluginInfo) { return parent::initializeLinks($product, $links); } else { return $this->___callPlugins('initializeLinks', func_get_args(), $pluginInfo); } }
/** * {@inheritdoc} */ public function install(array $related, array $upsell, array $crosssell) { $linkTypes = ['related' => $related, 'upsell' => $upsell, 'crosssell' => $crosssell]; foreach ($linkTypes as $linkType => $fixtures) { foreach ($fixtures as $fileName) { $fileName = $this->fixtureManager->getFixture($fileName); if (!file_exists($fileName)) { continue; } $rows = $this->csvReader->getData($fileName); $header = array_shift($rows); foreach ($rows as $row) { $data = []; foreach ($row as $key => $value) { $data[$header[$key]] = $value; } $row = $data; /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productFactory->create(); $productId = $product->getIdBySku($row['sku']); if (!$productId) { continue; } $product->setId($productId); $links = [$linkType => []]; foreach (explode("\n", $row['linked_sku']) as $linkedProductSku) { $linkedProductId = $product->getIdBySku($linkedProductSku); if ($linkedProductId) { $links[$linkType][$linkedProductId] = []; } } $this->linksInitializer->initializeLinks($product, $links); $product->getLinkInstance()->saveProductRelations($product); } } } }
/** * {@inheritdoc} */ public function delete(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) { $linkedProduct = $this->productRepository->get($entity->getLinkedProductSku()); $product = $this->productRepository->get($entity->getProductSku()); $links = $this->entityCollectionProvider->getCollection($product, $entity->getLinkType()); if (!isset($links[$linkedProduct->getId()])) { throw new NoSuchEntityException(__('Product with SKU %1 is not linked to product with SKU %2', $entity->getLinkedProductSku(), $entity->getProductSku())); } //Remove product from the linked product list unset($links[$linkedProduct->getId()]); $this->linkInitializer->initializeLinks($product, [$entity->getLinkType() => $links]); try { $product->save(); } catch (\Exception $exception) { throw new CouldNotSaveException(__('Invalid data provided for linked products')); } return true; }
/** * Process product links, creating new links, updating and deleting existing links * * @param \Magento\Catalog\Api\Data\ProductInterface $product * @param \Magento\Catalog\Api\Data\ProductLinkInterface[] $newLinks * @return $this * @throws NoSuchEntityException */ private function processLinks(\Magento\Catalog\Api\Data\ProductInterface $product, $newLinks) { if ($newLinks === null) { // If product links were not specified, don't do anything return $this; } // Clear all existing product links and then set the ones we want $linkTypes = $this->linkTypeProvider->getLinkTypes(); foreach (array_keys($linkTypes) as $typeName) { $this->linkInitializer->initializeLinks($product, [$typeName => []]); } // Set each linktype info if (!empty($newLinks)) { $productLinks = []; foreach ($newLinks as $link) { $productLinks[$link->getLinkType()][] = $link; } foreach ($productLinks as $type => $linksByType) { $assignedSkuList = []; /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */ foreach ($linksByType as $link) { $assignedSkuList[] = $link->getLinkedProductSku(); } $linkedProductIds = $this->resourceModel->getProductsIdsBySkus($assignedSkuList); $linksToInitialize = []; foreach ($linksByType as $link) { $linkDataArray = $this->extensibleDataObjectConverter->toNestedArray($link, [], 'Magento\\Catalog\\Api\\Data\\ProductLinkInterface'); $linkedSku = $link->getLinkedProductSku(); if (!isset($linkedProductIds[$linkedSku])) { throw new NoSuchEntityException(__('Product with SKU "%1" does not exist', $linkedSku)); } $linkDataArray['product_id'] = $linkedProductIds[$linkedSku]; $linksToInitialize[$linkedProductIds[$linkedSku]] = $linkDataArray; } $this->linkInitializer->initializeLinks($product, [$type => $linksToInitialize]); } } $product->setProductLinks($newLinks); return $this; }
/** * Setting product links * * @param \Magento\Catalog\Model\Product $product * @return \Magento\Catalog\Model\Product * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function setProductLinks(\Magento\Catalog\Model\Product $product) { $links = $this->getLinkResolver()->getLinks(); $product->setProductLinks([]); $product = $this->productLinks->initializeLinks($product, $links); $productLinks = $product->getProductLinks(); $linkTypes = ['related' => $product->getRelatedReadonly(), 'upsell' => $product->getUpsellReadonly(), 'crosssell' => $product->getCrosssellReadonly()]; foreach ($linkTypes as $linkType => $readonly) { if (isset($links[$linkType]) && !$readonly) { foreach ((array) $links[$linkType] as $linkData) { if (empty($linkData['id'])) { continue; } $linkProduct = $this->getProductRepository()->getById($linkData['id']); $link = $this->getProductLinkFactory()->create(); $link->setSku($product->getSku())->setLinkedProductSku($linkProduct->getSku())->setLinkType($linkType)->setPosition(isset($linkData['position']) ? (int) $linkData['position'] : 0); $productLinks[] = $link; } } } return $product->setProductLinks($productLinks); }
/** * Initialize product before saving * * @param \Magento\Catalog\Model\Product $product * @return \Magento\Catalog\Model\Product * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function initialize(\Magento\Catalog\Model\Product $product) { $productData = $this->request->getPost('product'); unset($productData['custom_attributes']); unset($productData['extension_attributes']); if ($productData) { $stockData = isset($productData['stock_data']) ? $productData['stock_data'] : []; $productData['stock_data'] = $this->stockFilter->filter($stockData); } foreach (['category_ids', 'website_ids'] as $field) { if (!isset($productData[$field])) { $productData[$field] = []; } } $wasLockedMedia = false; if ($product->isLockedAttribute('media')) { $product->unlockAttribute('media'); $wasLockedMedia = true; } $dateFieldFilters = []; $attributes = $product->getAttributes(); foreach ($attributes as $attrKey => $attribute) { if ($attribute->getBackend()->getType() == 'datetime') { if (array_key_exists($attrKey, $productData) && $productData[$attrKey] != '') { $dateFieldFilters[$attrKey] = $this->dateFilter; } } } $inputFilter = new \Zend_Filter_Input($dateFieldFilters, [], $productData); $productData = $inputFilter->getUnescaped(); $product->addData($productData); if ($wasLockedMedia) { $product->lockAttribute('media'); } if ($this->storeManager->hasSingleStore()) { $product->setWebsiteIds([$this->storeManager->getStore(true)->getWebsite()->getId()]); } /** * Check "Use Default Value" checkboxes values */ $useDefaults = $this->request->getPost('use_default'); if ($useDefaults) { foreach ($useDefaults as $attributeCode) { $product->setData($attributeCode, false); } } $links = $this->request->getPost('links'); $links = is_array($links) ? $links : []; $linkTypes = ['related', 'upsell', 'crosssell']; foreach ($linkTypes as $type) { if (isset($links[$type])) { $links[$type] = $this->jsHelper->decodeGridSerializedInput($links[$type]); } } $product = $this->productLinks->initializeLinks($product, $links); $productLinks = $product->getProductLinks(); $linkTypes = ['related' => $product->getRelatedReadonly(), 'upsell' => $product->getUpsellReadonly(), 'crosssell' => $product->getCrosssellReadonly()]; foreach ($linkTypes as $linkType => $readonly) { if (isset($links[$linkType]) && !$readonly) { foreach ($links[$linkType] as $linkId => $linkData) { $linkProduct = $this->productRepository->getById($linkId); $link = $this->productLinkFactory->create(); $link->setSku($product->getSku())->setLinkedProductSku($linkProduct->getSku())->setLinkType($linkType)->setPosition(isset($linkData['position']) ? (int) $linkData['position'] : 0); $productLinks[] = $link; } } } $product->setProductLinks($productLinks); /** * Initialize product options */ if (isset($productData['options']) && !$product->getOptionsReadonly()) { // mark custom options that should to fall back to default value $options = $this->mergeProductOptions($productData['options'], $this->request->getPost('options_use_default')); $customOptions = []; foreach ($options as $customOptionData) { if (!(bool) $customOptionData['is_delete']) { $customOption = $this->customOptionFactory->create(['data' => $customOptionData]); $customOption->setProductSku($product->getSku()); $customOption->setOptionId(null); $customOptions[] = $customOption; } } $product->setOptions($customOptions); } $product->setCanSaveCustomOptions((bool) $this->request->getPost('affect_product_custom_options') && !$product->getOptionsReadonly()); return $product; }
public function testInitializeLinks() { $links = ['related' => ['data'], 'upsell' => ['data'], 'crosssell' => ['data']]; $this->assertInstanceOf('\\Magento\\Catalog\\Model\\Product', $this->model->initializeLinks($this->getMockedProduct(), $links)); }