11
11
use Magento \CatalogImportExport \Model \Import \Product ;
12
12
use Magento \Framework \App \ResourceConnection ;
13
13
use Magento \ImportExport \Model \Import \ErrorProcessing \ProcessingErrorAggregatorInterface ;
14
- use Magento \Catalog \Api \Data \ProductInterface ;
14
+ use Magento \Catalog \Model \ResourceModel \Product \Option \Value \Collection as ProductOptionValueCollection ;
15
+ use Magento \Catalog \Model \ResourceModel \Product \Option \Value \CollectionFactory as ProductOptionValueCollectionFactory ;
15
16
16
17
/**
17
18
* Entity class which provide possibility to import product custom options
@@ -324,6 +325,16 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
324
325
*/
325
326
private $ productEntityIdentifierField ;
326
327
328
+ /**
329
+ * @var ProductOptionValueCollectionFactory
330
+ */
331
+ private $ productOptionValueCollectionFactory ;
332
+
333
+ /**
334
+ * @var array
335
+ */
336
+ private $ optionTypeTitles ;
337
+
327
338
/**
328
339
* @param \Magento\ImportExport\Model\ResourceModel\Import\Data $importData
329
340
* @param ResourceConnection $resource
@@ -337,8 +348,7 @@ class Option extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
337
348
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $dateTime
338
349
* @param ProcessingErrorAggregatorInterface $errorAggregator
339
350
* @param array $data
340
- * @throws \Magento\Framework\Exception\LocalizedException
341
- *
351
+ * @param ProductOptionValueCollectionFactory|null $productOptionValueCollectionFactory
342
352
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
343
353
*/
344
354
public function __construct (
@@ -353,7 +363,8 @@ public function __construct(
353
363
\Magento \Framework \App \Config \ScopeConfigInterface $ scopeConfig ,
354
364
\Magento \Framework \Stdlib \DateTime \TimezoneInterface $ dateTime ,
355
365
ProcessingErrorAggregatorInterface $ errorAggregator ,
356
- array $ data = []
366
+ array $ data = [],
367
+ ProductOptionValueCollectionFactory $ productOptionValueCollectionFactory = null
357
368
) {
358
369
$ this ->_resource = $ resource ;
359
370
$ this ->_catalogData = $ catalogData ;
@@ -365,6 +376,9 @@ public function __construct(
365
376
$ this ->_scopeConfig = $ scopeConfig ;
366
377
$ this ->dateTime = $ dateTime ;
367
378
379
+ $ this ->productOptionValueCollectionFactory = $ productOptionValueCollectionFactory
380
+ ?: \Magento \Framework \App \ObjectManager::getInstance ()->get (ProductOptionValueCollectionFactory::class);
381
+
368
382
if (isset ($ data ['connection ' ])) {
369
383
$ this ->_connection = $ data ['connection ' ];
370
384
} else {
@@ -781,15 +795,15 @@ protected function _addRowsErrors($errorCode, array $errorNumbers)
781
795
protected function _validateMainRow (array $ rowData , $ rowNumber )
782
796
{
783
797
if (!empty ($ rowData [self ::COLUMN_STORE ]) && !array_key_exists (
784
- $ rowData [self ::COLUMN_STORE ],
785
- $ this ->_storeCodeToId
786
- )
798
+ $ rowData [self ::COLUMN_STORE ],
799
+ $ this ->_storeCodeToId
800
+ )
787
801
) {
788
802
$ this ->_productEntity ->addRowError (self ::ERROR_INVALID_STORE , $ rowNumber );
789
803
} elseif (!empty ($ rowData [self ::COLUMN_TYPE ]) && !array_key_exists (
790
- $ rowData [self ::COLUMN_TYPE ],
791
- $ this ->_specificTypes
792
- )
804
+ $ rowData [self ::COLUMN_TYPE ],
805
+ $ this ->_specificTypes
806
+ )
793
807
) {
794
808
// type
795
809
$ this ->_productEntity ->addRowError (self ::ERROR_INVALID_TYPE , $ rowNumber );
@@ -894,9 +908,9 @@ protected function _saveNewOptionData(array $rowData, $rowNumber)
894
908
protected function _validateSecondaryRow (array $ rowData , $ rowNumber )
895
909
{
896
910
if (!empty ($ rowData [self ::COLUMN_STORE ]) && !array_key_exists (
897
- $ rowData [self ::COLUMN_STORE ],
898
- $ this ->_storeCodeToId
899
- )
911
+ $ rowData [self ::COLUMN_STORE ],
912
+ $ this ->_storeCodeToId
913
+ )
900
914
) {
901
915
$ this ->_productEntity ->addRowError (self ::ERROR_INVALID_STORE , $ rowNumber );
902
916
} elseif (!empty ($ rowData [self ::COLUMN_ROW_PRICE ]) && !is_numeric (rtrim ($ rowData [self ::COLUMN_ROW_PRICE ], '% ' ))
@@ -1125,7 +1139,7 @@ private function processOptionRow($name, $optionRow)
1125
1139
if (isset ($ optionRow ['price ' ])) {
1126
1140
$ percent_suffix = '' ;
1127
1141
if (isset ($ optionRow ['price_type ' ]) && $ optionRow ['price_type ' ] == 'percent ' ) {
1128
- $ percent_suffix = '% ' ;
1142
+ $ percent_suffix = '% ' ;
1129
1143
}
1130
1144
$ result [self ::COLUMN_ROW_PRICE ] = $ optionRow ['price ' ] . $ percent_suffix ;
1131
1145
}
@@ -1212,6 +1226,12 @@ protected function _importData()
1212
1226
if ($ this ->_isReadyForSaving ($ options , $ titles , $ typeValues )) {
1213
1227
if ($ this ->getBehavior () == \Magento \ImportExport \Model \Import::BEHAVIOR_APPEND ) {
1214
1228
$ this ->_compareOptionsWithExisting ($ options , $ titles , $ prices , $ typeValues );
1229
+
1230
+ $ optionsForRestore = $ this ->getRestoreOriginalOptionTypeIds ($ typeValues , $ typeTitles );
1231
+
1232
+ $ typeValues = $ this ->restoreTypeValues ($ typeValues , $ optionsForRestore );
1233
+ $ typePrices = $ this ->restoreOptionTypesData ($ typePrices , $ optionsForRestore );
1234
+ $ typeTitles = $ this ->restoreOptionTypesData ($ typeTitles , $ optionsForRestore );
1215
1235
}
1216
1236
1217
1237
$ this ->_saveOptions (
@@ -1278,12 +1298,12 @@ protected function _collectOptionMainData(
1278
1298
$ optionData = $ this ->_getOptionData ($ rowData , $ this ->_rowProductId , $ nextOptionId , $ this ->_rowType );
1279
1299
1280
1300
if (!$ this ->_isRowHasSpecificType (
1281
- $ this ->_rowType
1282
- ) && ($ priceData = $ this ->_getPriceData (
1283
- $ rowData ,
1284
- $ nextOptionId ,
1285
- $ this ->_rowType
1286
- ))
1301
+ $ this ->_rowType
1302
+ ) && ($ priceData = $ this ->_getPriceData (
1303
+ $ rowData ,
1304
+ $ nextOptionId ,
1305
+ $ this ->_rowType
1306
+ ))
1287
1307
) {
1288
1308
$ prices [$ nextOptionId ] = $ priceData ;
1289
1309
}
@@ -1416,6 +1436,107 @@ protected function _compareOptionsWithExisting(array &$options, array &$titles,
1416
1436
return $ this ;
1417
1437
}
1418
1438
1439
+ /**
1440
+ * Returns existing optionsTypes data for restoring original data
1441
+ *
1442
+ * @param array $typeValues
1443
+ * @param array $typeTitles
1444
+ * @return array
1445
+ */
1446
+ private function getRestoreOriginalOptionTypeIds (array $ typeValues , array $ typeTitles )
1447
+ {
1448
+ $ optionsForRestore = [];
1449
+ foreach ($ typeValues as $ optionId => $ optionTypes ) {
1450
+ foreach ($ optionTypes as $ optionTypeKey => $ optionType ) {
1451
+ $ optionTypeId = $ optionType ['option_type_id ' ];
1452
+ if (isset ($ typeTitles [$ optionTypeId ]) && is_array ($ typeTitles [$ optionTypeId ])) {
1453
+ foreach ($ typeTitles [$ optionTypeId ] as $ storeId => $ optionTypeTitle ) {
1454
+ $ existingTypeId = $ this ->getExistingOptionTypeId ($ optionId , $ storeId , $ optionTypeTitle );
1455
+ if ($ existingTypeId !== null ) {
1456
+ $ optionsForRestore [] = [
1457
+ 'searchKey ' => $ existingTypeId ,
1458
+ 'replaceKey ' => $ optionTypeId ,
1459
+ 'optionTypeKey ' => $ optionTypeKey ,
1460
+ 'optionId ' => $ optionId ,
1461
+ ];
1462
+ // If option type titles match at least in one store, consider current option type as existing
1463
+ break ;
1464
+ }
1465
+ }
1466
+ }
1467
+ }
1468
+ }
1469
+ return $ optionsForRestore ;
1470
+ }
1471
+
1472
+ /**
1473
+ * Returns restored array of typeValues
1474
+ *
1475
+ * @param array $typeValues
1476
+ * @param array $optionsForRestore
1477
+ * @return array
1478
+ */
1479
+ private function restoreTypeValues (array $ typeValues , array $ optionsForRestore )
1480
+ {
1481
+ foreach ($ optionsForRestore as $ restoreValues ) {
1482
+ if (isset ($ typeValues [$ restoreValues ['optionId ' ]][$ restoreValues ['optionTypeKey ' ]])) {
1483
+ $ typeValues [$ restoreValues ['optionId ' ]][$ restoreValues ['optionTypeKey ' ]]['option_type_id ' ] = $ restoreValues ['searchKey ' ];
1484
+ }
1485
+ }
1486
+ return $ typeValues ;
1487
+ }
1488
+
1489
+ /**
1490
+ * Restores optionTypes data
1491
+ *
1492
+ * @param array $optionDataArray
1493
+ * @param array $optionsForRestore
1494
+ * @return array
1495
+ */
1496
+ private function restoreOptionTypesData (array $ optionDataArray , array $ optionsForRestore )
1497
+ {
1498
+ foreach ($ optionsForRestore as $ restoreValues ) {
1499
+ $ replaceKey = $ restoreValues ['replaceKey ' ];
1500
+ $ searchKey = $ restoreValues ['searchKey ' ];
1501
+ if (isset ($ optionDataArray [$ replaceKey ])) {
1502
+ $ optionDataArray [$ searchKey ] = $ optionDataArray [$ replaceKey ];
1503
+ unset($ optionDataArray [$ replaceKey ]);
1504
+ }
1505
+ }
1506
+ return $ optionDataArray ;
1507
+ }
1508
+
1509
+ /**
1510
+ * Identify ID of the provided option type by its title in the specified store.
1511
+ *
1512
+ * @param int $optionId
1513
+ * @param int $storeId
1514
+ * @param string $optionTypeTitle
1515
+ * @return int|null
1516
+ */
1517
+ private function getExistingOptionTypeId ($ optionId , $ storeId , $ optionTypeTitle )
1518
+ {
1519
+ if (!isset ($ this ->optionTypeTitles [$ storeId ])) {
1520
+ /** @var ProductOptionValueCollection $optionTypeCollection */
1521
+ $ optionTypeCollection = $ this ->productOptionValueCollectionFactory ->create ();
1522
+ $ optionTypeCollection ->addTitleToResult ($ storeId );
1523
+ /** @var \Magento\Catalog\Model\Product\Option\Value $type */
1524
+ foreach ($ optionTypeCollection as $ type ) {
1525
+ $ this ->optionTypeTitles [$ storeId ][$ type ->getOptionId ()][$ type ->getId ()] = $ type ->getTitle ();
1526
+ }
1527
+ }
1528
+ if (isset ($ this ->optionTypeTitles [$ storeId ][$ optionId ])
1529
+ && is_array ($ this ->optionTypeTitles [$ storeId ][$ optionId ])
1530
+ ) {
1531
+ foreach ($ this ->optionTypeTitles [$ storeId ][$ optionId ] as $ optionTypeId => $ currentTypeTitle ) {
1532
+ if ($ optionTypeTitle === $ currentTypeTitle ) {
1533
+ return $ optionTypeId ;
1534
+ }
1535
+ }
1536
+ }
1537
+ return null ;
1538
+ }
1539
+
1419
1540
/**
1420
1541
* Parse required data from current row and store to class internal variables some data
1421
1542
* for underlying dependent rows
@@ -1547,13 +1668,13 @@ protected function _getOptionData(array $rowData, $productId, $optionId, $type)
1547
1668
protected function _getPriceData (array $ rowData , $ optionId , $ type )
1548
1669
{
1549
1670
if (in_array (
1550
- 'price ' ,
1551
- $ this ->_specificTypes [$ type ]
1552
- ) && isset (
1553
- $ rowData [self ::COLUMN_PREFIX . 'price ' ]
1554
- ) && strlen (
1555
- $ rowData [self ::COLUMN_PREFIX . 'price ' ]
1556
- ) > 0
1671
+ 'price ' ,
1672
+ $ this ->_specificTypes [$ type ]
1673
+ ) && isset (
1674
+ $ rowData [self ::COLUMN_PREFIX . 'price ' ]
1675
+ ) && strlen (
1676
+ $ rowData [self ::COLUMN_PREFIX . 'price ' ]
1677
+ ) > 0
1557
1678
) {
1558
1679
$ priceData = [
1559
1680
'option_id ' => $ optionId ,
@@ -1803,13 +1924,17 @@ protected function _updateProducts(array $data)
1803
1924
* @return array
1804
1925
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
1805
1926
*/
1806
- protected function _parseCustomOptions ($ rowData )
1927
+ protected function _parseCustomOptions ($ rowData )
1807
1928
{
1808
1929
$ beforeOptionValueSkuDelimiter = '; ' ;
1809
1930
if (empty ($ rowData ['custom_options ' ])) {
1810
1931
return $ rowData ;
1811
1932
}
1812
- $ rowData ['custom_options ' ] = str_replace ($ beforeOptionValueSkuDelimiter , $ this ->_productEntity ->getMultipleValueSeparator (), $ rowData ['custom_options ' ]);
1933
+ $ rowData ['custom_options ' ] = str_replace (
1934
+ $ beforeOptionValueSkuDelimiter ,
1935
+ $ this ->_productEntity ->getMultipleValueSeparator (),
1936
+ $ rowData ['custom_options ' ]
1937
+ );
1813
1938
$ options = [];
1814
1939
$ optionValues = explode (Product::PSEUDO_MULTI_LINE_SEPARATOR , $ rowData ['custom_options ' ]);
1815
1940
$ k = 0 ;
@@ -1821,7 +1946,7 @@ protected function _parseCustomOptions($rowData)
1821
1946
if (!empty ($ nameAndValue )) {
1822
1947
$ value = isset ($ nameAndValue [1 ]) ? $ nameAndValue [1 ] : '' ;
1823
1948
$ value = trim ($ value );
1824
- $ fieldName = trim ($ nameAndValue [0 ]);
1949
+ $ fieldName = trim ($ nameAndValue [0 ]);
1825
1950
if ($ value && ($ fieldName == 'name ' )) {
1826
1951
if ($ name != $ value ) {
1827
1952
$ name = $ value ;
0 commit comments