1515use Magento \Framework \Model \AbstractModel ;
1616use Magento \Framework \ObjectManager \ResetAfterRequestInterface ;
1717use Magento \Framework \Serialize \SerializerInterface ;
18+ use Magento \Store \Model \StoreManagerInterface ;
1819
1920/**
2021 * EAV config model.
@@ -71,11 +72,8 @@ class Config implements ResetAfterRequestInterface
7172 /**
7273 * Initialized attributes
7374 *
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>>>
7977 */
8078 private $ attributes ;
8179
@@ -123,6 +121,11 @@ class Config implements ResetAfterRequestInterface
123121 */
124122 protected $ _universalFactory ;
125123
124+ /**
125+ * @var StoreManagerInterface
126+ */
127+ protected $ _storeManager ;
128+
126129 /**
127130 * @var AbstractAttribute[]
128131 */
@@ -159,6 +162,9 @@ class Config implements ResetAfterRequestInterface
159162 */
160163 private $ attributesForPreload ;
161164
165+ /** @var bool[] */
166+ private array $ isAttributeTypeWebsiteSpecificCache = [];
167+
162168 /**
163169 * @param \Magento\Framework\App\CacheInterface $cache
164170 * @param Entity\TypeFactory $entityTypeFactory
@@ -168,6 +174,7 @@ class Config implements ResetAfterRequestInterface
168174 * @param SerializerInterface|null $serializer
169175 * @param ScopeConfigInterface|null $scopeConfig
170176 * @param array $attributesForPreload
177+ * @param StoreManagerInterface|null $storeManager
171178 * @codeCoverageIgnore
172179 */
173180 public function __construct (
@@ -178,7 +185,8 @@ public function __construct(
178185 \Magento \Framework \Validator \UniversalFactory $ universalFactory ,
179186 SerializerInterface $ serializer = null ,
180187 ScopeConfigInterface $ scopeConfig = null ,
181- $ attributesForPreload = []
188+ $ attributesForPreload = [],
189+ ?StoreManagerInterface $ storeManager = null ,
182190 ) {
183191 $ this ->_cache = $ cache ;
184192 $ this ->_entityTypeFactory = $ entityTypeFactory ;
@@ -188,6 +196,7 @@ public function __construct(
188196 $ this ->serializer = $ serializer ?: ObjectManager::getInstance ()->get (SerializerInterface::class);
189197 $ this ->scopeConfig = $ scopeConfig ?: ObjectManager::getInstance ()->get (ScopeConfigInterface::class);
190198 $ this ->attributesForPreload = $ attributesForPreload ;
199+ $ this ->_storeManager = $ storeManager ?: ObjectManager::getInstance ()->get (StoreManagerInterface::class);
191200 }
192201
193202 /**
@@ -243,7 +252,12 @@ protected function _load($id)
243252 */
244253 private function loadAttributes ($ entityTypeCode )
245254 {
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 ] ?? [];
247261 }
248262
249263 /**
@@ -269,7 +283,12 @@ protected function _save($obj, $id)
269283 */
270284 private function saveAttribute (AbstractAttribute $ attribute , $ entityTypeCode , $ attributeCode )
271285 {
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 ;
273292 }
274293
275294 /**
@@ -476,7 +495,7 @@ protected function _initAttributes($entityType)
476495
477496 $ entityTypeCode = $ entityType ->getEntityTypeCode ();
478497 $ attributes = $ this ->_universalFactory ->create ($ entityType ->getEntityAttributeCollection ());
479- $ websiteId = $ attributes instanceof Collection ? $ this ->getWebsiteId ($ attributes ) : 0 ;
498+ $ websiteId = $ attributes instanceof Collection ? $ this ->getWebsiteIdFromAttributeCollection ($ attributes ) : 0 ;
480499 $ cacheKey = self ::ATTRIBUTES_CACHE_ID . '- ' . $ entityTypeCode . '- ' . $ websiteId ;
481500
482501 if ($ this ->isCacheEnabled () && $ this ->initAttributesFromCache ($ entityType , $ cacheKey )) {
@@ -537,6 +556,11 @@ public function getAttributes($entityType)
537556 */
538557 public function getAttribute ($ entityType , $ code )
539558 {
559+ if ($ this ->isAttributeTypeWebsiteSpecific ($ entityType )) {
560+ $ websiteId = $ this ->getWebsiteId ();
561+ } else {
562+ $ websiteId = 0 ;
563+ }
540564 if ($ code instanceof \Magento \Eav \Model \Entity \Attribute \AttributeInterface) {
541565 return $ code ;
542566 }
@@ -548,19 +572,19 @@ public function getAttribute($entityType, $code)
548572 $ code = $ this ->_getAttributeReference ($ code , $ entityTypeCode ) ?: $ code ;
549573 }
550574
551- if (isset ($ this ->attributes [$ entityTypeCode ][$ code ])) {
575+ if (isset ($ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ])) {
552576 \Magento \Framework \Profiler::stop ('EAV: ' . __METHOD__ );
553- return $ this ->attributes [$ entityTypeCode ][$ code ];
577+ return $ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ];
554578 }
555579
556580 if (array_key_exists ($ entityTypeCode , $ this ->attributesForPreload )
557581 && array_key_exists ($ code , $ this ->attributesForPreload [$ entityTypeCode ])
558582 ) {
559583 $ this ->initSystemAttributes ($ entityType , $ this ->attributesForPreload [$ entityTypeCode ]);
560584 }
561- if (isset ($ this ->attributes [$ entityTypeCode ][$ code ])) {
585+ if (isset ($ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ])) {
562586 \Magento \Framework \Profiler::stop ('EAV: ' . __METHOD__ );
563- return $ this ->attributes [$ entityTypeCode ][$ code ];
587+ return $ this ->attributes [$ websiteId ][ $ entityTypeCode ][$ code ];
564588 }
565589
566590 if ($ this ->scopeConfig ->getValue (self ::XML_PATH_CACHE_USER_DEFINED_ATTRIBUTES )) {
@@ -590,7 +614,8 @@ private function initSystemAttributes($entityType, $systemAttributes)
590614 return ;
591615 }
592616 $ 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 ;
594619 $ cacheKey = self ::ATTRIBUTES_CACHE_ID . '- ' . $ entityTypeCode . '- ' . $ websiteId . '-preload ' ;
595620 if ($ this ->isCacheEnabled () && ($ attributes = $ this ->_cache ->load ($ cacheKey ))) {
596621 $ attributes = $ this ->serializer ->unserialize ($ attributes );
@@ -628,7 +653,7 @@ private function initSystemAttributes($entityType, $systemAttributes)
628653 $ cacheKey ,
629654 [
630655 \Magento \Eav \Model \Cache \Type::CACHE_TAG ,
631- \Magento \Eav \Model \Entity \Attribute::CACHE_TAG
656+ \Magento \Eav \Model \Entity \Attribute::CACHE_TAG ,
632657 ]
633658 );
634659 }
@@ -904,7 +929,7 @@ public function importAttributesData($entityType, array $attributes)
904929 /**
905930 * Create attribute by attribute code
906931 *
907- * @param string $entityType
932+ * @param string|Type $entityType
908933 * @param string $attributeCode
909934 * @return AbstractAttribute
910935 * @throws LocalizedException
@@ -973,27 +998,66 @@ private function initAttributesFromCache(Type $entityType, string $cacheKey)
973998 }
974999
9751000 /**
976- * Returns website id.
1001+ * Returns website id from attribute collection .
9771002 *
9781003 * @param Collection $attributeCollection
9791004 * @return int
9801005 */
981- private function getWebsiteId (Collection $ attributeCollection ): int
1006+ private function getWebsiteIdFromAttributeCollection (Collection $ attributeCollection ): int
9821007 {
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 ;
9841045 }
9851046
9861047 /**
9871048 * @inheritDoc
9881049 */
9891050 public function _resetState (): void
9901051 {
1052+ $ this ->isAttributeTypeWebsiteSpecificCache = [];
9911053 $ this ->attributesPerSet = [];
9921054 $ 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+ }
9971061 }
9981062 }
9991063 }
0 commit comments