6
6
namespace Magento \Catalog \Model \ResourceModel ;
7
7
8
8
use Magento \Catalog \Model \ResourceModel \Product \Website \Link as ProductWebsiteLink ;
9
+ use Magento \Eav \Api \AttributeManagementInterface ;
9
10
use Magento \Framework \App \ObjectManager ;
10
11
use Magento \Catalog \Model \Indexer \Category \Product \TableMaintainer ;
11
12
use Magento \Catalog \Model \Product as ProductEntity ;
12
13
use Magento \Eav \Model \Entity \Attribute \UniqueValidationInterface ;
14
+ use Magento \Framework \DataObject ;
13
15
use Magento \Framework \EntityManager \EntityManager ;
14
16
use Magento \Framework \Model \AbstractModel ;
15
17
@@ -93,6 +95,11 @@ class Product extends AbstractResource
93
95
*/
94
96
private $ tableMaintainer ;
95
97
98
+ /**
99
+ * @var AttributeManagementInterface
100
+ */
101
+ private $ eavAttributeManagement ;
102
+
96
103
/**
97
104
* @param \Magento\Eav\Model\Entity\Context $context
98
105
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -106,7 +113,7 @@ class Product extends AbstractResource
106
113
* @param array $data
107
114
* @param TableMaintainer|null $tableMaintainer
108
115
* @param UniqueValidationInterface|null $uniqueValidator
109
- *
116
+ * @param AttributeManagementInterface|null $eavAttributeManagement
110
117
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
111
118
*/
112
119
public function __construct (
@@ -121,7 +128,8 @@ public function __construct(
121
128
\Magento \Catalog \Model \Product \Attribute \DefaultAttributes $ defaultAttributes ,
122
129
$ data = [],
123
130
TableMaintainer $ tableMaintainer = null ,
124
- UniqueValidationInterface $ uniqueValidator = null
131
+ UniqueValidationInterface $ uniqueValidator = null ,
132
+ AttributeManagementInterface $ eavAttributeManagement = null
125
133
) {
126
134
$ this ->_categoryCollectionFactory = $ categoryCollectionFactory ;
127
135
$ this ->_catalogCategory = $ catalogCategory ;
@@ -138,6 +146,8 @@ public function __construct(
138
146
);
139
147
$ this ->connectionName = 'catalog ' ;
140
148
$ this ->tableMaintainer = $ tableMaintainer ?: ObjectManager::getInstance ()->get (TableMaintainer::class);
149
+ $ this ->eavAttributeManagement = $ eavAttributeManagement
150
+ ?? ObjectManager::getInstance ()->get (AttributeManagementInterface::class);
141
151
}
142
152
143
153
/**
@@ -268,10 +278,10 @@ public function getIdBySku($sku)
268
278
/**
269
279
* Process product data before save
270
280
*
271
- * @param \Magento\Framework\ DataObject $object
281
+ * @param DataObject $object
272
282
* @return $this
273
283
*/
274
- protected function _beforeSave (\ Magento \ Framework \ DataObject $ object )
284
+ protected function _beforeSave (DataObject $ object )
275
285
{
276
286
$ self = parent ::_beforeSave ($ object );
277
287
/**
@@ -286,15 +296,73 @@ protected function _beforeSave(\Magento\Framework\DataObject $object)
286
296
/**
287
297
* Save data related with product
288
298
*
289
- * @param \Magento\Framework\ DataObject $product
299
+ * @param DataObject $product
290
300
* @return $this
291
301
*/
292
- protected function _afterSave (\ Magento \ Framework \ DataObject $ product )
302
+ protected function _afterSave (DataObject $ product )
293
303
{
304
+ $ this ->removeNotInSetAttributeValues ($ product );
294
305
$ this ->_saveWebsiteIds ($ product )->_saveCategories ($ product );
295
306
return parent ::_afterSave ($ product );
296
307
}
297
308
309
+ /**
310
+ * Remove attribute values that absent in product attribute set
311
+ *
312
+ * @param DataObject $product
313
+ * @return DataObject
314
+ */
315
+ private function removeNotInSetAttributeValues (DataObject $ product ): DataObject
316
+ {
317
+ $ oldAttributeSetId = $ product ->getOrigData (ProductEntity::ATTRIBUTE_SET_ID );
318
+ if ($ oldAttributeSetId && $ product ->dataHasChangedFor (ProductEntity::ATTRIBUTE_SET_ID )) {
319
+ $ newAttributes = $ product ->getAttributes ();
320
+ $ newAttributesCodes = array_keys ($ newAttributes );
321
+ $ oldAttributes = $ this ->eavAttributeManagement ->getAttributes (
322
+ ProductEntity::ENTITY ,
323
+ $ oldAttributeSetId
324
+ );
325
+ $ oldAttributesCodes = [];
326
+ foreach ($ oldAttributes as $ oldAttribute ) {
327
+ $ oldAttributesCodes [] = $ oldAttribute ->getAttributecode ();
328
+ }
329
+ $ notInSetAttributeCodes = array_diff ($ oldAttributesCodes , $ newAttributesCodes );
330
+ if (!empty ($ notInSetAttributeCodes )) {
331
+ $ this ->deleteSelectedEntityAttributeRows ($ product , $ notInSetAttributeCodes );
332
+ }
333
+ }
334
+
335
+ return $ product ;
336
+ }
337
+
338
+ /**
339
+ * Clear selected entity attribute rows
340
+ *
341
+ * @param DataObject $product
342
+ * @param array $attributeCodes
343
+ * @return void
344
+ */
345
+ private function deleteSelectedEntityAttributeRows (DataObject $ product , array $ attributeCodes ): void
346
+ {
347
+ $ backendTables = [];
348
+ foreach ($ attributeCodes as $ attributeCode ) {
349
+ $ attribute = $ this ->getAttribute ($ attributeCode );
350
+ $ backendTable = $ attribute ->getBackendTable ();
351
+ if (!$ attribute ->isStatic () && $ backendTable ) {
352
+ $ backendTables [$ backendTable ][] = $ attribute ->getId ();
353
+ }
354
+ }
355
+
356
+ $ entityIdField = $ this ->getLinkField ();
357
+ $ entityId = $ product ->getData ($ entityIdField );
358
+ foreach ($ backendTables as $ backendTable => $ attributes ) {
359
+ $ connection = $ this ->getConnection ();
360
+ $ where = $ connection ->quoteInto ('attribute_id IN (?) ' , $ attributes );
361
+ $ where .= $ connection ->quoteInto (" AND {$ entityIdField } = ? " , $ entityId );
362
+ $ connection ->delete ($ backendTable , $ where );
363
+ }
364
+ }
365
+
298
366
/**
299
367
* @inheritdoc
300
368
*/
@@ -337,12 +405,12 @@ protected function _saveWebsiteIds($product)
337
405
/**
338
406
* Save product category relations
339
407
*
340
- * @param \Magento\Framework\ DataObject $object
408
+ * @param DataObject $object
341
409
* @return $this
342
410
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
343
411
* @deprecated 101.1.0
344
412
*/
345
- protected function _saveCategories (\ Magento \ Framework \ DataObject $ object )
413
+ protected function _saveCategories (DataObject $ object )
346
414
{
347
415
return $ this ;
348
416
}
0 commit comments