/** * Gather and save information about product links. * Must be called after ALL products saving done. * * @return $this */ protected function _saveLinks() { $resource = $this->_linkFactory->create(); $mainTable = $resource->getMainTable(); $positionAttrId = array(); $nextLinkId = $this->_resourceHelper->getNextAutoincrement($mainTable); $adapter = $this->_connection; // pre-load 'position' attributes ID for each link type once foreach ($this->_linkNameToId as $linkName => $linkId) { $select = $adapter->select()->from($resource->getTable('catalog_product_link_attribute'), array('id' => 'product_link_attribute_id'))->where('link_type_id = :link_id AND product_link_attribute_code = :position'); $bind = array(':link_id' => $linkId, ':position' => 'position'); $positionAttrId[$linkId] = $adapter->fetchOne($select, $bind); } while ($bunch = $this->_dataSourceModel->getNextBunch()) { $productIds = array(); $linkRows = array(); $positionRows = array(); foreach ($bunch as $rowNum => $rowData) { if (!$this->isRowAllowedToImport($rowData, $rowNum)) { continue; } if (self::SCOPE_DEFAULT == $this->getRowScope($rowData)) { $sku = $rowData[self::COL_SKU]; } foreach ($this->_linkNameToId as $linkName => $linkId) { $productId = $this->_newSku[$sku]['entity_id']; $productIds[] = $productId; if (isset($rowData[$linkName . 'sku'])) { $linkedSku = $rowData[$linkName . 'sku']; if ((isset($this->_newSku[$linkedSku]) || isset($this->_oldSku[$linkedSku])) && $linkedSku != $sku) { if (isset($this->_newSku[$linkedSku])) { $linkedId = $this->_newSku[$linkedSku]['entity_id']; } else { $linkedId = $this->_oldSku[$linkedSku]['entity_id']; } if ($linkedId == null) { // Import file links to a SKU which is skipped for some reason, which leads to a "NULL" // link causing fatal errors. $this->_logger->logException(new \Exception(sprintf('WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, ' . 'Link type id: %d', $sku, $productId, $linkedSku, $linkId))); continue; } $linkKey = "{$productId}-{$linkedId}-{$linkId}"; if (!isset($linkRows[$linkKey])) { $linkRows[$linkKey] = array('link_id' => $nextLinkId, 'product_id' => $productId, 'linked_product_id' => $linkedId, 'link_type_id' => $linkId); if (!empty($rowData[$linkName . 'position'])) { $positionRows[] = array('link_id' => $nextLinkId, 'product_link_attribute_id' => $positionAttrId[$linkId], 'value' => $rowData[$linkName . 'position']); } $nextLinkId++; } } } } } if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior() && $productIds) { $adapter->delete($mainTable, $adapter->quoteInto('product_id IN (?)', array_unique($productIds))); } if ($linkRows) { $adapter->insertOnDuplicate($mainTable, $linkRows, array('link_id')); } if ($positionRows) { // process linked product positions $adapter->insertOnDuplicate($resource->getAttributeTypeTable('int'), $positionRows, array('value')); } } return $this; }
/** * Save product type specific data. * * @return \Magento\CatalogImportExport\Model\Import\Product\Type\AbstractType * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function saveData() { $groupedLinkId = \Magento\GroupedProduct\Model\Resource\Product\Link::LINK_TYPE_GROUPED; $connection = $this->_resource->getConnection('write'); $resource = $this->_productLinkFactory->create(); $mainTable = $resource->getMainTable(); $relationTable = $resource->getTable('catalog_product_relation'); $newSku = $this->_entityModel->getNewSku(); $oldSku = $this->_entityModel->getOldSku(); $attributes = array(); // pre-load attributes parameters $select = $connection->select()->from($resource->getTable('catalog_product_link_attribute'), array('id' => 'product_link_attribute_id', 'code' => 'product_link_attribute_code', 'type' => 'data_type'))->where('link_type_id = ?', $groupedLinkId); foreach ($connection->fetchAll($select) as $row) { $attributes[$row['code']] = array('id' => $row['id'], 'table' => $resource->getAttributeTypeTable($row['type'])); } while ($bunch = $this->_entityModel->getNextBunch()) { $linksData = array('product_ids' => array(), 'links' => array(), 'attr_product_ids' => array(), 'position' => array(), 'qty' => array(), 'relation' => array()); foreach ($bunch as $rowNum => $rowData) { if (!$this->_entityModel->isRowAllowedToImport($rowData, $rowNum) || empty($rowData['_associated_sku'])) { continue; } if (isset($newSku[$rowData['_associated_sku']])) { $linkedProductId = $newSku[$rowData['_associated_sku']]['entity_id']; } elseif (isset($oldSku[$rowData['_associated_sku']])) { $linkedProductId = $oldSku[$rowData['_associated_sku']]['entity_id']; } else { continue; } $scope = $this->_entityModel->getRowScope($rowData); if (\Magento\CatalogImportExport\Model\Import\Product::SCOPE_DEFAULT == $scope) { $productData = $newSku[$rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_SKU]]; } else { $colAttrSet = \Magento\CatalogImportExport\Model\Import\Product::COL_ATTR_SET; $rowData[$colAttrSet] = $productData['attr_set_code']; $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE] = $productData['type_id']; } $productId = $productData['entity_id']; if ($this->_type != $rowData[\Magento\CatalogImportExport\Model\Import\Product::COL_TYPE]) { continue; } $linksData['product_ids'][$productId] = true; $linksData['links'][$productId][$linkedProductId] = $groupedLinkId; $linksData['relation'][] = array('parent_id' => $productId, 'child_id' => $linkedProductId); $qty = empty($rowData['_associated_default_qty']) ? 0 : $rowData['_associated_default_qty']; $pos = empty($rowData['_associated_position']) ? 0 : $rowData['_associated_position']; if ($qty || $pos) { $linksData['attr_product_ids'][$productId] = true; if ($pos) { $linksData['position']["{$productId} {$linkedProductId}"] = array('product_link_attribute_id' => $attributes['position']['id'], 'value' => $pos); } if ($qty) { $linksData['qty']["{$productId} {$linkedProductId}"] = array('product_link_attribute_id' => $attributes['qty']['id'], 'value' => $qty); } } } // save links and relations if ($linksData['product_ids'] && $this->getBehavior() != \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND) { $connection->delete($mainTable, $connection->quoteInto('product_id IN (?) AND link_type_id = ' . $groupedLinkId, array_keys($linksData['product_ids']))); } if ($linksData['links']) { $mainData = array(); foreach ($linksData['links'] as $productId => $linkedData) { foreach ($linkedData as $linkedId => $linkType) { $mainData[] = array('product_id' => $productId, 'linked_product_id' => $linkedId, 'link_type_id' => $linkType); } } $connection->insertOnDuplicate($mainTable, $mainData); $connection->insertOnDuplicate($relationTable, $linksData['relation']); } // save positions and default quantity if ($linksData['attr_product_ids']) { $savedData = $connection->fetchPairs($connection->select()->from($mainTable, array(new \Zend_Db_Expr('CONCAT_WS(" ", product_id, linked_product_id)'), 'link_id'))->where('product_id IN (?) AND link_type_id = ' . $groupedLinkId, array_keys($linksData['attr_product_ids']))); foreach ($savedData as $pseudoKey => $linkId) { if (isset($linksData['position'][$pseudoKey])) { $linksData['position'][$pseudoKey]['link_id'] = $linkId; } if (isset($linksData['qty'][$pseudoKey])) { $linksData['qty'][$pseudoKey]['link_id'] = $linkId; } } if ($linksData['position']) { $connection->insertOnDuplicate($attributes['position']['table'], $linksData['position']); } if ($linksData['qty']) { $connection->insertOnDuplicate($attributes['qty']['table'], $linksData['qty']); } } } return $this; }