10
10
use Magento \Catalog \Api \Data \ProductAttributeInterface ;
11
11
use Magento \Catalog \Api \Data \ProductExtension ;
12
12
use Magento \Catalog \Api \Data \ProductInterface ;
13
+ use Magento \Catalog \Controller \Adminhtml \Product \Initialization \Helper \AttributeFilter ;
13
14
use Magento \Catalog \Model \Attribute \ScopeOverriddenValue ;
14
15
use Magento \Catalog \Model \Product \Gallery \MimeTypeExtensionMap ;
15
16
use Magento \Catalog \Model \ProductRepository \MediaGalleryProcessor ;
@@ -187,6 +188,11 @@ class ProductRepository implements \Magento\Catalog\Api\ProductRepositoryInterfa
187
188
*/
188
189
private $ scopeOverriddenValue ;
189
190
191
+ /**
192
+ * @var AttributeFilter
193
+ */
194
+ private $ attributeFilter ;
195
+
190
196
/**
191
197
* ProductRepository constructor.
192
198
* @param ProductFactory $productFactory
@@ -237,6 +243,7 @@ public function __construct(
237
243
MimeTypeExtensionMap $ mimeTypeExtensionMap ,
238
244
ImageProcessorInterface $ imageProcessor ,
239
245
\Magento \Framework \Api \ExtensionAttribute \JoinProcessorInterface $ extensionAttributesJoinProcessor ,
246
+ AttributeFilter $ attributeFilter = null ,
240
247
CollectionProcessorInterface $ collectionProcessor = null ,
241
248
\Magento \Framework \Serialize \Serializer \Json $ serializer = null ,
242
249
$ cacheLimit = 1000 ,
@@ -260,6 +267,8 @@ public function __construct(
260
267
$ this ->contentFactory = $ contentFactory ;
261
268
$ this ->imageProcessor = $ imageProcessor ;
262
269
$ this ->extensionAttributesJoinProcessor = $ extensionAttributesJoinProcessor ;
270
+ $ this ->attributeFilter = $ attributeFilter ?: \Magento \Framework \App \ObjectManager::getInstance ()
271
+ ->get (AttributeFilter::class);
263
272
$ this ->collectionProcessor = $ collectionProcessor ?: $ this ->getCollectionProcessor ();
264
273
$ this ->serializer = $ serializer ?: \Magento \Framework \App \ObjectManager::getInstance ()
265
274
->get (\Magento \Framework \Serialize \Serializer \Json::class);
@@ -597,38 +606,8 @@ public function save(ProductInterface $product, $saveOptions = false)
597
606
&& $ product ->getStoreId () !== Store::DEFAULT_STORE_ID
598
607
&& (count ($ stores ) > 1 || count ($ websites ) === 1 )
599
608
) {
600
- foreach ($ productAttributes as $ attribute ) {
601
- $ attributeCode = $ attribute ->getAttributeCode ();
602
- $ value = $ product ->getData ($ attributeCode );
603
- if ($ existingProduct ->getData ($ attributeCode ) === $ value
604
- && $ attribute ->getScope () !== EavAttributeInterface::SCOPE_GLOBAL_TEXT
605
- && !is_array ($ value )
606
- && !$ attribute ->isStatic ()
607
- && !array_key_exists ($ attributeCode , $ productDataToChange )
608
- && $ value !== null
609
- && !$ this ->scopeOverriddenValue ->containsValue (
610
- ProductInterface::class,
611
- $ product ,
612
- $ attributeCode ,
613
- $ product ->getStoreId ()
614
- )
615
- ) {
616
- $ product ->setData (
617
- $ attributeCode ,
618
- $ attributeCode === ProductAttributeInterface::CODE_SEO_FIELD_URL_KEY ? false : null
619
- );
620
- $ hasDataChanged = true ;
621
- }
622
- }
623
- $ storeScopedAttributes = [
624
- ProductAttributeInterface::CODE_SEO_FIELD_META_TITLE ,
625
- ProductAttributeInterface::CODE_SEO_FIELD_META_DESCRIPTION ,
626
- ProductAttributeInterface::CODE_SEO_FIELD_META_KEYWORD ,
627
- ];
628
- $ origDataAttributes = [
629
- ProductAttributeInterface::CODE_NAME ,
630
- ProductAttributeInterface::CODE_SEO_FIELD_URL_KEY ,
631
- ];
609
+
610
+ $ useDefault = [];
632
611
foreach ($ product ->getAttributes () as $ attribute ) {
633
612
$ defaultValue = $ attribute ->getDefaultValue ();
634
613
$ attributeCode = $ attribute ->getAttributeCode ();
@@ -644,29 +623,43 @@ public function save(ProductInterface $product, $saveOptions = false)
644
623
$ product ->getStoreId ()
645
624
)
646
625
) {
647
- $ product -> setData ( $ attributeCode) ;
626
+ $ useDefault [ $ attributeCode] = ' 1 ' ;
648
627
$ hasDataChanged = true ;
649
628
} elseif (!$ defaultValue && $ value !== null
650
- && $ attribute ->getScope () === EavAttributeInterface::SCOPE_STORE_TEXT
629
+ && $ attribute ->getScope () !== EavAttributeInterface::SCOPE_GLOBAL_TEXT
651
630
&& $ existingProduct ->getData ($ attributeCode ) === $ value
652
- && in_array ( $ attributeCode , $ storeScopedAttributes )
653
- ) {
654
- $ product-> setData ( $ attributeCode );
655
- $ hasDataChanged = true ;
656
- } elseif ( in_array ( $ attributeCode , $ origDataAttributes )
657
- && $ existingProduct -> getOrigData ( $ attributeCode ) === $ value
631
+ && ! $ this -> scopeOverriddenValue -> containsValue (
632
+ ProductInterface::class,
633
+ $ product,
634
+ $ attributeCode ,
635
+ $ product -> getStoreId ( )
636
+ )
658
637
) {
659
- $ product -> setData ( $ attributeCode) ;
638
+ $ useDefault [ $ attributeCode] = ' 1 ' ;
660
639
$ hasDataChanged = true ;
640
+ } else {
641
+ $ useDefault [$ attributeCode ] = '0 ' ;
661
642
}
643
+
662
644
}
663
645
if ($ hasDataChanged ) {
664
646
$ product ->setData ('_edit_mode ' , true );
665
647
}
666
648
}
667
649
}
650
+ $ productDataArray = $ this ->extensibleDataObjectConverter
651
+ ->toNestedArray ($ product , [], ProductInterface::class);
652
+ $ productDataArray = array_replace ($ productDataArray , $ product ->getData ());
653
+
654
+ $ productDataArray = $ this ->attributeFilter ->prepareProductAttributes (
655
+ $ product ,
656
+ $ productDataArray ,
657
+ $ useDefault
658
+ );
659
+ $ newProduct = $ this ->productFactory ->create ();
660
+ $ newProduct ->setData ($ productDataArray );
661
+ $ this ->saveProduct ($ newProduct );
668
662
669
- $ this ->saveProduct ($ product );
670
663
if ($ assignToCategories === true && $ product ->getCategoryIds ()) {
671
664
$ this ->linkManagement ->assignProductToCategories (
672
665
$ product ->getSku (),
0 commit comments