Skip to content

Commit a269519

Browse files
committed
Refactoring: Extract Link Processing Logic to own Class "LinkProcessor"
1 parent b5b66fe commit a269519

File tree

2 files changed

+297
-184
lines changed

2 files changed

+297
-184
lines changed

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

Lines changed: 14 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Catalog\Model\Product\Visibility;
1212
use Magento\Catalog\Model\ResourceModel\Product\Link;
1313
use Magento\CatalogImportExport\Model\Import\Product\ImageTypeProcessor;
14+
use Magento\CatalogImportExport\Model\Import\Product\LinkProcessor;
1415
use Magento\CatalogImportExport\Model\Import\Product\MediaGalleryProcessor;
1516
use Magento\CatalogImportExport\Model\Import\Product\RowValidatorInterface as ValidatorInterface;
1617
use Magento\CatalogImportExport\Model\StockItemImporterInterface;
@@ -742,6 +743,11 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
742743
*/
743744
private $productRepository;
744745

746+
/**
747+
* @var LinkProcessor
748+
*/
749+
private $linkProcessor;
750+
745751
/**
746752
* @param \Magento\Framework\Json\Helper\Data $jsonHelper
747753
* @param \Magento\ImportExport\Helper\Data $importExportData
@@ -787,6 +793,7 @@ class Product extends \Magento\ImportExport\Model\Import\Entity\AbstractEntity
787793
* @param StockItemImporterInterface|null $stockItemImporter
788794
* @param DateTimeFactory $dateTimeFactory
789795
* @param ProductRepositoryInterface|null $productRepository
796+
* @oaram LinkProcessor|null $linkProcessor
790797
* @throws LocalizedException
791798
* @throws \Magento\Framework\Exception\FileSystemException
792799
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
@@ -836,7 +843,8 @@ public function __construct(
836843
MediaGalleryProcessor $mediaProcessor = null,
837844
StockItemImporterInterface $stockItemImporter = null,
838845
DateTimeFactory $dateTimeFactory = null,
839-
ProductRepositoryInterface $productRepository = null
846+
ProductRepositoryInterface $productRepository = null,
847+
LinkProcessor $linkProcessor = null
840848
) {
841849
$this->_eventManager = $eventManager;
842850
$this->stockRegistry = $stockRegistry;
@@ -872,6 +880,8 @@ public function __construct(
872880
$this->mediaProcessor = $mediaProcessor ?: ObjectManager::getInstance()->get(MediaGalleryProcessor::class);
873881
$this->stockItemImporter = $stockItemImporter ?: ObjectManager::getInstance()
874882
->get(StockItemImporterInterface::class);
883+
$this->linkProcessor = $linkProcessor ?? ObjectManager::getInstance()
884+
->get(LinkProcessor::class);
875885
parent::__construct(
876886
$jsonHelper,
877887
$importExportData,
@@ -1248,30 +1258,13 @@ protected function _prepareRowForDb(array $rowData)
12481258
*
12491259
* Must be called after ALL products saving done.
12501260
*
1261+
* @deprecated use linkProcessor Directly
1262+
*
12511263
* @return $this
12521264
*/
12531265
protected function _saveLinks()
12541266
{
1255-
/** @var Link $resource */
1256-
$resource = $this->_linkFactory->create();
1257-
$mainTable = $resource->getMainTable();
1258-
$positionAttrId = [];
1259-
$nextLinkId = $this->_resourceHelper->getNextAutoincrement($mainTable);
1260-
1261-
// pre-load 'position' attributes ID for each link type once
1262-
foreach ($this->_linkNameToId as $linkId) {
1263-
$select = $this->_connection->select()->from(
1264-
$resource->getTable('catalog_product_link_attribute'),
1265-
['id' => 'product_link_attribute_id']
1266-
)->where(
1267-
'link_type_id = :link_id AND product_link_attribute_code = :position'
1268-
);
1269-
$bind = [':link_id' => $linkId, ':position' => 'position'];
1270-
$positionAttrId[$linkId] = $this->_connection->fetchOne($select, $bind);
1271-
}
1272-
while ($bunch = $this->_dataSourceModel->getNextBunch()) {
1273-
$this->processLinkBunches($bunch, $resource, $nextLinkId, $positionAttrId);
1274-
}
1267+
$this->linkProcessor->saveLinks($this, $this->_dataSourceModel, $this->getProductEntityLinkField());
12751268
return $this;
12761269
}
12771270

@@ -3034,167 +3027,4 @@ private function getValidationErrorLevel($sku): string
30343027
? ProcessingError::ERROR_LEVEL_CRITICAL
30353028
: ProcessingError::ERROR_LEVEL_NOT_CRITICAL;
30363029
}
3037-
3038-
/**
3039-
* Processes link bunches
3040-
*
3041-
* @param array $bunch
3042-
* @param Link $resource
3043-
* @param int $nextLinkId
3044-
* @param array $positionAttrId
3045-
* @return void
3046-
*/
3047-
private function processLinkBunches(
3048-
array $bunch,
3049-
Link $resource,
3050-
int $nextLinkId,
3051-
array $positionAttrId
3052-
): void {
3053-
$productIds = [];
3054-
$linkRows = [];
3055-
$positionRows = [];
3056-
3057-
$bunch = array_filter($bunch, [$this, 'isRowAllowedToImport'], ARRAY_FILTER_USE_BOTH);
3058-
foreach ($bunch as $rowData) {
3059-
$sku = $rowData[self::COL_SKU];
3060-
$productId = $this->skuProcessor->getNewSku($sku)[$this->getProductEntityLinkField()];
3061-
$productIds[] = $productId;
3062-
$productLinkKeys = $this->fetchProductLinks($resource, $productId);
3063-
$linkNameToId = array_filter(
3064-
$this->_linkNameToId,
3065-
function ($linkName) use ($rowData) {
3066-
return isset($rowData[$linkName . 'sku']);
3067-
},
3068-
ARRAY_FILTER_USE_KEY
3069-
);
3070-
foreach ($linkNameToId as $linkName => $linkId) {
3071-
$linkSkus = explode($this->getMultipleValueSeparator(), $rowData[$linkName . 'sku']);
3072-
$linkPositions = !empty($rowData[$linkName . 'position'])
3073-
? explode($this->getMultipleValueSeparator(), $rowData[$linkName . 'position'])
3074-
: [];
3075-
3076-
$linkSkus = array_filter(
3077-
$linkSkus,
3078-
function ($linkedSku) use ($sku) {
3079-
$linkedSku = trim($linkedSku);
3080-
return ($this->skuProcessor->getNewSku($linkedSku) !== null || $this->isSkuExist($linkedSku))
3081-
&& strcasecmp($linkedSku, $sku) !== 0;
3082-
}
3083-
);
3084-
foreach ($linkSkus as $linkedKey => $linkedSku) {
3085-
$linkedId = $this->getProductLinkedId($linkedSku);
3086-
if ($linkedId == null) {
3087-
// Import file links to a SKU which is skipped for some reason, which leads to a "NULL"
3088-
// link causing fatal errors.
3089-
$formatStr = 'WARNING: Orphaned link skipped: From SKU %s (ID %d) to SKU %s, Link type id: %d';
3090-
$exception = new \Exception(sprintf($formatStr, $sku, $productId, $linkedSku, $linkId));
3091-
$this->_logger->critical($exception);
3092-
continue;
3093-
}
3094-
$linkKey = $this->composeLinkKey($productId, $linkedId, $linkId);
3095-
$productLinkKeys[$linkKey] = $productLinkKeys[$linkKey] ?? $nextLinkId;
3096-
3097-
$linkRows[$linkKey] = $linkRows[$linkKey] ?? [
3098-
'link_id' => $productLinkKeys[$linkKey],
3099-
'product_id' => $productId,
3100-
'linked_product_id' => $linkedId,
3101-
'link_type_id' => $linkId,
3102-
];
3103-
3104-
if (!empty($linkPositions[$linkedKey])) {
3105-
$positionRows[] = [
3106-
'link_id' => $productLinkKeys[$linkKey],
3107-
'product_link_attribute_id' => $positionAttrId[$linkId],
3108-
'value' => $linkPositions[$linkedKey],
3109-
];
3110-
}
3111-
$nextLinkId++;
3112-
}
3113-
}
3114-
}
3115-
$this->saveLinksData($resource, $productIds, $linkRows, $positionRows);
3116-
}
3117-
3118-
/**
3119-
* Fetches Product Links
3120-
*
3121-
* @param Link $resource
3122-
* @param int $productId
3123-
* @return array
3124-
*/
3125-
private function fetchProductLinks(Link $resource, int $productId) : array
3126-
{
3127-
$productLinkKeys = [];
3128-
$select = $this->_connection->select()->from(
3129-
$resource->getTable('catalog_product_link'),
3130-
['id' => 'link_id', 'linked_id' => 'linked_product_id', 'link_type_id' => 'link_type_id']
3131-
)->where(
3132-
'product_id = :product_id'
3133-
);
3134-
$bind = [':product_id' => $productId];
3135-
foreach ($this->_connection->fetchAll($select, $bind) as $linkData) {
3136-
$linkKey = $this->composeLinkKey($productId, $linkData['linked_id'], $linkData['link_type_id']);
3137-
$productLinkKeys[$linkKey] = $linkData['id'];
3138-
}
3139-
3140-
return $productLinkKeys;
3141-
}
3142-
3143-
/**
3144-
* Gets the Id of the Sku
3145-
*
3146-
* @param string $linkedSku
3147-
* @return int|null
3148-
*/
3149-
private function getProductLinkedId(string $linkedSku) : ?int
3150-
{
3151-
$linkedSku = trim($linkedSku);
3152-
$newSku = $this->skuProcessor->getNewSku($linkedSku);
3153-
$linkedId = !empty($newSku) ? $newSku['entity_id'] : $this->getExistingSku($linkedSku)['entity_id'];
3154-
return $linkedId;
3155-
}
3156-
3157-
/**
3158-
* Saves information about product links
3159-
*
3160-
* @param Link $resource
3161-
* @param array $productIds
3162-
* @param array $linkRows
3163-
* @param array $positionRows
3164-
* @throws LocalizedException
3165-
*/
3166-
private function saveLinksData(Link $resource, array $productIds, array $linkRows, array $positionRows)
3167-
{
3168-
$mainTable = $resource->getMainTable();
3169-
if (Import::BEHAVIOR_APPEND != $this->getBehavior() && $productIds) {
3170-
$this->_connection->delete(
3171-
$mainTable,
3172-
$this->_connection->quoteInto('product_id IN (?)', array_unique($productIds))
3173-
);
3174-
}
3175-
if ($linkRows) {
3176-
$this->_connection->insertOnDuplicate($mainTable, $linkRows, ['link_id']);
3177-
}
3178-
if ($positionRows) {
3179-
// process linked product positions
3180-
$this->_connection->insertOnDuplicate(
3181-
$resource->getAttributeTypeTable('int'),
3182-
$positionRows,
3183-
['value']
3184-
);
3185-
}
3186-
}
3187-
3188-
/**
3189-
* Composes the link key
3190-
*
3191-
* @param int $productId
3192-
* @param int $linkedId
3193-
* @param int $linkTypeId
3194-
* @return string
3195-
*/
3196-
private function composeLinkKey(int $productId, int $linkedId, int $linkTypeId) : string
3197-
{
3198-
return "{$productId}-{$linkedId}-{$linkTypeId}";
3199-
}
32003030
}

0 commit comments

Comments
 (0)