15
15
use Magento \Framework \Model \AbstractModel ;
16
16
use Magento \Framework \ObjectManager \ResetAfterRequestInterface ;
17
17
use Magento \Framework \Serialize \SerializerInterface ;
18
+ use Magento \Store \Model \StoreManagerInterface ;
18
19
19
20
/**
20
21
* EAV config model.
@@ -71,11 +72,8 @@ class Config implements ResetAfterRequestInterface
71
72
/**
72
73
* Initialized attributes
73
74
*
74
- * array ($entityTypeCode =>
75
- * ($attributeCode => $object)
76
- * )
77
- *
78
- * @var AbstractAttribute[][]
75
+ * [int $website][string $entityTypeCode][string $code] = AbstractAttribute $attribute
76
+ * @var array<int, array<string, array<string, AbstractAttribute>>>
79
77
*/
80
78
private $ attributes ;
81
79
@@ -123,6 +121,11 @@ class Config implements ResetAfterRequestInterface
123
121
*/
124
122
protected $ _universalFactory ;
125
123
124
+ /**
125
+ * @var StoreManagerInterface
126
+ */
127
+ protected $ _storeManager ;
128
+
126
129
/**
127
130
* @var AbstractAttribute[]
128
131
*/
@@ -159,6 +162,9 @@ class Config implements ResetAfterRequestInterface
159
162
*/
160
163
private $ attributesForPreload ;
161
164
165
+ /** @var bool[] */
166
+ private array $ isAttributeTypeWebsiteSpecificCache = [];
167
+
162
168
/**
163
169
* @param \Magento\Framework\App\CacheInterface $cache
164
170
* @param Entity\TypeFactory $entityTypeFactory
@@ -168,6 +174,7 @@ class Config implements ResetAfterRequestInterface
168
174
* @param SerializerInterface|null $serializer
169
175
* @param ScopeConfigInterface|null $scopeConfig
170
176
* @param array $attributesForPreload
177
+ * @param StoreManagerInterface|null $storeManager
171
178
* @codeCoverageIgnore
172
179
*/
173
180
public function __construct (
@@ -178,7 +185,8 @@ public function __construct(
178
185
\Magento \Framework \Validator \UniversalFactory $ universalFactory ,
179
186
SerializerInterface $ serializer = null ,
180
187
ScopeConfigInterface $ scopeConfig = null ,
181
- $ attributesForPreload = []
188
+ $ attributesForPreload = [],
189
+ ?StoreManagerInterface $ storeManager = null ,
182
190
) {
183
191
$ this ->_cache = $ cache ;
184
192
$ this ->_entityTypeFactory = $ entityTypeFactory ;
@@ -188,6 +196,7 @@ public function __construct(
188
196
$ this ->serializer = $ serializer ?: ObjectManager::getInstance ()->get (SerializerInterface::class);
189
197
$ this ->scopeConfig = $ scopeConfig ?: ObjectManager::getInstance ()->get (ScopeConfigInterface::class);
190
198
$ this ->attributesForPreload = $ attributesForPreload ;
199
+ $ this ->_storeManager = $ storeManager ?: ObjectManager::getInstance ()->get (StoreManagerInterface::class);
191
200
}
192
201
193
202
/**
@@ -243,7 +252,12 @@ protected function _load($id)
243
252
*/
244
253
private function loadAttributes ($ entityTypeCode )
245
254
{
246
- return $ this ->attributes [$ entityTypeCode ] ?? [];
255
+ if ($ this ->isAttributeTypeWebsiteSpecific ($ entityTypeCode )) {
256
+ $ websiteId = $ this ->getWebsiteId ();
257
+ } else {
258
+ $ websiteId = 0 ;
259
+ }
260
+ return $ this ->attributes [$ websiteId ][$ entityTypeCode ] ?? [];
247
261
}
248
262
249
263
/**
@@ -269,7 +283,12 @@ protected function _save($obj, $id)
269
283
*/
270
284
private function saveAttribute (AbstractAttribute $ attribute , $ entityTypeCode , $ attributeCode )
271
285
{
272
- $ this ->attributes [$ entityTypeCode ][$ attributeCode ] = $ attribute ;
286
+ if ($ this ->isAttributeTypeWebsiteSpecific ($ entityTypeCode )) {
287
+ $ websiteId = $ this ->getWebsiteId ();
288
+ } else {
289
+ $ websiteId = 0 ;
290
+ }
291
+ $ this ->attributes [$ websiteId ][$ entityTypeCode ][$ attributeCode ] = $ attribute ;
273
292
}
274
293
275
294
/**
@@ -476,7 +495,7 @@ protected function _initAttributes($entityType)
476
495
477
496
$ entityTypeCode = $ entityType ->getEntityTypeCode ();
478
497
$ attributes = $ this ->_universalFactory ->create ($ entityType ->getEntityAttributeCollection ());
479
- $ websiteId = $ attributes instanceof Collection ? $ this ->getWebsiteId ($ attributes ) : 0 ;
498
+ $ websiteId = $ attributes instanceof Collection ? $ this ->getWebsiteIdFromAttributeCollection ($ attributes ) : 0 ;
480
499
$ cacheKey = self ::ATTRIBUTES_CACHE_ID . '- ' . $ entityTypeCode . '- ' . $ websiteId ;
481
500
482
501
if ($ this ->isCacheEnabled () && $ this ->initAttributesFromCache ($ entityType , $ cacheKey )) {
@@ -537,6 +556,11 @@ public function getAttributes($entityType)
537
556
*/
538
557
public function getAttribute ($ entityType , $ code )
539
558
{
559
+ if ($ this ->isAttributeTypeWebsiteSpecific ($ entityType )) {
560
+ $ websiteId = $ this ->getWebsiteId ();
561
+ } else {
562
+ $ websiteId = 0 ;
563
+ }
540
564
if ($ code instanceof \Magento \Eav \Model \Entity \Attribute \AttributeInterface) {
541
565
return $ code ;
542
566
}
@@ -548,19 +572,19 @@ public function getAttribute($entityType, $code)
548
572
$ code = $ this ->_getAttributeReference ($ code , $ entityTypeCode ) ?: $ code ;
549
573
}
550
574
551
- if (isset ($ this ->attributes [$ entityTypeCode ][$ code ])) {
575
+ if (isset ($ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ])) {
552
576
\Magento \Framework \Profiler::stop ('EAV: ' . __METHOD__ );
553
- return $ this ->attributes [$ entityTypeCode ][$ code ];
577
+ return $ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ];
554
578
}
555
579
556
580
if (array_key_exists ($ entityTypeCode , $ this ->attributesForPreload )
557
581
&& array_key_exists ($ code , $ this ->attributesForPreload [$ entityTypeCode ])
558
582
) {
559
583
$ this ->initSystemAttributes ($ entityType , $ this ->attributesForPreload [$ entityTypeCode ]);
560
584
}
561
- if (isset ($ this ->attributes [$ entityTypeCode ][$ code ])) {
585
+ if (isset ($ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ])) {
562
586
\Magento \Framework \Profiler::stop ('EAV: ' . __METHOD__ );
563
- return $ this ->attributes [$ entityTypeCode ][$ code ];
587
+ return $ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ];
564
588
}
565
589
566
590
if ($ this ->scopeConfig ->getValue (self ::XML_PATH_CACHE_USER_DEFINED_ATTRIBUTES )) {
@@ -590,7 +614,8 @@ private function initSystemAttributes($entityType, $systemAttributes)
590
614
return ;
591
615
}
592
616
$ attributeCollection = $ this ->_universalFactory ->create ($ entityType ->getEntityAttributeCollection ());
593
- $ websiteId = $ attributeCollection instanceof Collection ? $ this ->getWebsiteId ($ attributeCollection ) : 0 ;
617
+ $ websiteId = $ attributeCollection instanceof Collection
618
+ ? $ this ->getWebsiteIdFromAttributeCollection ($ attributeCollection ) : 0 ;
594
619
$ cacheKey = self ::ATTRIBUTES_CACHE_ID . '- ' . $ entityTypeCode . '- ' . $ websiteId . '-preload ' ;
595
620
if ($ this ->isCacheEnabled () && ($ attributes = $ this ->_cache ->load ($ cacheKey ))) {
596
621
$ attributes = $ this ->serializer ->unserialize ($ attributes );
@@ -628,7 +653,7 @@ private function initSystemAttributes($entityType, $systemAttributes)
628
653
$ cacheKey ,
629
654
[
630
655
\Magento \Eav \Model \Cache \Type::CACHE_TAG ,
631
- \Magento \Eav \Model \Entity \Attribute::CACHE_TAG
656
+ \Magento \Eav \Model \Entity \Attribute::CACHE_TAG ,
632
657
]
633
658
);
634
659
}
@@ -904,7 +929,7 @@ public function importAttributesData($entityType, array $attributes)
904
929
/**
905
930
* Create attribute by attribute code
906
931
*
907
- * @param string $entityType
932
+ * @param string|Type $entityType
908
933
* @param string $attributeCode
909
934
* @return AbstractAttribute
910
935
* @throws LocalizedException
@@ -973,27 +998,66 @@ private function initAttributesFromCache(Type $entityType, string $cacheKey)
973
998
}
974
999
975
1000
/**
976
- * Returns website id.
1001
+ * Returns website id from attribute collection .
977
1002
*
978
1003
* @param Collection $attributeCollection
979
1004
* @return int
980
1005
*/
981
- private function getWebsiteId (Collection $ attributeCollection ): int
1006
+ private function getWebsiteIdFromAttributeCollection (Collection $ attributeCollection ): int
982
1007
{
983
- return $ attributeCollection ->getWebsite () ? (int )$ attributeCollection ->getWebsite ()->getId () : 0 ;
1008
+ return (int )$ attributeCollection ->getWebsite ()?->getId();
1009
+ }
1010
+
1011
+ /**
1012
+ * Return current website scope instance
1013
+ *
1014
+ * @return int website id
1015
+ */
1016
+ public function getWebsiteId () : int
1017
+ {
1018
+ $ websiteId = $ this ->_storeManager ->getStore ()?->getWebsiteId();
1019
+ return (int )$ websiteId ;
1020
+ }
1021
+
1022
+ /**
1023
+ * Returns true if $entityType has website-specific options.
1024
+ *
1025
+ * Most attributes are global, but some can have website-specific options.
1026
+ *
1027
+ * @param string|Type $entityType
1028
+ * @return bool
1029
+ */
1030
+ private function isAttributeTypeWebsiteSpecific (string |Type $ entityType ) : bool
1031
+ {
1032
+ if ($ entityType instanceof Type) {
1033
+ $ entityTypeCode = $ entityType ->getEntityTypeCode ();
1034
+ } else {
1035
+ $ entityTypeCode = $ entityType ;
1036
+ }
1037
+ if (key_exists ($ entityTypeCode , $ this ->isAttributeTypeWebsiteSpecificCache )) {
1038
+ return $ this ->isAttributeTypeWebsiteSpecificCache [$ entityTypeCode ];
1039
+ }
1040
+ $ entityType = $ this ->getEntityType ($ entityType );
1041
+ $ model = $ entityType ->getAttributeModel ();
1042
+ $ returnValue = is_a ($ model , \Magento \Eav \Model \Attribute::class, true );
1043
+ $ this ->isAttributeTypeWebsiteSpecificCache [$ entityTypeCode ] = $ returnValue ;
1044
+ return $ returnValue ;
984
1045
}
985
1046
986
1047
/**
987
1048
* @inheritDoc
988
1049
*/
989
1050
public function _resetState (): void
990
1051
{
1052
+ $ this ->isAttributeTypeWebsiteSpecificCache = [];
991
1053
$ this ->attributesPerSet = [];
992
1054
$ this ->_attributeData = null ;
993
- foreach ($ this ->attributes ?? [] as $ attributesGroupedByEntityTypeCode ) {
994
- foreach ($ attributesGroupedByEntityTypeCode as $ attribute ) {
995
- if ($ attribute instanceof ResetAfterRequestInterface) {
996
- $ attribute ->_resetState ();
1055
+ foreach ($ this ->attributes ?? [] as $ attributesGroupedByWebsites ) {
1056
+ foreach ($ attributesGroupedByWebsites ?? [] as $ attributesGroupedByEntityTypeCode ) {
1057
+ foreach ($ attributesGroupedByEntityTypeCode as $ attribute ) {
1058
+ if ($ attribute instanceof ResetAfterRequestInterface) {
1059
+ $ attribute ->_resetState ();
1060
+ }
997
1061
}
998
1062
}
999
1063
}
0 commit comments