/**
  * Cover getCategoryById().
  *
  * @dataProvider getCategoryByIdDataProvider
  */
 public function testGetCategoryById($categoriesCache, $expectedResult)
 {
     $categoryId = 'category_id';
     $this->setPropertyValue($this->categoryProcessor, 'categoriesCache', $categoriesCache);
     $actualResult = $this->categoryProcessor->getCategoryById($categoryId);
     $this->assertEquals($expectedResult, $actualResult);
 }
Example #2
0
 /**
  * {@inheritdoc}
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  * @SuppressWarnings(PHPMD.NPathComplexity)
  */
 public function isValid($value)
 {
     $this->_clearMessages();
     $emptyCategory = empty($value[Product::COL_CATEGORY]);
     $emptyRootCategory = empty($value[Product::COL_ROOT_CATEGORY]);
     $hasCategory = $emptyCategory ? false : $this->categoryProcessor->getCategory($value[Product::COL_CATEGORY]) !== null;
     $category = $emptyRootCategory ? null : $this->categoryProcessor->getCategoryWithRoot($value[Product::COL_ROOT_CATEGORY]);
     if (!$emptyCategory && !$hasCategory || !$emptyRootCategory && !isset($category) || !$emptyRootCategory && !$emptyCategory && !isset($category[$value[Product::COL_CATEGORY]])) {
         $this->_addMessages([self::ERROR_INVALID_CATEGORY]);
         return false;
     }
     return true;
 }
Example #3
0
 /**
  * Gather and save information about product entities.
  *
  * @return $this
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  * @SuppressWarnings(PHPMD.NPathComplexity)
  * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  * @SuppressWarnings(PHPMD.UnusedLocalVariable)
  */
 protected function _saveProducts()
 {
     /** @var $resource \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceModel */
     $resource = $this->_resourceFactory->create();
     $priceIsGlobal = $this->_catalogData->isPriceGlobal();
     $productLimit = null;
     $productsQty = null;
     while ($bunch = $this->_dataSourceModel->getNextBunch()) {
         $entityRowsIn = [];
         $entityRowsUp = [];
         $attributes = [];
         $this->websitesCache = [];
         $this->categoriesCache = [];
         $tierPrices = [];
         $mediaGallery = [];
         $uploadedGalleryFiles = [];
         $previousType = null;
         $prevAttributeSet = null;
         $allImagesFromBunch = $this->_getAllBunchImages($bunch);
         $existingImages = $this->_prepareAllMediaFiles($allImagesFromBunch);
         foreach ($bunch as $rowNum => $rowData) {
             if (!$this->validateRow($rowData, $rowNum)) {
                 continue;
             }
             if ($this->getErrorAggregator()->hasToBeTerminated()) {
                 $this->getErrorAggregator()->addRowToSkip($rowNum);
                 continue;
             }
             $rowScope = $this->getRowScope($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
                 $entityRowsUp[] = ['updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), 'entity_id' => $this->_oldSku[$rowSku]['entity_id']];
             } 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;
                 }
             }
             $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
             $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY];
             $this->categoriesCache[$rowSku] = [];
             if (!empty($categoriesString)) {
                 foreach ($this->categoryProcessor->upsertCategories($categoriesString) as $categoryId) {
                     $this->categoriesCache[$rowSku][$categoryId] = true;
                 }
             }
             // 4.1. Tier prices phase
             if (!empty($rowData['_tier_price_website'])) {
                 $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
             $mediaGalleryImages = array();
             $mediaGalleryLabels = array();
             if (!empty($rowData[self::COL_MEDIA_IMAGE])) {
                 $mediaGalleryImages = explode($this->getMultipleValueSeparator(), $rowData[self::COL_MEDIA_IMAGE]);
                 if (isset($rowData['_media_image_label'])) {
                     $mediaGalleryLabels = explode($this->getMultipleValueSeparator(), $rowData['_media_image_label']);
                 } else {
                     $mediaGalleryLabels = [];
                 }
                 if (count($mediaGalleryLabels) > count($mediaGalleryImages)) {
                     $mediaGalleryLabels = array_slice($mediaGalleryLabels, 0, count($mediaGalleryImages));
                 } elseif (count($mediaGalleryLabels) < count($mediaGalleryImages)) {
                     $mediaGalleryLabels = array_pad($mediaGalleryLabels, count($mediaGalleryImages), '');
                 }
             }
             foreach ($this->_imagesArrayKeys as $imageCol) {
                 if (!empty($rowData[$imageCol]) && $imageCol != self::COL_MEDIA_IMAGE && !in_array($rowData[$imageCol], $mediaGalleryImages)) {
                     $mediaGalleryImages[] = $rowData[$imageCol];
                     if (isset($mediaGalleryLabels)) {
                         $mediaGalleryLabels[] = isset($rowData[$imageCol . '_label']) ? $rowData[$imageCol . '_label'] : '';
                     } else {
                         $mediaGalleryLabels[] = '';
                     }
                 }
             }
             $rowData[self::COL_MEDIA_IMAGE] = array();
             foreach ($mediaGalleryImages as $mediaImage) {
                 $imagePath = $allImagesFromBunch[$mediaImage];
                 if (isset($existingImages[$imagePath]) && in_array($rowSku, $existingImages[$imagePath])) {
                     if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
                         $uploadedFile = $this->_uploadMediaFiles(trim($mediaImage), true);
                         if ($uploadedFile) {
                             $uploadedGalleryFiles[$mediaImage] = $uploadedFile;
                         } else {
                             $this->addRowError(ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE, $rowNum, null, null, ProcessingError::ERROR_LEVEL_NOT_CRITICAL);
                         }
                     }
                 } elseif (!isset($existingImages[$imagePath])) {
                     if (!array_key_exists($mediaImage, $uploadedGalleryFiles)) {
                         $uploadedFile = $this->_uploadMediaFiles(trim($mediaImage), true);
                         if ($uploadedFile) {
                             $uploadedGalleryFiles[$mediaImage] = $uploadedFile;
                             $newImagePath = $uploadedGalleryFiles[$mediaImage];
                             $existingImages[$newImagePath][] = $rowSku;
                         } else {
                             $this->addRowError(ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE, $rowNum, null, null, ProcessingError::ERROR_LEVEL_NOT_CRITICAL);
                         }
                     }
                     if (isset($uploadedGalleryFiles[$mediaImage])) {
                         $rowData[self::COL_MEDIA_IMAGE][] = $uploadedGalleryFiles[$mediaImage];
                         if (!empty($rowData[self::COL_MEDIA_IMAGE]) && is_array($rowData[self::COL_MEDIA_IMAGE])) {
                             $position = array_search($mediaImage, $mediaGalleryImages);
                             foreach ($rowData[self::COL_MEDIA_IMAGE] as $mediaImage) {
                                 $mediaGallery[$rowSku][] = ['attribute_id' => $this->getMediaGalleryAttributeId(), 'label' => isset($mediaGalleryLabels[$position]) ? $mediaGalleryLabels[$position] : '', 'position' => $position, 'disabled' => '', 'value' => $mediaImage];
                             }
                         }
                     }
                 }
                 foreach ($this->_imagesArrayKeys as $imageCol) {
                     if (empty($rowData[$imageCol]) || $imageCol == self::COL_MEDIA_IMAGE) {
                         continue;
                     }
                     if (isset($existingImages[$imagePath]) && !in_array($rowSku, $existingImages[$imagePath]) && ($rowData[$imageCol] == $imagePath || $rowData[$imageCol] == $mediaImage)) {
                         unset($rowData[$imageCol]);
                     } elseif (isset($uploadedGalleryFiles[$rowData[$imageCol]])) {
                         $rowData[$imageCol] = $uploadedGalleryFiles[$rowData[$imageCol]];
                     }
                 }
             }
             // 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() == \Magento\ImportExport\Model\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() && strtotime($attrValue)) {
                     $attrValue = (new \DateTime())->setTimestamp(strtotime($attrValue));
                     $attrValue = $attrValue->format(DateTime::DATETIME_PHP_FORMAT);
                 } 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) {
                     $attributes[$attrTable][$rowSku][$attrId][$storeId] = $attrValue;
                 }
                 // restore 'backend_model' to avoid 'default' setting
                 $attribute->setBackendModel($backModel);
             }
         }
         $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;
 }
Example #4
0
 /**
  * @param array $rowData
  * @return array
  */
 protected function processRowCategories($rowData)
 {
     $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY];
     $categoryIds = [];
     if (!empty($categoriesString)) {
         $categoryIds = $this->categoryProcessor->upsertCategories($categoriesString, $this->getMultipleValueSeparator());
     }
     return $categoryIds;
 }
 /**
  * @param array $rowData
  * @return array
  */
 protected function processRowCategories($rowData)
 {
     $categoriesString = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY];
     $categoryIds = [];
     if (!empty($categoriesString)) {
         $categoryIds = $this->categoryProcessor->upsertCategories($categoriesString, $this->getMultipleValueSeparator());
         foreach ($this->categoryProcessor->getFailedCategories() as $error) {
             $this->errorAggregator->addError(AbstractEntity::ERROR_CODE_CATEGORY_NOT_VALID, ProcessingError::ERROR_LEVEL_NOT_CRITICAL, $rowData['rowNum'], self::COL_CATEGORY, __('Category "%1" has not been created.', $error['category']) . ' ' . $error['exception']->getMessage());
         }
     }
     return $categoryIds;
 }
Example #6
0
 public function testUpsertCategories()
 {
     $categoryIds = $this->categoryProcessor->upsertCategories(self::CHILD_CATEGORY_NAME);
     $this->assertArrayHasKey(self::CHILD_CATEGORY_ID, array_flip($categoryIds));
 }
Example #7
0
 /**
  * Gather and save information about product entities.
  *
  * @return $this
  * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  * @SuppressWarnings(PHPMD.NPathComplexity)
  * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
  */
 protected function _saveProducts()
 {
     /** @var $resource \Magento\CatalogImportExport\Model\Import\Proxy\Product\Resource */
     $resource = $this->_resourceFactory->create();
     $priceIsGlobal = $this->_catalogData->isPriceGlobal();
     $productLimit = null;
     $productsQty = null;
     while ($bunch = $this->_dataSourceModel->getNextBunch()) {
         $entityRowsIn = [];
         $entityRowsUp = [];
         $attributes = [];
         $websites = [];
         $categories = [];
         $tierPrices = [];
         $groupPrices = [];
         $mediaGallery = [];
         $uploadedGalleryFiles = [];
         $previousType = null;
         $prevAttributeSet = null;
         foreach ($bunch as $rowNum => $rowData) {
             if (!$this->validateRow($rowData, $rowNum)) {
                 continue;
             }
             $rowScope = $this->getRowScope($rowData);
             if (self::SCOPE_DEFAULT == $rowScope) {
                 $rowSku = $rowData[self::COL_SKU];
                 // 1. Entity phase
                 if (isset($this->_oldSku[$rowSku])) {
                     // existing row
                     $entityRowsUp[] = ['updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), 'entity_id' => $this->_oldSku[$rowSku]['entity_id']];
                 } else {
                     // new row
                     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->_rowsToSkip[$rowNum] = true;
                         continue;
                     }
                 }
             } elseif (null === $rowSku) {
                 $this->_rowsToSkip[$rowNum] = true;
                 // skip rows when SKU is NULL
                 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'];
             }
             // 2. Product-to-Website phase
             if (!empty($rowData['_product_websites'])) {
                 $websites[$rowSku][$this->storeResolver->getWebsiteCodeToId($rowData['_product_websites'])] = true;
             }
             // 3. Categories phase
             $categoryPath = empty($rowData[self::COL_CATEGORY]) ? '' : $rowData[self::COL_CATEGORY];
             if (!empty($rowData[self::COL_ROOT_CATEGORY])) {
                 $categoryId = $this->categoryProcessor->getCategoryWithRoot($rowData[self::COL_ROOT_CATEGORY], $categoryPath);
                 $categories[$rowSku][$categoryId] = true;
             } elseif (!empty($categoryPath)) {
                 $categories[$rowSku][$this->categoryProcessor->getCategory($categoryPath)] = true;
             }
             // 4.1. Tier prices phase
             if (!empty($rowData['_tier_price_website'])) {
                 $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'])];
             }
             // 4.2. Group prices phase
             if (!empty($rowData['_group_price_website'])) {
                 $groupPrices[$rowSku][] = ['all_groups' => $rowData['_group_price_customer_group'] == self::VALUE_ALL, 'customer_group_id' => $rowData['_group_price_customer_group'] == self::VALUE_ALL ? 0 : $rowData['_group_price_customer_group'], 'value' => $rowData['_group_price_price'], 'website_id' => self::VALUE_ALL == $rowData['_group_price_website'] || $priceIsGlobal ? 0 : $this->storeResolver->getWebsiteCodeToId($rowData['_group_price_website'])];
             }
             // 5. Media gallery phase
             foreach ($this->_imagesArrayKeys as $imageCol) {
                 if (!empty($rowData[$imageCol])) {
                     if (!array_key_exists($rowData[$imageCol], $uploadedGalleryFiles)) {
                         $uploadedGalleryFiles[$rowData[$imageCol]] = $this->_uploadMediaFiles($rowData[$imageCol]);
                     }
                     $rowData[$imageCol] = $uploadedGalleryFiles[$rowData[$imageCol]];
                 }
             }
             if (!empty($rowData['_media_image'])) {
                 $mediaGallery[$rowSku][] = ['attribute_id' => $rowData['_media_attribute_id'], 'label' => $rowData['_media_label'], 'position' => $rowData['_media_position'], 'disabled' => $rowData['_media_is_disabled'], 'value' => $rowData['_media_image']];
             }
             // 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;
                 }
             }
             if ($this->getBehavior() == \Magento\ImportExport\Model\Import::BEHAVIOR_APPEND || empty($rowData[self::COL_SKU])) {
                 $rowData = $this->_productTypeModels[$productType]->clearEmptyData($rowData);
             }
             $rowData = $this->_productTypeModels[$productType]->prepareAttributesWithDefaultValueForSave($rowData, !isset($this->_oldSku[$rowSku]));
             $product = $this->_proxyProdFactory->create(['data' => $rowData]);
             foreach ($rowData as $attrCode => $attrValue) {
                 $attribute = $resource->getAttribute($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() && strtotime($attrValue)) {
                     $attrValue = (new \DateTime())->setTimestamp(strtotime($attrValue));
                     $attrValue = $attrValue->format(DateTime::DATETIME_PHP_FORMAT);
                 } 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];
                     }
                 }
                 foreach ($storeIds as $storeId) {
                     if ('multiselect' == $attribute->getFrontendInput()) {
                         if (!isset($attributes[$attrTable][$rowSku][$attrId][$storeId])) {
                             $attributes[$attrTable][$rowSku][$attrId][$storeId] = '';
                         } else {
                             $attributes[$attrTable][$rowSku][$attrId][$storeId] .= ',';
                         }
                         $attributes[$attrTable][$rowSku][$attrId][$storeId] .= $attrValue;
                     } else {
                         $attributes[$attrTable][$rowSku][$attrId][$storeId] = $attrValue;
                     }
                 }
                 // restore 'backend_model' to avoid 'default' setting
                 $attribute->setBackendModel($backModel);
             }
         }
         $this->_saveProductEntity($entityRowsIn, $entityRowsUp)->_saveProductWebsites($websites)->_saveProductCategories($categories)->_saveProductTierPrices($tierPrices)->_saveProductGroupPrices($groupPrices)->_saveMediaGallery($mediaGallery)->_saveProductAttributes($attributes);
     }
     return $this;
 }