Beispiel #1
0
 /**
  * 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');
     }
 }
Beispiel #2
0
 /**
  * {@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;
 }
Beispiel #4
0
 /**
  * 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;
 }
Beispiel #9
0
 /**
  * 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);
 }
Beispiel #10
0
 /**
  * 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;
 }
Beispiel #11
0
 protected function setUp()
 {
     $this->objectManager = new ObjectManager($this);
     $this->productLinkFactoryMock = $this->getMockBuilder(ProductLinkInterfaceFactory::class)->disableOriginalConstructor()->getMock();
     $this->productRepositoryMock = $this->getMockBuilder(ProductRepository::class)->disableOriginalConstructor()->getMock();
     $this->requestMock = $this->getMockBuilder(RequestInterface::class)->setMethods(['getPost'])->getMockForAbstractClass();
     $this->storeMock = $this->getMockBuilder(StoreInterface::class)->setMethods(['getWebsite'])->getMockForAbstractClass();
     $this->websiteMock = $this->getMockBuilder(WebsiteInterface::class)->getMockForAbstractClass();
     $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)->getMockForAbstractClass();
     $this->dateFilterMock = $this->getMockBuilder(DateFilter::class)->disableOriginalConstructor()->getMock();
     $this->stockFilterMock = $this->getMockBuilder(StockDataFilter::class)->disableOriginalConstructor()->getMock();
     $this->productMock = $this->getMockBuilder(Product::class)->setMethods(['setData', 'addData', 'getId', 'setWebsiteIds', 'isLockedAttribute', 'lockAttribute', 'getAttributes', 'unlockAttribute', 'getOptionsReadOnly', 'setOptions', 'setCanSaveCustomOptions', '__sleep', '__wakeup', 'getSku', 'getProductLinks', 'getWebsiteIds'])->disableOriginalConstructor()->getMock();
     $this->customOptionFactoryMock = $this->getMockBuilder(ProductCustomOptionInterfaceFactory::class)->disableOriginalConstructor()->setMethods(['create'])->getMock();
     $this->customOptionMock = $this->getMockBuilder(ProductCustomOptionInterface::class)->disableOriginalConstructor()->getMockForAbstractClass();
     $this->productLinksMock = $this->getMockBuilder(ProductLinks::class)->disableOriginalConstructor()->getMock();
     $this->productLinksMock->expects($this->any())->method('initializeLinks')->willReturn($this->productMock);
     $this->helper = $this->objectManager->getObject(Helper::class, ['request' => $this->requestMock, 'storeManager' => $this->storeManagerMock, 'stockFilter' => $this->stockFilterMock, 'productLinks' => $this->productLinksMock, 'dateFilter' => $this->dateFilterMock, 'customOptionFactory' => $this->customOptionFactoryMock, 'productLinkFactory' => $this->productLinkFactoryMock, 'productRepository' => $this->productRepositoryMock]);
     $this->linkResolverMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Link\Resolver::class)->disableOriginalConstructor()->getMock();
     $helperReflection = new \ReflectionClass(get_class($this->helper));
     $resolverProperty = $helperReflection->getProperty('linkResolver');
     $resolverProperty->setAccessible(true);
     $resolverProperty->setValue($this->helper, $this->linkResolverMock);
 }
Beispiel #12
0
 public function testInitializeLinks()
 {
     $links = ['related' => ['data'], 'upsell' => ['data'], 'crosssell' => ['data']];
     $this->assertInstanceOf('\\Magento\\Catalog\\Model\\Product', $this->model->initializeLinks($this->getMockedProduct(), $links));
 }
 protected function setUp()
 {
     $this->objectManager = new ObjectManager($this);
     $this->productLinkFactoryMock = $this->getMockBuilder(ProductLinkInterfaceFactory::class)->disableOriginalConstructor()->getMock();
     $this->productRepositoryMock = $this->getMockBuilder(ProductRepository::class)->disableOriginalConstructor()->getMock();
     $this->requestMock = $this->getMockBuilder(RequestInterface::class)->setMethods(['getPost'])->getMockForAbstractClass();
     $this->storeMock = $this->getMockBuilder(StoreInterface::class)->setMethods(['getWebsite'])->getMockForAbstractClass();
     $this->websiteMock = $this->getMockBuilder(WebsiteInterface::class)->getMockForAbstractClass();
     $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)->getMockForAbstractClass();
     $this->dateFilterMock = $this->getMockBuilder(DateFilter::class)->disableOriginalConstructor()->getMock();
     $this->stockFilterMock = $this->getMockBuilder(StockDataFilter::class)->disableOriginalConstructor()->getMock();
     $this->productMock = $this->getMockBuilder(Product::class)->setMethods(['setData', 'addData', 'getId', 'setWebsiteIds', 'isLockedAttribute', 'lockAttribute', 'getAttributes', 'unlockAttribute', 'getOptionsReadOnly', 'setOptions', 'setCanSaveCustomOptions', '__sleep', '__wakeup', 'getSku', 'getProductLinks'])->disableOriginalConstructor()->getMock();
     $this->customOptionFactoryMock = $this->getMockBuilder(ProductCustomOptionInterfaceFactory::class)->disableOriginalConstructor()->setMethods(['create'])->getMock();
     $this->customOptionMock = $this->getMockBuilder(ProductCustomOptionInterface::class)->disableOriginalConstructor()->getMockForAbstractClass();
     $this->productLinksMock = $this->getMockBuilder(ProductLinks::class)->disableOriginalConstructor()->getMock();
     $this->customOptionFactoryMock->expects($this->any())->method('create')->with(['data' => ['is_delete' => false]])->willReturn($this->customOptionMock);
     $this->productLinksMock->expects($this->any())->method('initializeLinks')->willReturn($this->productMock);
     $this->helper = $this->objectManager->getObject(Helper::class, ['request' => $this->requestMock, 'storeManager' => $this->storeManagerMock, 'stockFilter' => $this->stockFilterMock, 'productLinks' => $this->productLinksMock, 'dateFilter' => $this->dateFilterMock, 'customOptionFactory' => $this->customOptionFactoryMock, 'productLinkFactory' => $this->productLinkFactoryMock, 'productRepository' => $this->productRepositoryMock]);
 }