Skip to content

Commit dd8ed67

Browse files
ACPT-490: Catalog Import attributes - bulk load options
1 parent 2e45de7 commit dd8ed67

File tree

2 files changed

+147
-45
lines changed

2 files changed

+147
-45
lines changed

app/code/Magento/CatalogImportExport/Model/Import/Product/Type/AbstractType.php

Lines changed: 146 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
*/
66
namespace Magento\CatalogImportExport\Model\Import\Product\Type;
77

8-
use Magento\Framework\App\ResourceConnection;
8+
use Magento\Catalog\Api\Data\ProductAttributeInterface;
99
use 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;
1114
use 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
}
@@ -284,35 +294,71 @@ protected function _initAttributes()
284294
$absentKeys[$attributeRow['attribute_set_name']][] = $attributeRow['attribute_id'];
285295
}
286296
}
297+
$addedAttributes = [];
287298
foreach ($absentKeys as $attributeSetName => $attributeIds) {
288299
$unknownAttributeIds = array_diff(
289300
$attributeIds,
290301
array_keys(self::$commonAttributesCache),
291302
self::$invAttributesCache
292303
);
293-
if ($unknownAttributeIds || $this->_forcedAttributesCodes) {
294-
$this->attachAttributesById($attributeSetName, $attributeIds);
304+
if ($unknownAttributeIds) {
305+
$addedAttributes[] = $this->attachAttributesByOnlyId($attributeSetName, $unknownAttributeIds);
306+
}
307+
if ($this->_forcedAttributesCodes) {
308+
$addedAttributes[] = $this->attachAttributesByForcedCodes($attributeSetName);
309+
}
310+
}
311+
$addedAttributes = array_merge(...$addedAttributes);
312+
$attributesToLoadFromTable = [];
313+
foreach ($addedAttributes as $addedAttribute) {
314+
if (isset($addedAttribute['options_use_table'])) {
315+
$attributesToLoadFromTable[] = $addedAttribute['id'];
316+
unset(self::$commonAttributesCache[$addedAttribute['id']]['options_use_table']);
317+
}
318+
}
319+
if (!empty($attributesToLoadFromTable)) {
320+
$collection = $this->attributeOptionCollectionFactory->create();
321+
$collection->setAttributeFilter(['in' => $attributesToLoadFromTable]);
322+
$collection->setStoreFilter(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
323+
foreach($collection as $option) {
324+
$attributeId = $option->getAttributeId();
325+
$value = strtolower($option->getValue());
326+
self::$commonAttributesCache[$attributeId]['options'][$value] = $option->getOptionId();
295327
}
296328
}
297329
foreach ($entityAttributes as $attributeRow) {
298330
if (isset(self::$commonAttributesCache[$attributeRow['attribute_id']])) {
299331
$attribute = self::$commonAttributesCache[$attributeRow['attribute_id']];
300-
$this->_addAttributeParams(
301-
$attributeRow['attribute_set_name'],
302-
self::$commonAttributesCache[$attributeRow['attribute_id']],
303-
$attribute
304-
);
332+
$this->_addAttributeParams($attributeRow['attribute_set_name'], $attribute, $attribute);
333+
}
334+
}
335+
foreach (array_keys($this->_attributes) as $setName) {
336+
foreach ($this->_forcedAttributesCodes as $code) {
337+
$attributeId = self::$attributeCodeToId[$code] ?? null;
338+
if (null === $attributeId) {
339+
continue;
340+
}
341+
if (isset($this->_attributes[$setName][$code])) {
342+
continue;
343+
}
344+
$attribute = self::$commonAttributesCache[$attributeId] ?? null;
345+
if (!$attribute) {
346+
continue;
347+
}
348+
$this->_addAttributeParams($setName, $attribute, $attribute);
305349
}
306350
}
307351
return $this;
308352
}
309353

310354
/**
311-
* Attach Attributes By Id
355+
* Attach Attributes By Id and _forcedAttributesCodes
312356
*
313357
* @param string $attributeSetName
314358
* @param array $attributeIds
315359
* @return void
360+
* @deprecated use attachAttributesOnlyById and attachAttributesByForcedCodes
361+
* @see attachAttributesOnlyById() and attachAttributesByForcedCodes()
316362
*/
317363
protected function attachAttributesById($attributeSetName, $attributeIds)
318364
{
@@ -323,41 +369,97 @@ protected function attachAttributesById($attributeSetName, $attributeIds)
323369
['in' => $this->_forcedAttributesCodes]
324370
]
325371
) 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-
}
372+
$this->attachAttribute($attributeSetName, $attribute);
373+
}
374+
}
350375

376+
/**
377+
* Attach Attributes By Id
378+
*
379+
* @param string $attributeSetName
380+
* @param array $attributeIds
381+
* @return array
382+
*/
383+
private function attachAttributesByOnlyId(string $attributeSetName, array $attributeIds) : array
384+
{
385+
$addedAttributes = [];
386+
foreach ($this->_prodAttrColFac->create()->addFieldToFilter(
387+
['main_table.attribute_id', 'main_table.attribute_code'],
388+
[['in' => $attributeIds]]
389+
) as $attribute) {
390+
$cachedAttribute = $this->attachAttribute($attributeSetName, $attribute);
391+
if (null !== $cachedAttribute) {
392+
$addedAttributes[] = $cachedAttribute;
393+
}
394+
}
395+
return $addedAttributes;
396+
}
397+
398+
/**
399+
* Attach Attributes By _forcedAttributesCodes
400+
*
401+
* @param string $attributeSetName
402+
* @return array
403+
*/
404+
private function attachAttributesByForcedCodes(string $attributeSetName) : 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($attributeSetName, $attribute);
412+
if (null !== $cachedAttribute) {
413+
$addedAttributes[] = $cachedAttribute;
414+
}
415+
}
416+
return $addedAttributes;
417+
}
418+
419+
/**
420+
* Attach Attributes By Id
421+
*
422+
* @param string $attributeSetName
423+
* @param ProductAttributeInterface $attribute
424+
* @return array|null
425+
*/
426+
private function attachAttribute(string $attributeSetName, ProductAttributeInterface $attribute) {
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
/**

app/code/Magento/ImportExport/Model/Import/Entity/AbstractEntity.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ public function getAttributeOptions(
515515
// merge global entity index value attributes
516516
$indexValAttrs = array_merge($indexValAttrs, $this->_indexValueAttributes);
517517

518-
// should attribute has index (option value) instead of a label?
518+
// should attribute have index (option value) instead of a label?
519519
$index = in_array($attribute->getAttributeCode(), $indexValAttrs) ? 'value' : 'label';
520520

521521
// only default (admin) store values used

0 commit comments

Comments
 (0)