3
3
* Copyright © Magento, Inc. All rights reserved.
4
4
* See COPYING.txt for license details.
5
5
*/
6
+
6
7
namespace Magento \CatalogImportExport \Model \Import ;
7
8
8
9
use Magento \Catalog \Api \ProductRepositoryInterface ;
9
10
use Magento \Catalog \Model \Config as CatalogConfig ;
10
11
use Magento \Catalog \Model \Product \Visibility ;
11
- use Magento \CatalogImportExport \Model \Import \Product \MediaGalleryProcessor ;
12
12
use Magento \CatalogImportExport \Model \Import \Product \ImageTypeProcessor ;
13
+ use Magento \CatalogImportExport \Model \Import \Product \MediaGalleryProcessor ;
13
14
use Magento \CatalogImportExport \Model \Import \Product \RowValidatorInterface as ValidatorInterface ;
14
- use Magento \CatalogInventory \Api \Data \StockItemInterface ;
15
15
use Magento \CatalogImportExport \Model \StockItemImporterInterface ;
16
+ use Magento \CatalogInventory \Api \Data \StockItemInterface ;
16
17
use Magento \Framework \App \Filesystem \DirectoryList ;
17
18
use Magento \Framework \App \ObjectManager ;
18
19
use Magento \Framework \Exception \LocalizedException ;
@@ -307,7 +308,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
307
308
ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE => 'Imported resource (image) could not be downloaded from external resource due to timeout or access permissions ' ,
308
309
ValidatorInterface::ERROR_INVALID_WEIGHT => 'Product weight is invalid ' ,
309
310
ValidatorInterface::ERROR_DUPLICATE_URL_KEY => 'Url key: \'%s \' was already generated for an item with the SKU: \'%s \'. You need to specify the unique URL key manually ' ,
310
- ValidatorInterface::ERROR_DUPLICATE_MULTISELECT_VALUES => " Value for multiselect attribute %s contains duplicated values " ,
311
+ ValidatorInterface::ERROR_DUPLICATE_MULTISELECT_VALUES => ' Value for multiselect attribute %s contains duplicated values ' ,
311
312
ValidatorInterface::ERROR_NEW_TO_DATE => 'Make sure new_to_date is later than or the same as new_from_date ' ,
312
313
];
313
314
//@codingStandardsIgnoreEnd
@@ -795,6 +796,8 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
795
796
* @param StockItemImporterInterface|null $stockItemImporter
796
797
* @param DateTimeFactory $dateTimeFactory
797
798
* @param ProductRepositoryInterface|null $productRepository
799
+ * @throws LocalizedException
800
+ * @throws \Magento\Framework\Exception\FileSystemException
798
801
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
799
802
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
800
803
*/
@@ -913,7 +916,7 @@ public function isAttributeValid($attrCode, array $attrParams, array $rowData, $
913
916
{
914
917
if (!$ this ->validator ->isAttributeValid ($ attrCode , $ attrParams , $ rowData )) {
915
918
foreach ($ this ->validator ->getMessages () as $ message ) {
916
- $ this ->addRowError ( $ message , $ rowNum , $ attrCode );
919
+ $ this ->skipRow ( $ rowNum , $ message , ProcessingError:: ERROR_LEVEL_NOT_CRITICAL , $ attrCode );
917
920
}
918
921
return false ;
919
922
}
@@ -1646,19 +1649,16 @@ protected function _saveProducts()
1646
1649
continue ;
1647
1650
}
1648
1651
if ($ this ->getErrorAggregator ()->hasToBeTerminated ()) {
1649
- $ validationStrategy = $ this ->_parameters [Import::FIELD_NAME_VALIDATION_STRATEGY ];
1650
- if (ProcessingErrorAggregatorInterface::VALIDATION_STRATEGY_SKIP_ERRORS !== $ validationStrategy ) {
1651
- $ this ->getErrorAggregator ()->addRowToSkip ($ rowNum );
1652
- continue ;
1653
- }
1652
+ $ this ->getErrorAggregator ()->addRowToSkip ($ rowNum );
1653
+ continue ;
1654
1654
}
1655
1655
$ rowScope = $ this ->getRowScope ($ rowData );
1656
1656
1657
1657
$ urlKey = $ this ->getUrlKey ($ rowData );
1658
1658
if (!empty ($ rowData [self ::URL_KEY ])) {
1659
1659
// If url_key column and its value were in the CSV file
1660
1660
$ rowData [self ::URL_KEY ] = $ urlKey ;
1661
- } else if ($ this ->isNeedToChangeUrlKey ($ rowData )) {
1661
+ } elseif ($ this ->isNeedToChangeUrlKey ($ rowData )) {
1662
1662
// If url_key column was empty or even not declared in the CSV file but by the rules it is need to
1663
1663
// be setteed. In case when url_key is generating from name column we have to ensure that the bunch
1664
1664
// of products will pass for the event with url_key column.
@@ -1670,7 +1670,9 @@ protected function _saveProducts()
1670
1670
if (null === $ rowSku ) {
1671
1671
$ this ->getErrorAggregator ()->addRowToSkip ($ rowNum );
1672
1672
continue ;
1673
- } elseif (self ::SCOPE_STORE == $ rowScope ) {
1673
+ }
1674
+
1675
+ if (self ::SCOPE_STORE == $ rowScope ) {
1674
1676
// set necessary data from SCOPE_DEFAULT row
1675
1677
$ rowData [self ::COL_TYPE ] = $ this ->skuProcessor ->getNewSku ($ rowSku )['type_id ' ];
1676
1678
$ rowData ['attribute_set_id ' ] = $ this ->skuProcessor ->getNewSku ($ rowSku )['attr_set_id ' ];
@@ -1806,13 +1808,7 @@ protected function _saveProducts()
1806
1808
$ uploadedImages [$ columnImage ] = $ uploadedFile ;
1807
1809
} else {
1808
1810
unset($ rowData [$ column ]);
1809
- $ this ->addRowError (
1810
- ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE ,
1811
- $ rowNum ,
1812
- null ,
1813
- null ,
1814
- ProcessingError::ERROR_LEVEL_NOT_CRITICAL
1815
- );
1811
+ $ this ->skipRow ($ rowNum , ValidatorInterface::ERROR_MEDIA_URL_NOT_ACCESSIBLE );
1816
1812
}
1817
1813
} else {
1818
1814
$ uploadedFile = $ uploadedImages [$ columnImage ];
@@ -2436,6 +2432,7 @@ public function getRowScope(array $rowData)
2436
2432
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
2437
2433
* @SuppressWarnings(PHPMD.NPathComplexity)
2438
2434
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
2435
+ * @throws \Zend_Validate_Exception
2439
2436
*/
2440
2437
public function validateRow (array $ rowData , $ rowNum )
2441
2438
{
@@ -2451,32 +2448,35 @@ public function validateRow(array $rowData, $rowNum)
2451
2448
// BEHAVIOR_DELETE and BEHAVIOR_REPLACE use specific validation logic
2452
2449
if (Import::BEHAVIOR_REPLACE == $ this ->getBehavior ()) {
2453
2450
if (self ::SCOPE_DEFAULT == $ rowScope && !$ this ->isSkuExist ($ sku )) {
2454
- $ this ->addRowError ( ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE , $ rowNum );
2451
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE );
2455
2452
return false ;
2456
2453
}
2457
2454
}
2458
2455
if (Import::BEHAVIOR_DELETE == $ this ->getBehavior ()) {
2459
2456
if (self ::SCOPE_DEFAULT == $ rowScope && !$ this ->isSkuExist ($ sku )) {
2460
- $ this ->addRowError ( ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE , $ rowNum );
2457
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_SKU_NOT_FOUND_FOR_DELETE );
2461
2458
return false ;
2462
2459
}
2463
2460
return true ;
2464
2461
}
2465
2462
2463
+ // if product doesn't exist, need to throw critical error else all errors should be not critical.
2464
+ $ errorLevel = $ this ->getValidationErrorLevel ($ sku );
2465
+
2466
2466
if (!$ this ->validator ->isValid ($ rowData )) {
2467
2467
foreach ($ this ->validator ->getMessages () as $ message ) {
2468
- $ this ->addRowError ( $ message , $ rowNum , $ this ->validator ->getInvalidAttribute ());
2468
+ $ this ->skipRow ( $ rowNum , $ message , $ errorLevel , $ this ->validator ->getInvalidAttribute ());
2469
2469
}
2470
2470
}
2471
2471
2472
2472
if (null === $ sku ) {
2473
- $ this ->addRowError ( ValidatorInterface::ERROR_SKU_IS_EMPTY , $ rowNum );
2473
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_SKU_IS_EMPTY , $ errorLevel );
2474
2474
} elseif (false === $ sku ) {
2475
- $ this ->addRowError ( ValidatorInterface::ERROR_ROW_IS_ORPHAN , $ rowNum );
2475
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_ROW_IS_ORPHAN , $ errorLevel );
2476
2476
} elseif (self ::SCOPE_STORE == $ rowScope
2477
2477
&& !$ this ->storeResolver ->getStoreCodeToId ($ rowData [self ::COL_STORE ])
2478
2478
) {
2479
- $ this ->addRowError ( ValidatorInterface::ERROR_INVALID_STORE , $ rowNum );
2479
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_INVALID_STORE , $ errorLevel );
2480
2480
}
2481
2481
2482
2482
// SKU is specified, row is SCOPE_DEFAULT, new product block begins
@@ -2491,16 +2491,15 @@ public function validateRow(array $rowData, $rowNum)
2491
2491
$ this ->prepareNewSkuData ($ sku )
2492
2492
);
2493
2493
} else {
2494
- $ this ->addRowError ( ValidatorInterface::ERROR_TYPE_UNSUPPORTED , $ rowNum );
2494
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_TYPE_UNSUPPORTED , $ errorLevel );
2495
2495
}
2496
2496
} else {
2497
2497
// validate new product type and attribute set
2498
- if (!isset ($ rowData [self ::COL_TYPE ]) || !isset ($ this ->_productTypeModels [$ rowData [self ::COL_TYPE ]])) {
2499
- $ this ->addRowError (ValidatorInterface::ERROR_INVALID_TYPE , $ rowNum );
2500
- } elseif (!isset ($ rowData [self ::COL_ATTR_SET ])
2501
- || !isset ($ this ->_attrSetNameToId [$ rowData [self ::COL_ATTR_SET ]])
2498
+ if (!isset ($ rowData [self ::COL_TYPE ], $ this ->_productTypeModels [$ rowData [self ::COL_TYPE ]])) {
2499
+ $ this ->skipRow ($ rowNum , ValidatorInterface::ERROR_INVALID_TYPE , $ errorLevel );
2500
+ } elseif (!isset ($ rowData [self ::COL_ATTR_SET ], $ this ->_attrSetNameToId [$ rowData [self ::COL_ATTR_SET ]])
2502
2501
) {
2503
- $ this ->addRowError ( ValidatorInterface::ERROR_INVALID_ATTR_SET , $ rowNum );
2502
+ $ this ->skipRow ( $ rowNum , ValidatorInterface::ERROR_INVALID_ATTR_SET , $ errorLevel );
2504
2503
} elseif ($ this ->skuProcessor ->getNewSku ($ sku ) === null ) {
2505
2504
$ this ->skuProcessor ->addNewSku (
2506
2505
$ sku ,
@@ -2556,8 +2555,11 @@ public function validateRow(array $rowData, $rowNum)
2556
2555
ValidatorInterface::ERROR_DUPLICATE_URL_KEY ,
2557
2556
$ rowNum ,
2558
2557
$ rowData [self ::COL_NAME ],
2559
- $ message
2560
- );
2558
+ $ message ,
2559
+ ProcessingError::ERROR_LEVEL_NOT_CRITICAL
2560
+ )
2561
+ ->getErrorAggregator ()
2562
+ ->addRowToSkip ($ rowNum );
2561
2563
}
2562
2564
}
2563
2565
}
@@ -2567,9 +2569,10 @@ public function validateRow(array $rowData, $rowNum)
2567
2569
$ newFromTimestamp = strtotime ($ this ->dateTime ->formatDate ($ rowData [self ::COL_NEW_FROM_DATE ], false ));
2568
2570
$ newToTimestamp = strtotime ($ this ->dateTime ->formatDate ($ rowData [self ::COL_NEW_TO_DATE ], false ));
2569
2571
if ($ newFromTimestamp > $ newToTimestamp ) {
2570
- $ this ->addRowError (
2571
- ValidatorInterface::ERROR_NEW_TO_DATE ,
2572
+ $ this ->skipRow (
2572
2573
$ rowNum ,
2574
+ ValidatorInterface::ERROR_NEW_TO_DATE ,
2575
+ $ errorLevel ,
2573
2576
$ rowData [self ::COL_NEW_TO_DATE ]
2574
2577
);
2575
2578
}
@@ -2588,8 +2591,8 @@ private function isNeedToValidateUrlKey($rowData)
2588
2591
{
2589
2592
return (!empty ($ rowData [self ::URL_KEY ]) || !empty ($ rowData [self ::COL_NAME ]))
2590
2593
&& (empty ($ rowData [self ::COL_VISIBILITY ])
2591
- || $ rowData [self ::COL_VISIBILITY ]
2592
- !== (string )Visibility::getOptionArray ()[Visibility::VISIBILITY_NOT_VISIBLE ]);
2594
+ || $ rowData [self ::COL_VISIBILITY ]
2595
+ !== (string )Visibility::getOptionArray ()[Visibility::VISIBILITY_NOT_VISIBLE ]);
2593
2596
}
2594
2597
2595
2598
/**
@@ -3095,4 +3098,38 @@ private function retrieveProductBySku($sku)
3095
3098
}
3096
3099
return $ product ;
3097
3100
}
3101
+
3102
+ /**
3103
+ * Add row as skipped
3104
+ *
3105
+ * @param int $rowNum
3106
+ * @param string $errorCode Error code or simply column name
3107
+ * @param string $errorLevel error level
3108
+ * @param string|null $colName optional column name
3109
+ * @return $this
3110
+ */
3111
+ private function skipRow (
3112
+ $ rowNum ,
3113
+ string $ errorCode ,
3114
+ string $ errorLevel = ProcessingError::ERROR_LEVEL_NOT_CRITICAL ,
3115
+ $ colName = null
3116
+ ): self {
3117
+ $ this ->addRowError ($ errorCode , $ rowNum , $ colName , null , $ errorLevel );
3118
+ $ this ->getErrorAggregator ()
3119
+ ->addRowToSkip ($ rowNum );
3120
+ return $ this ;
3121
+ }
3122
+
3123
+ /**
3124
+ * Returns errorLevel for validation
3125
+ *
3126
+ * @param string $sku
3127
+ * @return string
3128
+ */
3129
+ private function getValidationErrorLevel ($ sku ): string
3130
+ {
3131
+ return (!$ this ->isSkuExist ($ sku ) && Import::BEHAVIOR_REPLACE !== $ this ->getBehavior ())
3132
+ ? ProcessingError::ERROR_LEVEL_CRITICAL
3133
+ : ProcessingError::ERROR_LEVEL_NOT_CRITICAL ;
3134
+ }
3098
3135
}
0 commit comments