parseAdditionalAttributes($rowData['additional_attributes'])); return $rowData; } private function parseAdditionalAttributes($additionalAttributes) { return empty($this->_parameters[Import::FIELDS_ENCLOSURE]) ? $this->parseAttributesWithoutWrappedValues($additionalAttributes) : $this->parseAttributesWithWrappedValues($additionalAttributes); } private function parseAttributesWithoutWrappedValues($attributesData) { $attributeNameValuePairs = explode($this->getMultipleValueSeparator(), $attributesData); $preparedAttributes = []; $code = ''; foreach ($attributeNameValuePairs as $attributeData) { //process case when attribute has ImportModel::DEFAULT_GLOBAL_MULTI_VALUE_SEPARATOR inside its value if (strpos($attributeData, self::PAIR_NAME_VALUE_SEPARATOR) === false) { if (!$code) { continue; } $preparedAttributes[$code] .= $this->getMultipleValueSeparator() . $attributeData; continue; } list($code, $value) = explode(self::PAIR_NAME_VALUE_SEPARATOR, $attributeData, 2); $code = mb_strtolower($code); $preparedAttributes[$code] = $value; } return $preparedAttributes; } private function parseAttributesWithWrappedValues($attributesData) { $attributes = []; preg_match_all('~((?:[a-zA-Z0-9_])+)="((?:[^"]|""|"' . $this->getMultiLineSeparatorForRegexp() . '")+)"+~', $attributesData, $matches ); foreach ($matches[1] as $i => $attributeCode) { $attribute = $this->retrieveAttributeByCode($attributeCode); $value = 'multiselect' != $attribute->getFrontendInput() ? str_replace('""', '"', $matches[2][$i]) : '"' . $matches[2][$i] . '"'; $attributes[mb_strtolower($attributeCode)] = $value; } return $attributes; } private function _setStockUseConfigFieldsValues($rowData) { $useConfigFields = array(); foreach ($rowData as $key => $value) { $useConfigName = self::INVENTORY_USE_CONFIG_PREFIX . $key; if (isset($this->defaultStockData[$key]) && isset($this->defaultStockData[$useConfigName]) && !empty($value) && empty($rowData[$useConfigName]) ) { $useConfigFields[$useConfigName] = ($value == self::INVENTORY_USE_CONFIG) ? 1 : 0; } } $rowData = array_merge($rowData, $useConfigFields); return $rowData; } private function _customFieldsMapping($rowData) { foreach ($this->_fieldsMap as $systemFieldName => $fileFieldName) { if (array_key_exists($fileFieldName, $rowData)) { $rowData[$systemFieldName] = $rowData[$fileFieldName]; } } $rowData = $this->_parseAdditionalAttributes($rowData); $rowData = $this->_setStockUseConfigFieldsValues($rowData); if (array_key_exists('status', $rowData) && $rowData['status'] != \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED ) { if ($rowData['status'] == 'yes') { $rowData['status'] = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED; } elseif (!empty($rowData['status']) || $this->getRowScope($rowData) == self::SCOPE_DEFAULT) { $rowData['status'] = \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED; } } return $rowData; } private function getProductEntityLinkField() { if (!$this->productEntityLinkField) { $this->productEntityLinkField = $this->getMetadataPool() ->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class) ->getLinkField(); } return $this->productEntityLinkField; } /** * Get product entity identifier field * * @return string */ /* private function getProductIdentifierField() { if (!$this->productEntityIdentifierField) { $this->productEntityIdentifierField = $this->getMetadataPool() ->getMetadata(\Magento\Catalog\Api\Data\ProductInterface::class) ->getIdentifierField(); } return $this->productEntityIdentifierField; } */ protected function _prepareRowForDb(array $rowData) { $rowData = $this->_customFieldsMapping($rowData); // $rowData = parent::_prepareRowForDb($rowData); static $lastSku = null; if (Import::BEHAVIOR_DELETE == $this->getBehavior()) { return $rowData; } $lastSku = $rowData[self::COL_SKU]; if (isset($this->_oldSku[$lastSku])) { $newSku = $this->skuProcessor->getNewSku($lastSku); $rowData[self::COL_ATTR_SET] = $newSku['attr_set_code']; $rowData[self::COL_TYPE] = $newSku['type_id']; } return $rowData; } private function isSkuExist($sku) { $sku = strtolower($sku); return isset($this->_oldSku[$sku]); } protected function _saveProductsData() { $this->_saveProducts(); $this->_saveLinks(); foreach ($this->_productTypeModels as $productTypeModel) { $productTypeModel->saveData(); } $this->_saveStockItem(); if ($this->_replaceFlag) { $this->getOptionEntity()->clearProductsSkuToId(); } $this->getOptionEntity()->importData(); return $this; } protected function _saveProductAttributes(array $attributesData) { foreach ($attributesData as $tableName => $skuData) { $tableData = []; foreach ($skuData as $sku => $attributes) { $linkId = $this->_connection->fetchOne( $this->_connection->select() ->from($this->getResource()->getTable('catalog_product_entity')) ->where('sku = ?', $sku) ->columns($this->getProductEntityLinkField()) ); foreach ($attributes as $attributeId => $storeValues) { foreach ($storeValues as $storeId => $storeValue) { if ($storeValue !== null || $storeId==0) { if ($storeValue == ' ')$storeValue=''; $tableData[] = [ $this->getProductEntityLinkField() => $linkId, 'attribute_id' => $attributeId, 'store_id' => $storeId, 'value' => $storeValue, ]; } else { $connection = $this->_connection; $affectedRows = $connection->delete($tableName, array( $this->getProductEntityLinkField().'=?' => $linkId, 'attribute_id=?' => $attributeId, 'store_id=?' => $storeId, )); } } } } $this->_connection->insertOnDuplicate($tableName, $tableData, ['value']); } return $this; } public function isAttributeValid($attrCode, array $attrParams, array $rowData, $rowNum) { // return false; if (!$this->validator->isAttributeValid($attrCode, $attrParams, $rowData)) { foreach ($this->validator->getMessages() as $message) { $this->addRowError($message, $rowNum, $attrCode); } return false; } return true; } protected function getExistingImages($bunch) { return []; $result = []; if ($this->getErrorAggregator()->hasToBeTerminated()) { return $result; } $this->initMediaGalleryResources(); $productSKUs = array_map('strval', array_column($bunch, self::COL_SKU)); $select = $this->_connection->select()->from( ['mg' => $this->mediaGalleryTableName], ['value' => 'mg.value'] )->joinInner( ['mgvte' => $this->mediaGalleryEntityToValueTableName], '(mg.value_id = mgvte.value_id)', [$this->getProductEntityLinkField() => 'mgvte.' . $this->getProductEntityLinkField()] )->joinInner( ['pe' => $this->productEntityTableName], "(mgvte.{$this->getProductEntityLinkField()} = pe.{$this->getProductEntityLinkField()})", ['sku' => 'pe.sku'] )->where( 'pe.sku IN (?)', $productSKUs ); foreach ($this->_connection->fetchAll($select) as $image) { $result[$image['sku']][$image['value']] = true; } return $result; } public function getBehavior() { if (isset($this->_parameters['behavior']) && $this->_parameters['behavior'] == \Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE) { return $this->_parameters['behavior']; } if (!isset( $this->_parameters['behavior'] ) || $this->_parameters['behavior'] != \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND && $this->_parameters['behavior'] != \Magento\ImportExport\Model\Import::BEHAVIOR_REPLACE && $this->_parameters['behavior'] != \Magento\ImportExport\Model\Import::BEHAVIOR_DELETE ) { return \Magento\ImportExport\Model\Import::getDefaultBehavior(); } return $this->_parameters['behavior']; } protected function _saveProducts() { $cc = \Magento\Framework\App\ObjectManager::getInstance()->get(CatalogConfig::class); $priceIsGlobal = $this->_catalogData->isPriceGlobal(); $productLimit = null; $productsQty = null; $entityLinkField = $this->getProductEntityLinkField(); while ($bunch = $this->_dataSourceModel->getNextBunch()) { $entityRowsIn = []; $entityRowsUp = []; $attributes = []; $this->websitesCache = []; $this->categoriesCache = []; $tierPrices = []; $mediaGallery = []; $uploadedImages = []; $previousType = null; $prevAttributeSet = null; $existingImages = $this->getExistingImages($bunch); foreach ($bunch as $rowNum => $rowData) { if (!$this->validateRow($rowData, $rowNum)) { continue; } if ($this->getErrorAggregator()->hasToBeTerminated()) { $this->getErrorAggregator()->addRowToSkip($rowNum); continue; } $rowScope = $this->getRowScope($rowData); if (!array_key_exists(self::URL_KEY, $rowData) || ($rowData[self::URL_KEY] !== null && $rowData[self::URL_KEY] != '###EMPTY###')) { $rowData[self::URL_KEY] = $this->getUrlKey($rowData); } $rowSku = $rowData[self::COL_SKU]; if (null === $rowSku) { $this->getErrorAggregator()->addRowToSkip($rowNum); continue; } elseif (self::SCOPE_STORE == $rowScope) { // set necessary data from SCOPE_DEFAULT row $rowData[self::COL_TYPE] = $this->skuProcessor->getNewSku($rowSku)['type_id']; $rowData['attribute_set_id'] = $this->skuProcessor->getNewSku($rowSku)['attr_set_id']; $rowData[self::COL_ATTR_SET] = $this->skuProcessor->getNewSku($rowSku)['attr_set_code']; } // 1. Entity phase if (isset($this->_oldSku[$rowSku])) { // existing row if (isset($rowData['attribute_set_code'])) { $attributeSetId = $cc->getAttributeSetId( $this->getEntityTypeId(), $rowData['attribute_set_code'] ); // wrong attribute_set_code was received if (!$attributeSetId) { throw new \Magento\Framework\Exception\LocalizedException( __( 'Wrong attribute set code "%1", please correct it and try again.', $rowData['attribute_set_code'] ) ); } } else { $attributeSetId = $this->skuProcessor->getNewSku($rowSku)['attr_set_id']; } $entityRowsUp[] = [ 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), 'attribute_set_id' => $attributeSetId, $entityLinkField => $this->_oldSku[$rowSku][$this->getProductEntityLinkField()], ]; } else { if (!$productLimit || $productsQty < $productLimit) { $entityRowsIn[$rowSku] = [ 'attribute_set_id' => $this->skuProcessor->getNewSku($rowSku)['attr_set_id'], 'type_id' => $this->skuProcessor->getNewSku($rowSku)['type_id'], 'sku' => $rowSku, 'has_options' => isset($rowData['has_options']) ? $rowData['has_options'] : 0, 'created_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), ]; $productsQty++; } else { $rowSku = null; // sign for child rows to be skipped $this->getErrorAggregator()->addRowToSkip($rowNum); continue; } } if (!array_key_exists($rowSku, $this->websitesCache)) { $this->websitesCache[$rowSku] = []; } // 2. Product-to-Website phase if (!empty($rowData[self::COL_PRODUCT_WEBSITES])) { $websiteCodes = explode($this->getMultipleValueSeparator(), $rowData[self::COL_PRODUCT_WEBSITES]); foreach ($websiteCodes as $websiteCode) { $websiteId = $this->storeResolver->getWebsiteCodeToId($websiteCode); $this->websitesCache[$rowSku][$websiteId] = true; } } // 3. Categories phase if (!array_key_exists($rowSku, $this->categoriesCache)) { $this->categoriesCache[$rowSku] = []; } $rowData['rowNum'] = $rowNum; $categoryIds = $this->processRowCategories($rowData); foreach ($categoryIds as $id) { $this->categoriesCache[$rowSku][$id] = true; } unset($rowData['rowNum']); // 4.1. Tier prices phase if (!empty($rowData['_tier_price_website'])) { if ($rowData['_tier_price_website'] === null){ $tierPrices[$rowSku] = array(); }else{ $tierPrices[$rowSku][] = [ 'all_groups' => $rowData['_tier_price_customer_group'] == self::VALUE_ALL, 'customer_group_id' => $rowData['_tier_price_customer_group'] == self::VALUE_ALL ? 0 : $rowData['_tier_price_customer_group'], 'qty' => $rowData['_tier_price_qty'], 'value' => $rowData['_tier_price_price'], 'website_id' => self::VALUE_ALL == $rowData['_tier_price_website'] || $priceIsGlobal ? 0 : $this->storeResolver->getWebsiteCodeToId($rowData['_tier_price_website']), ]; } } if (!$this->validateRow($rowData, $rowNum)) { continue; } // 5. Media gallery phase $disabledImages = []; list($rowImages, $rowLabels) = $this->getImagesFromRow($rowData); if (isset($rowData['_media_is_disabled'])) { $disabledImages = array_flip( explode($this->getMultipleValueSeparator(), $rowData['_media_is_disabled']) ); } $rowData[self::COL_MEDIA_IMAGE] = []; /* * Note: to avoid problems with undefined sorting, the value of media gallery items positions * must be unique in scope of one product. */ $position = 0; foreach ($rowImages as $column => $columnImages) { foreach ($columnImages as $columnImageKey => $columnImage) { if (!isset($uploadedImages[$columnImage])) { $uploadedFile = $this->uploadMediaFiles(trim($columnImage), true); if ($uploadedFile) { $uploadedImages[$columnImage] = $uploadedFile; } else { $this->addRowError( ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE, $rowNum, null, null, ProcessingError::ERROR_LEVEL_NOT_CRITICAL ); } } else { $uploadedFile = $uploadedImages[$columnImage]; } if ($uploadedFile && $column !== self::COL_MEDIA_IMAGE) { $rowData[$column] = $uploadedFile; } $imageNotAssigned = !isset($existingImages[$rowSku][$uploadedFile]); if ($uploadedFile && $imageNotAssigned) { if ($column == self::COL_MEDIA_IMAGE) { $rowData[$column][] = $uploadedFile; } $label = isset($rowLabels[$column][$columnImageKey]) ? $rowLabels[$column][$columnImageKey] : ''; $mediaGallery[$rowSku][] = [ 'attribute_id' => $this->getMediaGalleryAttributeId(), 'label' => $label, 'position' => ++$position, 'disabled' => isset($disabledImages[$columnImage]) ? '1' : '0', 'value' => $uploadedFile, ]; $existingImages[$rowSku][$uploadedFile] = true; } } } // 6. Attributes phase $rowStore = (self::SCOPE_STORE == $rowScope) ? $this->storeResolver->getStoreCodeToId($rowData[self::COL_STORE]) : 0; $productType = isset($rowData[self::COL_TYPE]) ? $rowData[self::COL_TYPE] : null; if (!is_null($productType)) { $previousType = $productType; } if (isset($rowData[self::COL_ATTR_SET])) { $prevAttributeSet = $rowData[self::COL_ATTR_SET]; } if (self::SCOPE_NULL == $rowScope) { // for multiselect attributes only if (!is_null($prevAttributeSet)) { $rowData[self::COL_ATTR_SET] = $prevAttributeSet; } if (is_null($productType) && !is_null($previousType)) { $productType = $previousType; } if (is_null($productType)) { continue; } } $productTypeModel = $this->_productTypeModels[$productType]; if (!empty($rowData['tax_class_name'])) { $rowData['tax_class_id'] = $this->taxClassProcessor->upsertTaxClass($rowData['tax_class_name'], $productTypeModel); } if ($this->getBehavior() == Import::BEHAVIOR_ADD_UPDATE || $this->getBehavior() == Import::BEHAVIOR_APPEND || empty($rowData[self::COL_SKU]) ) { $rowData = $productTypeModel->clearEmptyData($rowData); } $rowData = $productTypeModel->prepareAttributesWithDefaultValueForSave( $rowData, !isset($this->_oldSku[$rowSku]) ); $product = $this->_proxyProdFactory->create(['data' => $rowData]); foreach ($rowData as $attrCode => $attrValue) { $attribute = $this->retrieveAttributeByCode($attrCode); if ('multiselect' != $attribute->getFrontendInput() && self::SCOPE_NULL == $rowScope) { // skip attribute processing for SCOPE_NULL rows continue; } $attrId = $attribute->getId(); $backModel = $attribute->getBackendModel(); $attrTable = $attribute->getBackend()->getTable(); $storeIds = [0]; if ( 'datetime' == $attribute->getBackendType() && ( in_array($attribute->getAttributeCode(), $this->dateAttrCodes) || $attribute->getIsUserDefined() ) ) { $attrValue = $this->dateTime->formatDate($attrValue, false); } else if ('datetime' == $attribute->getBackendType() && strtotime($attrValue)) { $attrValue = $this->dateTime->gmDate( 'Y-m-d H:i:s', $this->_localeDate->date($attrValue)->getTimestamp() ); } elseif ($backModel) { $attribute->getBackend()->beforeSave($product); $attrValue = $product->getData($attribute->getAttributeCode()); } if (self::SCOPE_STORE == $rowScope) { if (self::SCOPE_WEBSITE == $attribute->getIsGlobal()) { // check website defaults already set if (!isset($attributes[$attrTable][$rowSku][$attrId][$rowStore])) { $storeIds = $this->storeResolver->getStoreIdToWebsiteStoreIds($rowStore); } } elseif (self::SCOPE_STORE == $attribute->getIsGlobal()) { $storeIds = [$rowStore]; } if (!isset($this->_oldSku[$rowSku])) { $storeIds[] = 0; } } foreach ($storeIds as $storeId) { if (!isset($attributes[$attrTable][$rowSku][$attrId][$storeId])) { $attributes[$attrTable][$rowSku][$attrId][$storeId] = $attrValue; } } // restore 'backend_model' to avoid 'default' setting $attribute->setBackendModel($backModel); } } foreach ($bunch as $rowNum => $rowData) { if ($this->getErrorAggregator()->isRowInvalid($rowNum)) { unset($bunch[$rowNum]); } } $this->saveProductEntity( $entityRowsIn, $entityRowsUp )->_saveProductWebsites( $this->websitesCache )->_saveProductCategories( $this->categoriesCache )->_saveProductTierPrices( $tierPrices )->_saveMediaGallery( $mediaGallery )->_saveProductAttributes( $attributes ); $this->_eventManager->dispatch( 'catalog_product_import_bunch_save_after', ['adapter' => $this, 'bunch' => $bunch] ); } return $this; } protected function _saveMediaGallery(array $mediaGalleryData) { if (empty($mediaGalleryData)) { return $this; } $cb = function ($data) use (&$cb) { if (!is_array($data)) return false; if (array_key_exists('value', $data)) { return (trim($data['value']) && $data['value'] != '###EMPTY###') ? $data : false; } $data = array_map($cb, $data); return array_filter($data); }; if (1||\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->initMediaGalleryResources(); $arrSKUS = []; //foreach ($mediaGalleryData as $arrStoreData) { $arrSKUS = array_merge($arrSKUS, array_keys((array)$mediaGalleryData)); //} $arrSKUS = array_unique($arrSKUS); $productIds = []; foreach ($arrSKUS as $productSku) { $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; $productIds[] = $productId; $this->_connection->delete( $this->mediaGalleryEntityToValueTableName, $this->_connection->quoteInto($this->getProductEntityLinkField().' IN (?)', $productId) ); $this->_connection->delete( $this->mediaGalleryValueTableName, $this->_connection->quoteInto($this->getProductEntityLinkField().' IN (?)', $productId) ); } } $mediaGalleryData = $cb($mediaGalleryData); return parent::_saveMediaGallery($mediaGalleryData); } protected function _saveMediaGallery1(array $mediaGalleryData) { if (empty($mediaGalleryData)) { return $this; } $this->initMediaGalleryResources(); $productIds = []; $imageNames = []; $multiInsertData = []; $valueToProductId = []; foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { $productId = $this->skuProcessor->getNewSku($productSku)[$this->getProductEntityLinkField()]; $productIds[] = $productId; $insertedGalleryImgs = []; if (\Magento\ImportExport\Model\Import::BEHAVIOR_APPEND != $this->getBehavior()) { $this->_connection->delete( $this->mediaGalleryEntityToValueTableName, array($this->getProductEntityLinkField() => $productId) ); } foreach ($mediaGalleryRows as $insertValue) { if (!in_array($insertValue['value'], $insertedGalleryImgs)) { $valueArr = [ 'attribute_id' => $insertValue['attribute_id'], 'value' => $insertValue['value'], ]; $valueToProductId[$insertValue['value']][] = $productId; $imageNames[] = $insertValue['value']; $multiInsertData[] = $valueArr; $insertedGalleryImgs[] = $insertValue['value']; } } } $oldMediaValues = $this->_connection->fetchAssoc( $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames) ); $this->_connection->insertOnDuplicate($this->mediaGalleryTableName, $multiInsertData, []); $multiInsertData = []; $newMediaSelect = $this->_connection->select()->from($this->mediaGalleryTableName, ['value_id', 'value']) ->where('value IN (?)', $imageNames); if (array_keys($oldMediaValues)) { $newMediaSelect->where('value_id NOT IN (?)', array_keys($oldMediaValues)); } $dataForSkinnyTable = []; $newMediaValues = $this->_connection->fetchAssoc($newMediaSelect); foreach ($mediaGalleryData as $productSku => $mediaGalleryRows) { foreach ($mediaGalleryRows as $insertValue) { foreach ($newMediaValues as $value_id => $values) { if ($values['value'] == $insertValue['value']) { $insertValue['value_id'] = $value_id; $insertValue[$this->getProductEntityLinkField()] = array_shift($valueToProductId[$values['value']]); unset($newMediaValues[$value_id]); break; } } if (isset($insertValue['value_id'])) { $valueArr = [ 'value_id' => $insertValue['value_id'], 'store_id' => \Magento\Store\Model\Store::DEFAULT_STORE_ID, $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], 'label' => $insertValue['label'], 'position' => $insertValue['position'], 'disabled' => $insertValue['disabled'], ]; $multiInsertData[] = $valueArr; $dataForSkinnyTable[] = [ 'value_id' => $insertValue['value_id'], $this->getProductEntityLinkField() => $insertValue[$this->getProductEntityLinkField()], ]; } } } try { $this->_connection->insertOnDuplicate( $this->mediaGalleryValueTableName, $multiInsertData, ['value_id', 'store_id', $this->getProductEntityLinkField(), 'label', 'position', 'disabled'] ); $this->_connection->insertOnDuplicate( $this->mediaGalleryEntityToValueTableName, $dataForSkinnyTable, ['value_id'] ); $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); $objProductRepository = $objectManager->get('\Magento\Catalog\Api\ProductRepositoryInterface'); $objImageFacory = $objectManager->get('\Magento\Catalog\Model\Product\Image\CacheFactory'); foreach ($productIds as $intProduct) { try { /** @var Product $product */ $product = $objProductRepository->getById($intProduct); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { continue; } $imageCache = $objImageFacory->create(); $imageCache->generate($product); } } catch (\Exception $e) { $this->_connection->delete( $this->mediaGalleryTableName, $this->_connection->quoteInto('value_id IN (?)', $newMediaValues) ); } return $this; } public function validateRow(array $rowData, $rowNum) { if (!empty($rowData[self::COL_NAME]) && $rowData[self::COL_NAME] == '###EMPTY###') { $rowData[self::COL_NAME] = null; } return parent::validateRow($rowData, $rowNum); } protected function _saveProductCategories(array $categoriesData) { static $tableName = null; static $arrCleanCatgeoryIds = array(); if (!$tableName) { $tableName = $this->_resourceFactory->create()->getProductCategoryTable(); } if ($categoriesData) { $categoriesIn = []; $delProductId = []; $arrPos = []; $arrCurrentCatIds = []; foreach ($categoriesData as $delSku => $categories) { foreach (array_keys($categories) as $categoryId) { $arrPos[$categoryId] = 0; } } foreach ($categoriesData as $delSku => $categories) { $productId = $this->skuProcessor->getNewSku($delSku)['entity_id']; $delProductId[] = $productId; foreach (array_keys($categories) as $categoryId) { $arrPos[$categoryId]++; $categoriesIn[] = ['product_id' => $productId, 'category_id' => $categoryId, 'position' => $arrPos[$categoryId]]; $arrCurrentCatIds[] = $categoryId; } } $arrCurrentCatIds = array_unique($arrCurrentCatIds); $arrCatIdsToClean = array_diff($arrCurrentCatIds, $arrCleanCatgeoryIds); if (\Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE === $this->getBehavior() && !empty($arrCatIdsToClean)) { $this->_connection->delete( $tableName, $this->_connection->quoteInto('category_id IN ('. rtrim(str_repeat('?,', count($arrCatIdsToClean)),',').')', $arrCatIdsToClean) ); $arrCleanCatgeoryIds = array_merge($arrCleanCatgeoryIds, $arrCatIdsToClean); } if (Import::BEHAVIOR_APPEND != $this->getBehavior() && \Magento\ImportExport\Model\Import::BEHAVIOR_ADD_UPDATE != $this->getBehavior()) { $this->_connection->delete( $tableName, $this->_connection->quoteInto('product_id IN (?)', $delProductId) ); } if ($categoriesIn) { $this->_connection->insertOnDuplicate($tableName, $categoriesIn, ['product_id', 'category_id']); } } return $this; } protected function getUrlKey($rowData) { $key = parent::getUrlKey($rowData); if ($key === 'empty') { if (empty($rowData[self::URL_KEY]) && (!empty($rowData[self::COL_NAME])) && ($rowData[self::COL_NAME] === '###EMPTY###')){ return null; } } return $key; } protected function _initSkus() { $this->skuProcessor->reloadOldSkus(); parent::_initSkus(); foreach ($this->_oldSku as $sku => $v) { $this->_oldSku[strtolower($sku)] = $v; } return $this; } public function saveProductEntity(array $entityRowsIn, array $entityRowsUp) { parent::saveProductEntity($entityRowsIn, $entityRowsUp); foreach ($this->_oldSku as $sku => $v) { $this->_oldSku[strtolower($sku)] = $v; } return $this; } }