Skip to content

Commit 39d60f3

Browse files
author
Oleksii Korshenko
authored
MAGETWO-85772: #12699: Multiselect Attribute is not saved #12767
2 parents db12206 + 8b027c8 commit 39d60f3

File tree

6 files changed

+116
-56
lines changed

6 files changed

+116
-56
lines changed

app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/AbstractTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ public function testWalkAttributes()
4444

4545
$code = 'test_attr';
4646
$set = 10;
47+
$storeId = 100;
4748

4849
$object = $this->createPartialMock(\Magento\Catalog\Model\Product::class, ['__wakeup']);
4950

5051
$object->setData('test_attr', 'test_attr');
5152
$object->setData('attribute_set_id', $set);
53+
$object->setData('store_id', $storeId);
5254

5355
$entityType = new \Magento\Framework\DataObject();
5456
$entityType->setEntityTypeCode('test');

app/code/Magento/Eav/Model/Entity/AbstractEntity.php

Lines changed: 92 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use Magento\Eav\Model\Entity\Attribute\Frontend\AbstractFrontend;
1414
use Magento\Eav\Model\Entity\Attribute\Source\AbstractSource;
1515
use Magento\Framework\App\Config\Element;
16+
use Magento\Framework\DataObject;
1617
use Magento\Framework\DB\Adapter\DuplicateException;
1718
use Magento\Framework\Exception\AlreadyExistsException;
1819
use Magento\Framework\Exception\LocalizedException;
@@ -62,6 +63,13 @@ abstract class AbstractEntity extends AbstractResource implements EntityInterfac
6263
*/
6364
protected $_attributesByCode = [];
6465

66+
/**
67+
* Attributes stored by scope (store id and attribute set id).
68+
*
69+
* @var array
70+
*/
71+
private $attributesByScope = [];
72+
6573
/**
6674
* Two-dimensional array by table name and attribute name
6775
*
@@ -473,6 +481,46 @@ public function addAttribute(AbstractAttribute $attribute)
473481
return $this;
474482
}
475483

484+
/**
485+
* Adding attribute to entity by scope.
486+
*
487+
* @param AbstractAttribute $attribute
488+
* @param DataObject|null $entity
489+
* @return $this
490+
*/
491+
public function addAttributeByScope(AbstractAttribute $attribute, $entity = null)
492+
{
493+
$suffix = $entity !== null ? $this->getAttributesCacheSuffix($entity) : '0-0';
494+
$attributeCode = $attribute->getAttributeCode();
495+
$this->attributesByScope[$suffix][$attributeCode] = $attribute;
496+
return $this->addAttribute($attribute);
497+
}
498+
499+
/**
500+
* Get attributes by scope
501+
*
502+
* @return array
503+
*/
504+
private function getAttributesByScope($suffix)
505+
{
506+
return !empty($this->attributesByScope[$suffix])
507+
? $this->attributesByScope[$suffix]
508+
: $this->getAttributesByCode();
509+
}
510+
511+
/**
512+
* Get attributes cache suffix.
513+
*
514+
* @param DataObject $object
515+
* @return string
516+
*/
517+
private function getAttributesCacheSuffix(DataObject $object)
518+
{
519+
$attributeSetId = $object->getAttributeSetId() ?: 0;
520+
$storeId = $object->getStoreId() ?: 0;
521+
return $storeId . '-' . $attributeSetId;
522+
}
523+
476524
/**
477525
* Retrieve partial load flag
478526
*
@@ -506,7 +554,7 @@ public function isPartialSave($flag = null)
506554
/**
507555
* Retrieve configuration for all attributes
508556
*
509-
* @param null|\Magento\Framework\DataObject $object
557+
* @param null|DataObject $object
510558
* @return $this
511559
*/
512560
public function loadAllAttributes($object = null)
@@ -566,7 +614,7 @@ public function attributesCompare($firstAttribute, $secondAttribute)
566614
/**
567615
* Check whether the attribute is Applicable to the object
568616
*
569-
* @param \Magento\Framework\DataObject $object
617+
* @param DataObject $object
570618
* @param AbstractAttribute $attribute
571619
* @return bool
572620
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
@@ -611,7 +659,8 @@ public function walkAttributes($partMethod, array $args = [], $collectExceptionM
611659
break;
612660
}
613661
$results = [];
614-
foreach ($this->getAttributesByCode() as $attrCode => $attribute) {
662+
$suffix = $this->getAttributesCacheSuffix($args[0]);
663+
foreach ($this->getAttributesByScope($suffix) as $attrCode => $attribute) {
615664
if (isset($args[0]) && is_object($args[0]) && !$this->_isApplicableAttribute($args[0], $attribute)) {
616665
continue;
617666
}
@@ -830,7 +879,7 @@ public function isAttributeStatic($attribute)
830879
/**
831880
* Validate all object's attributes against configuration
832881
*
833-
* @param \Magento\Framework\DataObject $object
882+
* @param DataObject $object
834883
* @throws \Magento\Eav\Model\Entity\Attribute\Exception
835884
* @return true|array
836885
*/
@@ -856,10 +905,10 @@ public function validate($object)
856905
/**
857906
* Set new increment id to object
858907
*
859-
* @param \Magento\Framework\DataObject $object
908+
* @param DataObject $object
860909
* @return $this
861910
*/
862-
public function setNewIncrementId(\Magento\Framework\DataObject $object)
911+
public function setNewIncrementId(DataObject $object)
863912
{
864913
if ($object->getIncrementId()) {
865914
return $this;
@@ -878,7 +927,7 @@ public function setNewIncrementId(\Magento\Framework\DataObject $object)
878927
* Check attribute unique value
879928
*
880929
* @param AbstractAttribute $attribute
881-
* @param \Magento\Framework\DataObject $object
930+
* @param DataObject $object
882931
* @return bool
883932
*/
884933
public function checkAttributeUniqueValue(AbstractAttribute $attribute, $object)
@@ -1051,7 +1100,7 @@ protected function _prepareLoadSelect(array $selects)
10511100
/**
10521101
* Retrieve select object for loading base entity row
10531102
*
1054-
* @param \Magento\Framework\DataObject $object
1103+
* @param DataObject $object
10551104
* @param string|int $rowId
10561105
* @return \Magento\Framework\DB\Select
10571106
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
@@ -1071,7 +1120,7 @@ protected function _getLoadRowSelect($object, $rowId)
10711120
/**
10721121
* Retrieve select object for loading entity attributes values
10731122
*
1074-
* @param \Magento\Framework\DataObject $object
1123+
* @param DataObject $object
10751124
* @param string $table
10761125
* @return \Magento\Framework\DB\Select
10771126
*/
@@ -1091,7 +1140,7 @@ protected function _getLoadAttributesSelect($object, $table)
10911140
/**
10921141
* Initialize attribute value for object
10931142
*
1094-
* @param \Magento\Framework\DataObject $object
1143+
* @param DataObject $object
10951144
* @param array $valueRow
10961145
* @return $this
10971146
*/
@@ -1181,8 +1230,8 @@ protected function processSave($object)
11811230
/**
11821231
* Retrieve Object instance with original data
11831232
*
1184-
* @param \Magento\Framework\DataObject $object
1185-
* @return \Magento\Framework\DataObject
1233+
* @param DataObject $object
1234+
* @return DataObject
11861235
*/
11871236
protected function _getOrigObject($object)
11881237
{
@@ -1422,7 +1471,7 @@ protected function _processSaveData($saveData)
14221471
/**
14231472
* Process base row
14241473
*/
1425-
$entityObject = new \Magento\Framework\DataObject($entityRow);
1474+
$entityObject = new DataObject($entityRow);
14261475
$entityRow = $this->_prepareDataForTable($entityObject, $entityTable);
14271476
if ($insertEntity) {
14281477
if (!empty($entityId)) {
@@ -1477,7 +1526,7 @@ protected function _processSaveData($saveData)
14771526
/**
14781527
* Insert entity attribute value
14791528
*
1480-
* @param \Magento\Framework\DataObject $object
1529+
* @param DataObject $object
14811530
* @param AbstractAttribute $attribute
14821531
* @param mixed $value
14831532
* @return $this
@@ -1490,7 +1539,7 @@ protected function _insertAttribute($object, $attribute, $value)
14901539
/**
14911540
* Update entity attribute value
14921541
*
1493-
* @param \Magento\Framework\DataObject $object
1542+
* @param DataObject $object
14941543
* @param AbstractAttribute $attribute
14951544
* @param mixed $valueId
14961545
* @param mixed $value
@@ -1585,10 +1634,10 @@ protected function _prepareValueForSave($value, AbstractAttribute $attribute)
15851634
/**
15861635
* Delete entity attribute values
15871636
*
1588-
* @param \Magento\Framework\DataObject $object
1637+
* @param DataObject $object
15891638
* @param string $table
15901639
* @param array $info
1591-
* @return \Magento\Framework\DataObject
1640+
* @return DataObject
15921641
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
15931642
*/
15941643
protected function _deleteAttributes($object, $table, $info)
@@ -1614,13 +1663,13 @@ protected function _deleteAttributes($object, $table, $info)
16141663
/**
16151664
* Save attribute
16161665
*
1617-
* @param \Magento\Framework\DataObject $object
1666+
* @param DataObject $object
16181667
* @param string $attributeCode
16191668
* @return $this
16201669
* @throws \Exception
16211670
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
16221671
*/
1623-
public function saveAttribute(\Magento\Framework\DataObject $object, $attributeCode)
1672+
public function saveAttribute(DataObject $object, $attributeCode)
16241673
{
16251674
$attribute = $this->getAttribute($attributeCode);
16261675
$backend = $attribute->getBackend();
@@ -1666,8 +1715,8 @@ public function saveAttribute(\Magento\Framework\DataObject $object, $attributeC
16661715
/**
16671716
* Return attribute row to prepare where statement
16681717
*
1669-
* @param \Magento\Framework\DataObject $entity
1670-
* @param \Magento\Framework\DataObject $object
1718+
* @param DataObject $entity
1719+
* @param DataObject $object
16711720
* @param \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attribute
16721721
* @return array
16731722
*/
@@ -1688,7 +1737,7 @@ protected function getAttributeRow($entity, $object, $attribute)
16881737
/**
16891738
* Delete entity using current object's data
16901739
*
1691-
* @param \Magento\Framework\DataObject|int|string $object
1740+
* @param DataObject|int|string $object
16921741
* @return $this
16931742
* @throws \Exception
16941743
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
@@ -1730,7 +1779,7 @@ public function delete($object)
17301779
/**
17311780
* Evaluate Delete operations
17321781
*
1733-
* @param \Magento\Framework\DataObject|int|string $object
1782+
* @param DataObject|int|string $object
17341783
* @param string|int $id
17351784
* @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
17361785
* @return void
@@ -1764,10 +1813,10 @@ protected function evaluateDelete($object, $id, $connection)
17641813
/**
17651814
* After Load Entity process
17661815
*
1767-
* @param \Magento\Framework\DataObject $object
1816+
* @param DataObject $object
17681817
* @return $this
17691818
*/
1770-
protected function _afterLoad(\Magento\Framework\DataObject $object)
1819+
protected function _afterLoad(DataObject $object)
17711820
{
17721821
\Magento\Framework\Profiler::start('after_load');
17731822
$this->walkAttributes('backend/afterLoad', [$object]);
@@ -1778,10 +1827,10 @@ protected function _afterLoad(\Magento\Framework\DataObject $object)
17781827
/**
17791828
* Before delete Entity process
17801829
*
1781-
* @param \Magento\Framework\DataObject $object
1830+
* @param DataObject $object
17821831
* @return $this
17831832
*/
1784-
protected function _beforeSave(\Magento\Framework\DataObject $object)
1833+
protected function _beforeSave(DataObject $object)
17851834
{
17861835
$this->walkAttributes('backend/beforeSave', [$object]);
17871836
return $this;
@@ -1790,10 +1839,10 @@ protected function _beforeSave(\Magento\Framework\DataObject $object)
17901839
/**
17911840
* After Save Entity process
17921841
*
1793-
* @param \Magento\Framework\DataObject $object
1842+
* @param DataObject $object
17941843
* @return $this
17951844
*/
1796-
protected function _afterSave(\Magento\Framework\DataObject $object)
1845+
protected function _afterSave(DataObject $object)
17971846
{
17981847
$this->walkAttributes('backend/afterSave', [$object]);
17991848
return $this;
@@ -1802,10 +1851,10 @@ protected function _afterSave(\Magento\Framework\DataObject $object)
18021851
/**
18031852
* Before Delete Entity process
18041853
*
1805-
* @param \Magento\Framework\DataObject $object
1854+
* @param DataObject $object
18061855
* @return $this
18071856
*/
1808-
protected function _beforeDelete(\Magento\Framework\DataObject $object)
1857+
protected function _beforeDelete(DataObject $object)
18091858
{
18101859
$this->walkAttributes('backend/beforeDelete', [$object]);
18111860
return $this;
@@ -1814,10 +1863,10 @@ protected function _beforeDelete(\Magento\Framework\DataObject $object)
18141863
/**
18151864
* After delete entity process
18161865
*
1817-
* @param \Magento\Framework\DataObject $object
1866+
* @param DataObject $object
18181867
* @return $this
18191868
*/
1820-
protected function _afterDelete(\Magento\Framework\DataObject $object)
1869+
protected function _afterDelete(DataObject $object)
18211870
{
18221871
$this->walkAttributes('backend/afterDelete', [$object]);
18231872
return $this;
@@ -1887,54 +1936,54 @@ protected function getAttributeLoader()
18871936
/**
18881937
* Perform actions after entity load
18891938
*
1890-
* @param \Magento\Framework\DataObject $object
1939+
* @param DataObject $object
18911940
* @since 100.1.0
18921941
*/
1893-
public function afterLoad(\Magento\Framework\DataObject $object)
1942+
public function afterLoad(DataObject $object)
18941943
{
18951944
$this->_afterLoad($object);
18961945
}
18971946

18981947
/**
18991948
* Perform actions before entity save
19001949
*
1901-
* @param \Magento\Framework\DataObject $object
1950+
* @param DataObject $object
19021951
* @since 100.1.0
19031952
*/
1904-
public function beforeSave(\Magento\Framework\DataObject $object)
1953+
public function beforeSave(DataObject $object)
19051954
{
19061955
$this->_beforeSave($object);
19071956
}
19081957

19091958
/**
19101959
* Perform actions after entity save
19111960
*
1912-
* @param \Magento\Framework\DataObject $object
1961+
* @param DataObject $object
19131962
* @since 100.1.0
19141963
*/
1915-
public function afterSave(\Magento\Framework\DataObject $object)
1964+
public function afterSave(DataObject $object)
19161965
{
19171966
$this->_afterSave($object);
19181967
}
19191968

19201969
/**
19211970
* Perform actions before entity delete
19221971
*
1923-
* @param \Magento\Framework\DataObject $object
1972+
* @param DataObject $object
19241973
* @since 100.1.0
19251974
*/
1926-
public function beforeDelete(\Magento\Framework\DataObject $object)
1975+
public function beforeDelete(DataObject $object)
19271976
{
19281977
$this->_beforeDelete($object);
19291978
}
19301979

19311980
/**
19321981
* Perform actions after entity delete
19331982
*
1934-
* @param \Magento\Framework\DataObject $object
1983+
* @param DataObject $object
19351984
* @since 100.1.0
19361985
*/
1937-
public function afterDelete(\Magento\Framework\DataObject $object)
1986+
public function afterDelete(DataObject $object)
19381987
{
19391988
$this->_afterDelete($object);
19401989
}

0 commit comments

Comments
 (0)