55 */
66namespace Magento \CatalogImportExport \Model \Import \Product \Type ;
77
8- use Magento \Framework \ App \ ResourceConnection ;
8+ use Magento \Catalog \ Model \ ResourceModel \ Eav \ Attribute ;
99use Magento \CatalogImportExport \Model \Import \Product \RowValidatorInterface ;
10- use Magento \CatalogImportExport \Model \Import \Product ;
10+ use Magento \Eav \Model \Entity \Attribute \Source \Table ;
11+ use Magento \Eav \Model \ResourceModel \Entity \Attribute \Option \CollectionFactory as AttributeOptionCollectionFactory ;
12+ use Magento \Framework \App \ObjectManager ;
13+ use Magento \Framework \App \ResourceConnection ;
1114use Magento \Framework \EntityManager \MetadataPool ;
1215
1316/**
@@ -151,6 +154,11 @@ abstract class AbstractType
151154 */
152155 private $ productEntityLinkField ;
153156
157+ /**
158+ * @var AttributeOptionCollectionFactory
159+ */
160+ private $ attributeOptionCollectionFactory ;
161+
154162 /**
155163 * AbstractType constructor
156164 *
@@ -159,20 +167,24 @@ abstract class AbstractType
159167 * @param ResourceConnection $resource
160168 * @param array $params
161169 * @param MetadataPool|null $metadataPool
170+ * @param AttributeOptionCollectionFactory|null $attributeOptionCollectionFactory
162171 * @throws \Magento\Framework\Exception\LocalizedException
163172 */
164173 public function __construct (
165174 \Magento \Eav \Model \ResourceModel \Entity \Attribute \Set \CollectionFactory $ attrSetColFac ,
166175 \Magento \Catalog \Model \ResourceModel \Product \Attribute \CollectionFactory $ prodAttrColFac ,
167176 \Magento \Framework \App \ResourceConnection $ resource ,
168177 array $ params ,
169- MetadataPool $ metadataPool = null
178+ MetadataPool $ metadataPool = null ,
179+ AttributeOptionCollectionFactory $ attributeOptionCollectionFactory = null
170180 ) {
171181 $ this ->_attrSetColFac = $ attrSetColFac ;
172182 $ this ->_prodAttrColFac = $ prodAttrColFac ;
173183 $ this ->_resource = $ resource ;
174184 $ this ->connection = $ resource ->getConnection ();
175185 $ this ->metadataPool = $ metadataPool ?: $ this ->getMetadataPool ();
186+ $ this ->attributeOptionCollectionFactory = $ attributeOptionCollectionFactory
187+ ?: ObjectManager::getInstance ()->get (AttributeOptionCollectionFactory::class);
176188 if ($ this ->isSuitable ()) {
177189 if (!isset ($ params [0 ])
178190 || !isset ($ params [1 ])
@@ -183,11 +195,9 @@ public function __construct(
183195 }
184196 $ this ->_entityModel = $ params [0 ];
185197 $ this ->_type = $ params [1 ];
186-
187198 $ this ->initMessageTemplates (
188199 array_merge ($ this ->_genericMessageTemplates , $ this ->_messageTemplates )
189200 );
190-
191201 $ this ->_initAttributes ();
192202 }
193203 }
@@ -257,6 +267,10 @@ protected function _getProductAttributes($attrSetData)
257267 /**
258268 * Initialize attributes parameters for all attributes' sets.
259269 *
270+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
271+ * @SuppressWarnings(PHPMD.NPathComplexity)
272+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
273+ *
260274 * @return $this
261275 */
262276 protected function _initAttributes ()
@@ -284,80 +298,168 @@ protected function _initAttributes()
284298 $ absentKeys [$ attributeRow ['attribute_set_name ' ]][] = $ attributeRow ['attribute_id ' ];
285299 }
286300 }
287- foreach ($ absentKeys as $ attributeSetName => $ attributeIds ) {
301+ $ addedAttributes = [];
302+ foreach ($ absentKeys as $ attributeIds ) {
288303 $ unknownAttributeIds = array_diff (
289304 $ attributeIds ,
290305 array_keys (self ::$ commonAttributesCache ),
291306 self ::$ invAttributesCache
292307 );
293- if ($ unknownAttributeIds || $ this ->_forcedAttributesCodes ) {
294- $ this ->attachAttributesById ($ attributeSetName , $ attributeIds );
308+ if ($ unknownAttributeIds ) {
309+ $ addedAttributes [] = $ this ->attachAttributesByOnlyId ($ unknownAttributeIds );
310+ }
311+ }
312+ if ($ this ->_forcedAttributesCodes ) {
313+ $ addedAttributes [] = $ this ->attachAttributesByForcedCodes ();
314+ }
315+ $ addedAttributes = array_merge (...$ addedAttributes );
316+ $ attributesToLoadFromTable = [];
317+ foreach ($ addedAttributes as $ addedAttribute ) {
318+ if (isset ($ addedAttribute ['options_use_table ' ])) {
319+ $ attributesToLoadFromTable [] = $ addedAttribute ['id ' ];
320+ unset(self ::$ commonAttributesCache [$ addedAttribute ['id ' ]]['options_use_table ' ]);
321+ }
322+ }
323+ foreach (array_chunk ($ attributesToLoadFromTable , 1000 ) as $ attributesToLoadFromTableChunk ) {
324+ $ collection = $ this ->attributeOptionCollectionFactory ->create ();
325+ $ collection ->setAttributeFilter (['in ' => $ attributesToLoadFromTableChunk ]);
326+ $ collection ->setStoreFilter (\Magento \Store \Model \Store::DEFAULT_STORE_ID );
327+ foreach ($ collection as $ option ) {
328+ $ attributeId = $ option ->getAttributeId ();
329+ $ value = strtolower ($ option ->getValue ());
330+ self ::$ commonAttributesCache [$ attributeId ]['options ' ][$ value ] = $ option ->getOptionId ();
295331 }
296332 }
297333 foreach ($ entityAttributes as $ attributeRow ) {
298334 if (isset (self ::$ commonAttributesCache [$ attributeRow ['attribute_id ' ]])) {
299335 $ attribute = self ::$ commonAttributesCache [$ attributeRow ['attribute_id ' ]];
300- $ this ->_addAttributeParams (
301- $ attributeRow ['attribute_set_name ' ],
302- self ::$ commonAttributesCache [$ attributeRow ['attribute_id ' ]],
303- $ attribute
304- );
336+ $ this ->_addAttributeParams ($ attributeRow ['attribute_set_name ' ], $ attribute , $ attribute );
337+ }
338+ }
339+ foreach (array_keys ($ this ->_attributes ) as $ setName ) {
340+ foreach ($ this ->_forcedAttributesCodes as $ code ) {
341+ $ attributeId = self ::$ attributeCodeToId [$ code ] ?? null ;
342+ if (null === $ attributeId ) {
343+ continue ;
344+ }
345+ if (isset ($ this ->_attributes [$ setName ][$ code ])) {
346+ continue ;
347+ }
348+ $ attribute = self ::$ commonAttributesCache [$ attributeId ] ?? null ;
349+ if (!$ attribute ) {
350+ continue ;
351+ }
352+ $ this ->_addAttributeParams ($ setName , $ attribute , $ attribute );
305353 }
306354 }
307355 return $ this ;
308356 }
309357
310358 /**
311- * Attach Attributes By Id
359+ * Attach Attributes By Id and _forcedAttributesCodes
312360 *
313361 * @param string $attributeSetName
314362 * @param array $attributeIds
315363 * @return void
364+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
365+ * @deprecated use attachAttributesByOnlyId and attachAttributesByForcedCodes
366+ * @see attachAttributesByOnlyId() and attachAttributesByForcedCodes()
316367 */
317368 protected function attachAttributesById ($ attributeSetName , $ attributeIds )
318369 {
319370 foreach ($ this ->_prodAttrColFac ->create ()->addFieldToFilter (
320371 ['main_table.attribute_id ' , 'main_table.attribute_code ' ],
321- [
322- ['in ' => $ attributeIds ],
323- ['in ' => $ this ->_forcedAttributesCodes ]
324- ]
372+ [['in ' => $ attributeIds ], ['in ' => $ this ->_forcedAttributesCodes ]]
325373 ) as $ attribute ) {
326- $ attributeCode = $ attribute -> getAttributeCode ( );
327- $ attributeId = $ attribute -> getId ();
328-
329- if ( $ attribute -> getIsVisible () || in_array ( $ attributeCode , $ this -> _forcedAttributesCodes )) {
330- if (! isset ( self :: $ commonAttributesCache [ $ attributeId ])) {
331- $ defaultValue = $ attribute -> getDefaultValue ();
332- self :: $ commonAttributesCache [ $ attributeId ] = [
333- ' id ' => $ attributeId ,
334- ' code ' => $ attributeCode ,
335- ' is_global ' => $ attribute -> getIsGlobal (),
336- ' is_required ' => $ attribute -> getIsRequired (),
337- ' is_unique ' => $ attribute -> getIsUnique (),
338- ' frontend_label ' => $ attribute -> getFrontendLabel (),
339- ' is_static ' => $ attribute -> isStatic (),
340- ' apply_to ' => $ attribute -> getApplyTo () ,
341- ' type ' => \ Magento \ ImportExport \ Model \Import:: getAttributeType ( $ attribute ),
342- ' default_value ' => ( is_string ( $ defaultValue ) && strlen ( $ defaultValue )) ?
343- $ attribute -> getDefaultValue () : null ,
344- ' options ' => $ this -> _entityModel -> getAttributeOptions (
345- $ attribute ,
346- $ this -> _indexValueAttributes
347- ),
348- ] ;
349- }
374+ $ this -> attachAttribute ( $ attribute );
375+ }
376+ }
377+
378+ /**
379+ * Attach Attributes By Id
380+ *
381+ * @param array $attributeIds
382+ * @return array
383+ */
384+ private function attachAttributesByOnlyId ( array $ attributeIds ) : array
385+ {
386+ $ addedAttributes = [];
387+ foreach ( $ this -> _prodAttrColFac -> create ()-> addFieldToFilter (
388+ [ ' main_table.attribute_id ' ] ,
389+ [[ ' in ' => $ attributeIds ]]
390+ ) as $ attribute ) {
391+ $ cachedAttribute = $ this -> attachAttribute ( $ attribute );
392+ if ( null !== $ cachedAttribute ) {
393+ $ addedAttributes [] = $ cachedAttribute ;
394+ }
395+ }
396+ return $ addedAttributes ;
397+ }
350398
399+ /**
400+ * Attach Attributes By _forcedAttributesCodes
401+ *
402+ * @return array
403+ */
404+ private function attachAttributesByForcedCodes () : array
405+ {
406+ $ addedAttributes = [];
407+ foreach ($ this ->_prodAttrColFac ->create ()->addFieldToFilter (
408+ ['main_table.attribute_code ' ],
409+ [['in ' => $ this ->_forcedAttributesCodes ]]
410+ ) as $ attribute ) {
411+ $ cachedAttribute = $ this ->attachAttribute ($ attribute );
412+ if (null !== $ cachedAttribute ) {
413+ $ addedAttributes [] = $ cachedAttribute ;
414+ }
415+ }
416+ return $ addedAttributes ;
417+ }
418+
419+ /**
420+ * Attach Attribute to self::$commonAttributesCache or self::$invAttributesCache
421+ *
422+ * @param Attribute $attribute
423+ * @return array|null
424+ */
425+ private function attachAttribute (Attribute $ attribute )
426+ {
427+ $ cachedAttribute = null ;
428+ $ attributeCode = $ attribute ->getAttributeCode ();
429+ $ attributeId = $ attribute ->getId ();
430+ if ($ attribute ->getIsVisible () || in_array ($ attributeCode , $ this ->_forcedAttributesCodes )) {
431+ if (!isset (self ::$ commonAttributesCache [$ attributeId ])) {
432+ $ defaultValue = $ attribute ->getDefaultValue ();
433+ $ cachedAttribute = [
434+ 'id ' => $ attributeId ,
435+ 'code ' => $ attributeCode ,
436+ 'is_global ' => $ attribute ->getIsGlobal (),
437+ 'is_required ' => $ attribute ->getIsRequired (),
438+ 'is_unique ' => $ attribute ->getIsUnique (),
439+ 'frontend_label ' => $ attribute ->getFrontendLabel (),
440+ 'is_static ' => $ attribute ->isStatic (),
441+ 'apply_to ' => $ attribute ->getApplyTo (),
442+ 'type ' => \Magento \ImportExport \Model \Import::getAttributeType ($ attribute ),
443+ 'default_value ' => (is_string ($ defaultValue ) && strlen ($ defaultValue )) ?
444+ $ attribute ->getDefaultValue () : null ,
445+ 'options ' => [],
446+ ];
447+ $ sourceModel = $ attribute ->getSourceModel ();
448+ if (Table::class === $ sourceModel ) {
449+ $ cachedAttribute ['options_use_table ' ] = true ;
450+ } else {
451+ $ cachedAttribute ['options ' ] = $ this ->_entityModel ->getAttributeOptions (
452+ $ attribute ,
453+ $ this ->_indexValueAttributes
454+ );
455+ }
456+ self ::$ commonAttributesCache [$ attributeId ] = $ cachedAttribute ;
351457 self ::$ attributeCodeToId [$ attributeCode ] = $ attributeId ;
352- $ this ->_addAttributeParams (
353- $ attributeSetName ,
354- self ::$ commonAttributesCache [$ attributeId ],
355- $ attribute
356- );
357- } else {
358- self ::$ invAttributesCache [] = $ attributeId ;
359458 }
459+ } else {
460+ self ::$ invAttributesCache [] = $ attributeId ;
360461 }
462+ return $ cachedAttribute ;
361463 }
362464
363465 /**
@@ -524,7 +626,6 @@ public function isSuitable()
524626 public function prepareAttributesWithDefaultValueForSave (array $ rowData , $ withDefaultValue = true )
525627 {
526628 $ resultAttrs = [];
527-
528629 foreach ($ this ->_getProductAttributes ($ rowData ) as $ attrCode => $ attrParams ) {
529630 if ($ attrParams ['is_static ' ]) {
530631 continue ;
@@ -548,7 +649,6 @@ public function prepareAttributesWithDefaultValueForSave(array $rowData, $withDe
548649 $ resultAttrs [$ attrCode ] = $ attrParams ['default_value ' ];
549650 }
550651 }
551-
552652 return $ resultAttrs ;
553653 }
554654
0 commit comments