From c877ffd6a03347bc167b684170747261e8b68b0a Mon Sep 17 00:00:00 2001 From: Maikel Koek Date: Mon, 4 Sep 2023 10:08:43 +0200 Subject: [PATCH 01/12] fix(TEN-661): stream can't retrieve items with the caching middleware somehow after the latest magento upgrade. --- src/Streamer/HttpXml.php | 28 +--------------------------- 1 file changed, 1 insertion(+), 27 deletions(-) diff --git a/src/Streamer/HttpXml.php b/src/Streamer/HttpXml.php index c3c7f26..42ce2f1 100644 --- a/src/Streamer/HttpXml.php +++ b/src/Streamer/HttpXml.php @@ -128,33 +128,7 @@ public function getIterator() "Streamer\HttpXml: Getting data from URL {$this->requestUrl}" ); - $stack = \GuzzleHttp\HandlerStack::create(); - $stack->push(new \Kevinrob\GuzzleCache\CacheMiddleware( - new \Kevinrob\GuzzleCache\Strategy\GreedyCacheStrategy( - new \Kevinrob\GuzzleCache\Storage\Psr6CacheStorage( - $this->cacheItemPool - ), - $this->ttl - ) - ), 'cache'); - - $httpClient = new \GuzzleHttp\Client(['handler' => $stack]); - - $result = $httpClient->request( - $this->requestMethod, - $this->requestUrl, - $this->requestOptions + ['stream' => true, 'auth' => $this->auth] - ); - $stream = new \Prewk\XmlStringStreamer\Stream\Guzzle(''); - - if ($result->getHeader('X-Kevinrob-Cache') && $result->getHeader('X-Kevinrob-Cache')[0] == 'HIT') { - $this->consoleOutput->write(" [Cache {$result->getHeader('X-Kevinrob-Cache')[0]}]"); - } else { - $this->consoleOutput->write(" [Cache {$result->getHeader('X-Kevinrob-Cache')[0]}]"); - } - $this->consoleOutput->write("\n"); - - $stream->setGuzzleStream($result->getBody()); + $stream = new \Prewk\XmlStringStreamer\Stream\Guzzle($this->requestUrl); $class = isset($this->xmlOptions['uniqueNode']) ? UniqueNode::class : StringWalker::class; $parser = new $class($this->xmlOptions + [ From 2f0e986d23e60adadd3178672a451099007e1510 Mon Sep 17 00:00:00 2001 From: Maikel Koek Date: Mon, 4 Sep 2023 10:21:17 +0200 Subject: [PATCH 02/12] fix(TEN-661): update import output message to reflect errors --- src/Model/ImportProfile.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Model/ImportProfile.php b/src/Model/ImportProfile.php index 67e5159..95bd418 100644 --- a/src/Model/ImportProfile.php +++ b/src/Model/ImportProfile.php @@ -89,7 +89,10 @@ public function run() $errors = $importer->processImport($items); $stopwatchEvent = $this->stopwatch->stop('importinstance'); - $output = (string) new Phrase('%1 items imported in %2 sec, %3 items / sec (%4mb used)', [ + $message = $errors + ? 'Tried to import %1 items in %2 sec, %3 items / sec (%4mb used)' + : '%1 items imported in %2 sec, %3 items / sec (%4mb used)'; + $output = (string) new Phrase($message, [ count($items), round($stopwatchEvent->getDuration() / 1000, 1), round(count($items) / ($stopwatchEvent->getDuration() / 1000), 1), From d8cb2a5776a94e6eb80f76f186cc33021adf5940 Mon Sep 17 00:00:00 2001 From: Maikel Koek Date: Tue, 21 Nov 2023 15:09:49 +0100 Subject: [PATCH 03/12] feat(TEN-661): possibility to update products with same names By default, it's not possible to import products with the same name when URL key is not defined in the import data. When we update products, we omit the URL from the import data to prevent changes, so we have to make sure this doesn't throw errors. See also: https://github.com/magento/magento2/issues/13604 https://magento.stackexchange.com/questions/213036/url-was-already-generated-for-an-item-with-sku-error --- src/Rewrite/ImportExport/Import/Product.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Rewrite/ImportExport/Import/Product.php b/src/Rewrite/ImportExport/Import/Product.php index 91487d9..2fda31d 100644 --- a/src/Rewrite/ImportExport/Import/Product.php +++ b/src/Rewrite/ImportExport/Import/Product.php @@ -25,6 +25,7 @@ use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; use Magento\Store\Model\Store; +// prettier-ignore class Product extends \Magento\CatalogImportExport\Model\Import\Product { const SKIP_ATTRIBUTES_WHEN_UPDATING = '_import_skip_attributes_when_updating'; @@ -746,7 +747,7 @@ public function validateRow(array $rowData, $rowNum) */ private function isNeedToValidateUrlKey($rowData) { - return (!empty($rowData[self::URL_KEY]) || !empty($rowData[self::COL_NAME])) + return !empty($rowData[self::URL_KEY]) && (empty($rowData[self::COL_VISIBILITY]) || $rowData[self::COL_VISIBILITY] !== (string)Visibility::getOptionArray()[Visibility::VISIBILITY_NOT_VISIBLE]); From fe6ae605fda55bc6d9569fbafc63666fe2aac023 Mon Sep 17 00:00:00 2001 From: Maikel Koek Date: Wed, 22 Nov 2023 11:46:29 +0100 Subject: [PATCH 04/12] feat(TEN-661): store processed items in import profile class --- src/Api/ImportProfileInterface.php | 2 ++ src/Model/ImportProfile.php | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/src/Api/ImportProfileInterface.php b/src/Api/ImportProfileInterface.php index 4cf5bbe..ede89cf 100644 --- a/src/Api/ImportProfileInterface.php +++ b/src/Api/ImportProfileInterface.php @@ -15,6 +15,8 @@ interface ImportProfileInterface */ public function getItems(); + public function getProcessedItems(): array; + /** * Array of the config values * diff --git a/src/Model/ImportProfile.php b/src/Model/ImportProfile.php index 95bd418..5cab0c1 100644 --- a/src/Model/ImportProfile.php +++ b/src/Model/ImportProfile.php @@ -52,6 +52,8 @@ abstract class ImportProfile implements ImportProfileInterface */ private $errors = null; + private ?array $processedItems = null; + /** * @param ObjectManagerFactory $objectManagerFactory * @param Stopwatch $stopwatch @@ -105,6 +107,7 @@ public function run() $this->consoleOutput->writeln("$errors"); $this->log->error($errors); + $this->processedItems = $items; $this->errors = $errors; return \Magento\Framework\Console\Cli::RETURN_SUCCESS; @@ -138,6 +141,11 @@ public function getErrors() return $this->errors; } + public function getProcessedItems(): array + { + return $this->processedItems; + } + /** * Get all items that need to be imported * From 2878cd0c7c35a101877a7bd783af805f475e50dc Mon Sep 17 00:00:00 2001 From: Maikel Date: Tue, 10 Sep 2024 11:31:23 +0200 Subject: [PATCH 05/12] feat: update php to 8.1 in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a096921..afdfe9e 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "honl/magento2-import", "description": "", "require": { - "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0", + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.1", "guzzlehttp/guzzle": "^7", "prewk/xml-string-streamer": "^1.2", "prewk/xml-string-streamer-guzzle": "^1.2", From f1258fc2c8585ed4a3a23b9c19e0ea19a2547ffd Mon Sep 17 00:00:00 2001 From: Maikel Date: Tue, 10 Sep 2024 16:26:29 +0200 Subject: [PATCH 06/12] feat: update symfony/stopwatch to ~6.0 in composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index afdfe9e..7559367 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "prewk/xml-string-streamer-guzzle": "^1.2", "kevinrob/guzzle-cache-middleware": "^4", "ecomdev/magento-psr6-bridge": "^0.2.1", - "symfony/stopwatch": "~4.0", + "symfony/stopwatch": "~6.0", "bakame/psr7-csv-factory": "^1.0@dev", "league/csv": "^9.1", "monolog/monolog": "^2.8" From b73b9c1d6a6151c8f861d3f63dd6e80f860ca9ae Mon Sep 17 00:00:00 2001 From: Maikel Date: Wed, 11 Sep 2024 16:14:21 +0200 Subject: [PATCH 07/12] feat(TEN-830): updated php requirements --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 68b7bb4..6a068b2 100644 --- a/composer.json +++ b/composer.json @@ -2,7 +2,7 @@ "name": "honl/magento2-import", "description": "", "require": { - "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.2", + "php": "~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.1 || ~8.2", "guzzlehttp/guzzle": "^7", "prewk/xml-string-streamer": "^1.2", "prewk/xml-string-streamer-guzzle": "^1.2", From 627128409468f55adf34e4f456387b12813ae1cb Mon Sep 17 00:00:00 2001 From: Maikel Date: Wed, 11 Sep 2024 16:50:04 +0200 Subject: [PATCH 08/12] fix(TEN-830): use fork for magento-psr6-bridge dependency --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6a068b2..86b86b4 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "prewk/xml-string-streamer": "^1.2", "prewk/xml-string-streamer-guzzle": "^1.2", "kevinrob/guzzle-cache-middleware": "^4", - "ecomdev/magento-psr6-bridge": "^0.2.1", + "ho-nl-fork/magento-psr6-bridge": "^0.2.1", "symfony/stopwatch": "^v6.2", "bakame/psr7-csv-factory": "^1.0@dev", "league/csv": "^9.1", From deff17c015c70e33d3b1adfa23113345b4eda01f Mon Sep 17 00:00:00 2001 From: Maikel Date: Wed, 11 Sep 2024 16:53:20 +0200 Subject: [PATCH 09/12] updated dependency version for magento-psr6-bridge --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 86b86b4..c39c75c 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "prewk/xml-string-streamer": "^1.2", "prewk/xml-string-streamer-guzzle": "^1.2", "kevinrob/guzzle-cache-middleware": "^4", - "ho-nl-fork/magento-psr6-bridge": "^0.2.1", + "ho-nl-fork/magento-psr6-bridge": "dev-master", "symfony/stopwatch": "^v6.2", "bakame/psr7-csv-factory": "^1.0@dev", "league/csv": "^9.1", From 41a78f760984cc96a1c89bfb21f9b04883200c3d Mon Sep 17 00:00:00 2001 From: Maikel Date: Thu, 12 Sep 2024 09:59:54 +0200 Subject: [PATCH 10/12] fix(TEN-830): updated dependency for bakame/psr7-csv-factory --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c39c75c..b565655 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "kevinrob/guzzle-cache-middleware": "^4", "ho-nl-fork/magento-psr6-bridge": "dev-master", "symfony/stopwatch": "^v6.2", - "bakame/psr7-csv-factory": "^1.0@dev", + "ho-nl-fork/psr7-csv-factory": "dev-master", "league/csv": "^9.1", "monolog/monolog": "^2.8", "ext-mbstring": "*" From 19c81771c7ca3b93879bed598efcc430554add69 Mon Sep 17 00:00:00 2001 From: Maikel Koek Date: Mon, 16 Sep 2024 14:09:43 +0200 Subject: [PATCH 11/12] fix(TEN-830): replace deprecated _oldSku --- src/Rewrite/ImportExport/Import/Product.php | 290 ++++++++------------ 1 file changed, 121 insertions(+), 169 deletions(-) diff --git a/src/Rewrite/ImportExport/Import/Product.php b/src/Rewrite/ImportExport/Import/Product.php index 91487d9..c9ffe4e 100644 --- a/src/Rewrite/ImportExport/Import/Product.php +++ b/src/Rewrite/ImportExport/Import/Product.php @@ -12,10 +12,16 @@ use Magento\Catalog\Model\Config as CatalogConfig; use Magento\Catalog\Model\Product\Visibility; use Magento\CatalogImportExport\Model\Import\Product\ImageTypeProcessor; +use Magento\CatalogImportExport\Model\Import\Product\LinkProcessor; use Magento\CatalogImportExport\Model\Import\Product\MediaGalleryProcessor; use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface; +use Magento\CatalogImportExport\Model\Import\Product\SkuStorage; +use Magento\CatalogImportExport\Model\Import\Product\StatusProcessor; +use Magento\CatalogImportExport\Model\Import\Product\StockProcessor; use Magento\CatalogImportExport\Model\StockItemImporterInterface; +use Magento\CatalogImportExport\Model\StockItemProcessorInterface; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Filesystem\Driver\File; use Magento\Framework\Intl\DateTimeFactory; use Magento\Framework\Model\ResourceModel\Db\ObjectRelationProcessor; use Magento\Framework\Model\ResourceModel\Db\TransactionManagerInterface; @@ -25,68 +31,19 @@ use Magento\ImportExport\Model\Import\ErrorProcessing\ProcessingErrorAggregatorInterface; use Magento\Store\Model\Store; +/** + * @prettier-ignore + */ class Product extends \Magento\CatalogImportExport\Model\Import\Product { const SKIP_ATTRIBUTES_WHEN_UPDATING = '_import_skip_attributes_when_updating'; - /** @var LineFormatterMulti $lineFormatterMulti */ - private $lineFormatterMulti; - - /** @var CatalogConfig $catalogConfig */ - private $catalogConfig; - + private LineFormatterMulti $lineFormatterMulti; + private ?CatalogConfig $catalogConfig; /** @var string $productEntityLinkField */ private $productEntityLinkField; + private ?SkuStorage $skuStorage; - /** - * @param \Magento\Framework\Json\Helper\Data $jsonHelper - * @param \Magento\ImportExport\Helper\Data $importExportData - * @param \Magento\ImportExport\Model\ResourceModel\Import\Data $importData - * @param \Magento\Eav\Model\Config $config - * @param \Magento\Framework\App\ResourceConnection $resource - * @param \Magento\ImportExport\Model\ResourceModel\Helper $resourceHelper - * @param \Magento\Framework\Stdlib\StringUtils $string - * @param ProcessingErrorAggregatorInterface $errorAggregator - * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry - * @param \Magento\CatalogInventory\Api\StockConfigurationInterface $stockConfiguration - * @param \Magento\CatalogInventory\Model\Spi\StockStateProviderInterface $stockStateProvider - * @param \Magento\Catalog\Helper\Data $catalogData - * @param Import\Config $importConfig - * @param \Magento\CatalogImportExport\Model\Import\Proxy\Product\ResourceModelFactory $resourceFactory - * @param \Magento\CatalogImportExport\Model\Import\Product $optionFactory - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory $setColFactory - * @param \Magento\CatalogImportExport\Model\Import\Product $productTypeFactory - * @param \Magento\Catalog\Model\ResourceModel\Product\LinkFactory $linkFactory - * @param \Magento\CatalogImportExport\Model\Import\Proxy\ProductFactory $proxyProdFactory - * @param \Magento\CatalogImportExport\Model\Import\UploaderFactory $uploaderFactory - * @param \Magento\Framework\Filesystem $filesystem - * @param \Magento\CatalogInventory\Model\ResourceModel\Stock\ItemFactory $stockResItemFac - * @param DateTime\TimezoneInterface $localeDate - * @param DateTime $dateTime - * @param \Psr\Log\LoggerInterface $logger - * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry - * @param \Magento\CatalogImportExport\Model\Import\Product $storeResolver - * @param \Magento\CatalogImportExport\Model\Import\Product $skuProcessor - * @param \Magento\CatalogImportExport\Model\Import\Product $categoryProcessor - * @param \Magento\CatalogImportExport\Model\Import\Product $validator - * @param ObjectRelationProcessor $objectRelationProcessor - * @param TransactionManagerInterface $transactionManager - * @param \Magento\CatalogImportExport\Model\Import\Product $taxClassProcessor - * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig - * @param \Magento\Catalog\Model\Product\Url $productUrl - * @param array $data - * @param array $dateAttrCodes - * @param CatalogConfig|null $catalogConfig - * @param ImageTypeProcessor|null $imageTypeProcessor - * @param MediaGalleryProcessor|null $mediaProcessor - * @param StockItemImporterInterface|null $stockItemImporter - * @param DateTimeFactory|null $dateTimeFactory - * @param ProductRepositoryInterface|null $productRepository - * - * @throws \Magento\Framework\Exception\FileSystemException - * @throws \Magento\Framework\Exception\LocalizedException - */ public function __construct( \Magento\Framework\Json\Helper\Data $jsonHelper, \Magento\ImportExport\Helper\Data $importExportData, @@ -133,109 +90,70 @@ public function __construct( StockItemImporterInterface $stockItemImporter = null, DateTimeFactory $dateTimeFactory = null, ProductRepositoryInterface $productRepository = null, - $statusProcessor = null, - $stockProcessor = null + StatusProcessor $statusProcessor = null, + StockProcessor $stockProcessor = null, + LinkProcessor $linkProcessor = null, + ?File $fileDriver = null, + ?StockItemProcessorInterface $stockItemProcessor = null, + ?SkuStorage $skuStorage = null ) { - if ($statusProcessor && \is_a($statusProcessor, 'Magento\CatalogImportExport\Model\Import\Product\StatusProcessor')) { - parent::__construct( - $jsonHelper, - $importExportData, - $importData, - $config, - $resource, - $resourceHelper, - $string, - $errorAggregator, - $eventManager, - $stockRegistry, - $stockConfiguration, - $stockStateProvider, - $catalogData, - $importConfig, - $resourceFactory, - $optionFactory, - $setColFactory, - $productTypeFactory, - $linkFactory, - $proxyProdFactory, - $uploaderFactory, - $filesystem, - $stockResItemFac, - $localeDate, - $dateTime, - $logger, - $indexerRegistry, - $storeResolver, - $skuProcessor, - $categoryProcessor, - $validator, - $objectRelationProcessor, - $transactionManager, - $taxClassProcessor, - $scopeConfig, - $productUrl, - $data, - $dateAttrCodes, - $catalogConfig, - $imageTypeProcessor, - $mediaProcessor, - $stockItemImporter, - $dateTimeFactory, - $productRepository, - $statusProcessor, - $stockProcessor - ); - } else { - parent::__construct( - $jsonHelper, - $importExportData, - $importData, - $config, - $resource, - $resourceHelper, - $string, - $errorAggregator, - $eventManager, - $stockRegistry, - $stockConfiguration, - $stockStateProvider, - $catalogData, - $importConfig, - $resourceFactory, - $optionFactory, - $setColFactory, - $productTypeFactory, - $linkFactory, - $proxyProdFactory, - $uploaderFactory, - $filesystem, - $stockResItemFac, - $localeDate, - $dateTime, - $logger, - $indexerRegistry, - $storeResolver, - $skuProcessor, - $categoryProcessor, - $validator, - $objectRelationProcessor, - $transactionManager, - $taxClassProcessor, - $scopeConfig, - $productUrl, - $data, - $dateAttrCodes, - $catalogConfig, - $imageTypeProcessor, - $mediaProcessor, - $stockItemImporter, - $dateTimeFactory, - $productRepository - ); - } + parent::__construct( + $jsonHelper, + $importExportData, + $importData, + $config, + $resource, + $resourceHelper, + $string, + $errorAggregator, + $eventManager, + $stockRegistry, + $stockConfiguration, + $stockStateProvider, + $catalogData, + $importConfig, + $resourceFactory, + $optionFactory, + $setColFactory, + $productTypeFactory, + $linkFactory, + $proxyProdFactory, + $uploaderFactory, + $filesystem, + $stockResItemFac, + $localeDate, + $dateTime, + $logger, + $indexerRegistry, + $storeResolver, + $skuProcessor, + $categoryProcessor, + $validator, + $objectRelationProcessor, + $transactionManager, + $taxClassProcessor, + $scopeConfig, + $productUrl, + $data, + $dateAttrCodes, + $catalogConfig, + $imageTypeProcessor, + $mediaProcessor, + $stockItemImporter, + $dateTimeFactory, + $productRepository, + $statusProcessor, + $stockProcessor, + $linkProcessor, + $fileDriver, + $stockItemProcessor, + $skuStorage, + ); $this->lineFormatterMulti = $lineFormatterMulti; $this->catalogConfig = $catalogConfig ?: ObjectManager::getInstance()->get(CatalogConfig::class); + $this->skuStorage = $skuStorage ?? ObjectManager::getInstance() + ->get(SkuStorage::class); } /** @@ -316,7 +234,7 @@ protected function _saveProducts() } // 1. Entity phase - if (isset($this->_oldSku[\strtolower($rowSku)])) { + if ($this->isSkuExist($rowSku)) { // existing row if (isset($rowData['attribute_set_code'])) { $attributeSetId = $this->catalogConfig->getAttributeSetId( @@ -337,10 +255,11 @@ protected function _saveProducts() $attributeSetId = $this->skuProcessor->getNewSku($rowSku)['attr_set_id']; } // existing row + $entityLinkField = $this->getProductEntityLinkField(); $entityRowsUp[] = [ 'updated_at' => (new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT), 'attribute_set_id' => $attributeSetId, - $this->getProductEntityLinkField() => $this->_oldSku[\strtolower($rowSku)][$this->getProductEntityLinkField()], + $entityLinkField => $this->getExistingSku($rowSku)[$entityLinkField] ]; } else { if (!$productLimit || $productsQty < $productLimit) { @@ -505,7 +424,7 @@ protected function _saveProducts() $rowData = $productTypeModel->prepareAttributesWithDefaultValueForSave( $rowData, - !isset($this->_oldSku[strtolower($rowSku)]) + $this->isSkuExist($rowSku) ); $product = $this->_proxyProdFactory->create(['data' => $rowData]); @@ -551,7 +470,7 @@ protected function _saveProducts() } elseif (self::SCOPE_STORE == $attribute->getIsGlobal()) { $storeIds = [$rowStore]; } - if (!isset($this->_oldSku[strtolower($rowSku)])) { + if (!$this->isSkuExist($rowSku)) { $storeIds[] = 0; } } @@ -595,9 +514,11 @@ protected function _saveProducts() return $this; } - public function skipUpdatingAttribute($rowSku, $attrCode) + public function skipUpdatingAttribute($rowSku, $attrCode): bool { - return isset($this->_oldSku[strtolower($rowSku)]) && \array_key_exists(self::SKIP_ATTRIBUTES_WHEN_UPDATING, $this->_parameters) && \array_key_exists($attrCode, $this->_parameters[self::SKIP_ATTRIBUTES_WHEN_UPDATING]); + return $this->isSkuExist($rowSku) + && \array_key_exists(self::SKIP_ATTRIBUTES_WHEN_UPDATING, $this->_parameters) + && \array_key_exists($attrCode, $this->_parameters[self::SKIP_ATTRIBUTES_WHEN_UPDATING]); } /** @@ -633,11 +554,15 @@ public function validateRow(array $rowData, $rowNum) // check that row is already validated return !$this->getErrorAggregator()->isRowInvalid($rowNum); } + $this->_validatedRows[$rowNum] = true; + $rowScope = $this->getRowScope($rowData); + $sku = $rowData[self::COL_SKU]; + // BEHAVIOR_DELETE use specific validation logic if (Import::BEHAVIOR_DELETE == $this->getBehavior()) { - if (self::SCOPE_DEFAULT == $rowScope && !isset($this->_oldSku[strtolower($rowData[self::COL_SKU])])) { + if (self::SCOPE_DEFAULT == $rowScope && !$this->isSkuExist($sku)) { $this->addRowError(ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE, $rowNum); return false; } @@ -648,7 +573,7 @@ public function validateRow(array $rowData, $rowNum) $this->addRowError($message, $rowNum, $this->validator->getInvalidAttribute()); } } - $sku = $rowData[self::COL_SKU]; + if (null === $sku) { $this->addRowError(ValidatorInterface::ERROR_SKU_IS_EMPTY, $rowNum); } elseif (false === $sku) { @@ -660,11 +585,11 @@ public function validateRow(array $rowData, $rowNum) } // SKU is specified, row is SCOPE_DEFAULT, new product block begins $this->_processedEntitiesCount++; - $sku = $rowData[self::COL_SKU]; - if (isset($this->_oldSku[\strtolower($sku)])) { + + if ($this->isSkuExist($sku)) { // can we get all necessary data from existent DB product? // check for supported type of existing product - if (isset($this->_productTypeModels[$this->_oldSku[\strtolower($sku)]['type_id']])) { + if (isset($this->_productTypeModels[$this->getExistingSku($sku)['type_id']])) { $this->skuProcessor->addNewSku( $sku, $this->prepareNewSkuData($sku) @@ -709,7 +634,7 @@ public function validateRow(array $rowData, $rowNum) $rowAttributesValid = $this->_productTypeModels[$newSku['type_id']]->isRowValid( $rowData, $rowNum, - !isset($this->_oldSku[\strtolower($sku)]) + !($this->isSkuExist($sku)) ); if (!$rowAttributesValid && self::SCOPE_DEFAULT == $rowScope) { // mark SCOPE_DEFAULT row as invalid for future child rows if product not in DB already @@ -762,10 +687,37 @@ private function isNeedToValidateUrlKey($rowData) private function prepareNewSkuData($sku) { $data = []; - foreach ($this->_oldSku[\strtolower($sku)] as $key => $value) { - $data[$key] = $value; + foreach ($this->getExistingSku($sku) as $key => $value) { + $data[$key] = $value; } - $data['attr_set_code'] = $this->_attrSetIdToName[$this->_oldSku[\strtolower($sku)]['attr_set_id']]; + + $data['attr_set_code'] = $this->_attrSetIdToName[$this->getExistingSku($sku)['attr_set_id']]; + return $data; } + + /** + * Check if product exists for specified SKU + * + * @param string $sku + * @return bool + */ + private function isSkuExist($sku): bool + { + if ($sku !== null) { + return $this->skuStorage->has($sku); + } + return false; + } + + /** + * Get existing product data for specified SKU + * + * @param string $sku + * @return array + */ + private function getExistingSku($sku) + { + return $this->skuStorage->get((string)$sku); + } } From 976aad9edffbe6116a6b00cc583043d2b2a30f43 Mon Sep 17 00:00:00 2001 From: Wim Date: Mon, 14 Oct 2024 13:33:12 +0200 Subject: [PATCH 12/12] fix(TEN-835): prevent setting default attribute values on product that exist --- src/Rewrite/ImportExport/Import/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rewrite/ImportExport/Import/Product.php b/src/Rewrite/ImportExport/Import/Product.php index d8420fd..75fd9c8 100644 --- a/src/Rewrite/ImportExport/Import/Product.php +++ b/src/Rewrite/ImportExport/Import/Product.php @@ -424,7 +424,7 @@ protected function _saveProducts() $rowData = $productTypeModel->prepareAttributesWithDefaultValueForSave( $rowData, - $this->isSkuExist($rowSku) + !$this->isSkuExist($rowSku) ); $product = $this->_proxyProdFactory->create(['data' => $rowData]);